build: 增加iec61850bean源码
parent
4eb486e7ed
commit
830ef69c1d
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.josistack.AcseAssociation;
|
||||
import com.beanit.josistack.AcseAssociationListener;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
final class AcseListener implements AcseAssociationListener {
|
||||
|
||||
ServerSap serverSap;
|
||||
|
||||
AcseListener(ServerSap serverSap) {
|
||||
this.serverSap = serverSap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionIndication(AcseAssociation acseAssociation, ByteBuffer psdu) {
|
||||
serverSap.connectionIndication(acseAssociation, psdu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serverStoppedListeningIndication(IOException e) {
|
||||
serverSap.serverStoppedListeningIndication(e);
|
||||
}
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeSpecification;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned32;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An Array can contain up to n instances of one and the same DataObject, ConstructedDataAttribute,
|
||||
* or BasicDataAttribute. The children of the array have the name that equals the index in the array
|
||||
* (e.g. "0","1" etc.)
|
||||
*
|
||||
* @author Stefan Feuerhahn
|
||||
*/
|
||||
public final class Array extends FcModelNode {
|
||||
|
||||
private final List<ModelNode> items;
|
||||
|
||||
/**
|
||||
* Creates an array object.
|
||||
*
|
||||
* @param objectReference the reference of the array
|
||||
* @param fc the functional constraint of the array
|
||||
* @param children the children of the array
|
||||
*/
|
||||
public Array(ObjectReference objectReference, Fc fc, List<FcModelNode> children) {
|
||||
this.objectReference = objectReference;
|
||||
this.fc = fc;
|
||||
items = new ArrayList<>(children.size());
|
||||
for (ModelNode child : children) {
|
||||
items.add(child);
|
||||
child.setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModelNode> getChildren() {
|
||||
return new ArrayList<>(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ModelNode> iterator() {
|
||||
return items.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelNode getChild(String childName, Fc fc) {
|
||||
return items.get(Integer.parseInt(childName));
|
||||
}
|
||||
|
||||
public ModelNode getChild(int index) {
|
||||
return items.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelNode copy() {
|
||||
List<FcModelNode> itemsCopy = new ArrayList<>(items.size());
|
||||
for (ModelNode item : items) {
|
||||
itemsCopy.add((FcModelNode) item.copy());
|
||||
}
|
||||
return new Array(objectReference, fc, itemsCopy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BasicDataAttribute> getBasicDataAttributes() {
|
||||
List<BasicDataAttribute> subBasicDataAttributes = new ArrayList<>();
|
||||
for (ModelNode item : items) {
|
||||
subBasicDataAttributes.addAll(item.getBasicDataAttributes());
|
||||
}
|
||||
return subBasicDataAttributes;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return items.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
|
||||
Data.Array dataArray = new Data.Array();
|
||||
List<Data> arrayDataList = dataArray.getData();
|
||||
|
||||
for (ModelNode modelNode : items) {
|
||||
Data mmsArrayItem = modelNode.getMmsDataObj();
|
||||
if (mmsArrayItem == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to convert Child: " + modelNode.objectReference + " to MMS Data Object.");
|
||||
}
|
||||
arrayDataList.add(mmsArrayItem);
|
||||
}
|
||||
|
||||
if (arrayDataList.size() == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Converting ModelNode: "
|
||||
+ objectReference
|
||||
+ " to MMS Data Object resulted in Sequence of size zero.");
|
||||
}
|
||||
|
||||
Data data = new Data();
|
||||
data.setArray(dataArray);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getArray() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: array");
|
||||
}
|
||||
if (data.getArray().getData().size() != items.size()) {
|
||||
throw new ServiceError(
|
||||
ServiceError.TYPE_CONFLICT, "expected type: array with " + children.size() + " elements");
|
||||
}
|
||||
|
||||
Iterator<Data> iterator = data.getArray().getData().iterator();
|
||||
for (ModelNode child : items) {
|
||||
child.setValueFromMmsDataObj(iterator.next());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
|
||||
TypeSpecification elementType = new TypeSpecification();
|
||||
elementType.setTypeDescription(items.get(0).getMmsTypeSpec());
|
||||
|
||||
TypeDescription.Array array = new TypeDescription.Array();
|
||||
array.setNumberOfElements(new Unsigned32(items.size()));
|
||||
array.setElementType(elementType);
|
||||
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setArray(array);
|
||||
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getReference().toString()).append(" [").append(fc).append("]");
|
||||
for (ModelNode childNode : items) {
|
||||
sb.append("\n");
|
||||
sb.append(childNode.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class BasicDataAttribute extends FcModelNode {
|
||||
|
||||
final List<Urcb> chgRcbs;
|
||||
final List<Urcb> dupdRcbs;
|
||||
BasicDataAttribute mirror;
|
||||
/** attribute value type */
|
||||
BdaType basicType = null;
|
||||
/** short address, can be used by SCSM and for local data mapping */
|
||||
String sAddr = null;
|
||||
|
||||
boolean dchg;
|
||||
boolean qchg;
|
||||
boolean dupd;
|
||||
|
||||
protected BasicDataAttribute(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
this.objectReference = objectReference;
|
||||
this.fc = fc;
|
||||
this.sAddr = sAddr;
|
||||
this.dchg = dchg;
|
||||
this.dupd = dupd;
|
||||
|
||||
if (dchg) {
|
||||
chgRcbs = new ArrayList<>();
|
||||
} else {
|
||||
chgRcbs = null;
|
||||
}
|
||||
if (dupd) {
|
||||
dupdRcbs = new ArrayList<>();
|
||||
} else {
|
||||
dupdRcbs = null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getDchg() {
|
||||
return dchg;
|
||||
}
|
||||
|
||||
public boolean getDupd() {
|
||||
return dupd;
|
||||
}
|
||||
|
||||
public boolean getQchg() {
|
||||
return dupd;
|
||||
}
|
||||
|
||||
public BdaType getBasicType() {
|
||||
return basicType;
|
||||
}
|
||||
|
||||
public String getSAddr() {
|
||||
return sAddr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelNode getChild(String childName, Fc fc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelNode getChild(String childName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModelNode> getChildren() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ModelNode> iterator() {
|
||||
return Collections.emptyIterator();
|
||||
}
|
||||
|
||||
public abstract void setDefault();
|
||||
|
||||
@Override
|
||||
public List<BasicDataAttribute> getBasicDataAttributes() {
|
||||
List<BasicDataAttribute> subBasicDataAttributes = new ArrayList<>();
|
||||
subBasicDataAttributes.add(this);
|
||||
return subBasicDataAttributes;
|
||||
}
|
||||
|
||||
public abstract void setValueFrom(BasicDataAttribute bda);
|
||||
|
||||
void setMirror(BasicDataAttribute bda) {
|
||||
mirror = bda;
|
||||
}
|
||||
|
||||
public String getValueString() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerBitString;
|
||||
import com.beanit.iec61850bean.internal.HexString;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Integer32;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
|
||||
public abstract class BdaBitString extends BasicDataAttribute {
|
||||
|
||||
final int maxNumBits;
|
||||
volatile byte[] value;
|
||||
|
||||
protected BdaBitString(
|
||||
ObjectReference objectReference,
|
||||
Fc fc,
|
||||
String sAddr,
|
||||
int maxNumBits,
|
||||
boolean dchg,
|
||||
boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
this.maxNumBits = maxNumBits;
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
if (value.length != ((maxNumBits - 1) / 8 + 1)) {
|
||||
throw new IllegalArgumentException("value does not have correct length.");
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
byte[] srcValue = ((BdaBitString) bda).getValue();
|
||||
if (value.length != srcValue.length) {
|
||||
value = new byte[srcValue.length];
|
||||
}
|
||||
System.arraycopy(srcValue, 0, value, 0, srcValue.length);
|
||||
}
|
||||
|
||||
public int getMaxNumBits() {
|
||||
return maxNumBits;
|
||||
}
|
||||
|
||||
/** Initializes BIT_STRING with all zeros */
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[(maxNumBits - 1) / 8 + 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setBitString(new BerBitString(value, maxNumBits));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getBitString() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: bit_string");
|
||||
}
|
||||
if (data.getBitString().numBits > maxNumBits) {
|
||||
throw new ServiceError(
|
||||
ServiceError.TYPE_CONFLICT,
|
||||
objectReference
|
||||
+ ": bit_string is bigger than type's size: "
|
||||
+ data.getBitString().numBits
|
||||
+ ">"
|
||||
+ maxNumBits);
|
||||
}
|
||||
value = data.getBitString().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setBitString(new Integer32(maxNumBits * -1));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + HexString.fromBytes(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return HexString.fromBytes(value);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerNull;
|
||||
import com.beanit.iec61850bean.internal.BerBoolean;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
|
||||
public final class BdaBoolean extends BasicDataAttribute {
|
||||
|
||||
private volatile boolean value;
|
||||
|
||||
public BdaBoolean(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.BOOLEAN;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaBoolean) bda).getValue();
|
||||
}
|
||||
|
||||
public boolean getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaBoolean copy() {
|
||||
BdaBoolean copy = new BdaBoolean(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setBool(new BerBoolean(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getBool() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: boolean");
|
||||
}
|
||||
value = data.getBool().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setBool(new BerNull());
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
/** Check packed list according to 61850-7-2 */
|
||||
public final class BdaCheck extends BdaBitString {
|
||||
|
||||
public BdaCheck(ObjectReference objectReference) {
|
||||
super(objectReference, Fc.CO, null, 2, false, false);
|
||||
basicType = BdaType.CHECK;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
public boolean getSynchrocheck() {
|
||||
return ((value[0] & 0x80) == 0x80);
|
||||
}
|
||||
|
||||
public void setSynchrocheck(boolean synchrocheck) {
|
||||
if (synchrocheck) {
|
||||
value[0] = (byte) (value[0] | 0x80);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0x7f);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getInterlockCheck() {
|
||||
return ((value[0] & 0x40) == 0x40);
|
||||
}
|
||||
|
||||
public void setInterlockCheck(boolean interlockCheck) {
|
||||
if (interlockCheck) {
|
||||
value[0] = (byte) (value[0] | 0x40);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xbf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaCheck copy() {
|
||||
BdaCheck copy = new BdaCheck(objectReference);
|
||||
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + String.format("0x%x", value[0]);
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class BdaDoubleBitPos extends BdaBitString {
|
||||
|
||||
public BdaDoubleBitPos(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, 2, dchg, dupd);
|
||||
basicType = BdaType.DOUBLE_BIT_POS;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
/** Sets the value to DoubleBitPos.OFF */
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[] {0x40};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaDoubleBitPos copy() {
|
||||
BdaDoubleBitPos copy = new BdaDoubleBitPos(objectReference, fc, sAddr, dchg, dupd);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public DoubleBitPos getDoubleBitPos() {
|
||||
|
||||
if ((value[0] & 0xC0) == 0xC0) {
|
||||
return DoubleBitPos.BAD_STATE;
|
||||
}
|
||||
|
||||
if ((value[0] & 0x80) == 0x80) {
|
||||
return DoubleBitPos.ON;
|
||||
}
|
||||
|
||||
if ((value[0] & 0x40) == 0x40) {
|
||||
return DoubleBitPos.OFF;
|
||||
}
|
||||
|
||||
return DoubleBitPos.INTERMEDIATE_STATE;
|
||||
}
|
||||
|
||||
public void setDoubleBitPos(DoubleBitPos doubleBitPos) {
|
||||
if (doubleBitPos == DoubleBitPos.BAD_STATE) {
|
||||
value[0] = (byte) 0xC0;
|
||||
} else if (doubleBitPos == DoubleBitPos.ON) {
|
||||
value[0] = (byte) 0x80;
|
||||
} else if (doubleBitPos == DoubleBitPos.OFF) {
|
||||
value[0] = (byte) 0x40;
|
||||
} else {
|
||||
value[0] = (byte) 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return getDoubleBitPos().toString();
|
||||
}
|
||||
|
||||
public enum DoubleBitPos {
|
||||
INTERMEDIATE_STATE(0),
|
||||
OFF(1),
|
||||
ON(2),
|
||||
BAD_STATE(3);
|
||||
private final int value;
|
||||
|
||||
DoubleBitPos(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getIntValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.iec61850bean.internal.BerBoolean;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TimeOfDay;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
|
||||
/**
|
||||
* BdaEntryTime stores time in terms of days and ms since 1984.
|
||||
*
|
||||
* @author Stefan Feuerhahn
|
||||
*/
|
||||
public final class BdaEntryTime extends BasicDataAttribute {
|
||||
|
||||
private volatile byte[] value;
|
||||
|
||||
public BdaEntryTime(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.ENTRY_TIME;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of this object to the given timestamp, where timestamp is the number of ms since
|
||||
* epoch 1970-01-01 00:00:00 UTC. Note that timestamps before 1984 are not valid as they cannot be
|
||||
* stored.
|
||||
*
|
||||
* @param timestamp the number of ms since epoch 1970-01-01
|
||||
*/
|
||||
public void setTimestamp(long timestamp) {
|
||||
long msSince1984 = timestamp - 441763200000l;
|
||||
int days = (int) (msSince1984 / 86400000);
|
||||
int ms = (int) (msSince1984 % 86400000);
|
||||
value =
|
||||
new byte[] {
|
||||
(byte) (ms >> 24),
|
||||
(byte) (ms >> 16),
|
||||
(byte) (ms >> 8),
|
||||
(byte) ms,
|
||||
(byte) (days >> 8),
|
||||
(byte) days
|
||||
};
|
||||
}
|
||||
|
||||
public long getTimestampValue() {
|
||||
if (value.length != 6) {
|
||||
return -1;
|
||||
}
|
||||
return (((value[0] & 0xffl) << 24)
|
||||
+ ((value[1] & 0xffl) << 16)
|
||||
+ ((value[2] & 0xffl) << 8)
|
||||
+ (value[3] & 0xffl)
|
||||
+ (((value[4] & 0xffl) << 8) + (value[5] & 0xffl)) * 86400000l)
|
||||
+ 441763200000l;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
byte[] srcValue = ((BdaEntryTime) bda).getValue();
|
||||
if (value.length != srcValue.length) {
|
||||
value = new byte[srcValue.length];
|
||||
}
|
||||
System.arraycopy(srcValue, 0, value, 0, srcValue.length);
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/** Sets EntryTime to byte[6] with all zeros */
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[6];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaEntryTime copy() {
|
||||
BdaEntryTime copy = new BdaEntryTime(objectReference, fc, sAddr, dchg, dupd);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
Data data = new Data();
|
||||
data.setBinaryTime(new TimeOfDay(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getBinaryTime() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: binary_time/EntryTime");
|
||||
}
|
||||
value = data.getBinaryTime().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setBinaryTime(new BerBoolean(true));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + getTimestampValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return "" + getTimestampValue();
|
||||
}
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.FloatingPoint;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public final class BdaFloat32 extends BasicDataAttribute {
|
||||
|
||||
private volatile byte[] value;
|
||||
|
||||
public BdaFloat32(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.FLOAT32;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
byte[] srcValue = ((BdaFloat32) bda).getValue();
|
||||
if (value.length != srcValue.length) {
|
||||
value = new byte[srcValue.length];
|
||||
}
|
||||
System.arraycopy(srcValue, 0, value, 0, srcValue.length);
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Float getFloat() {
|
||||
return Float.intBitsToFloat(
|
||||
((0xff & value[1]) << 24)
|
||||
| ((0xff & value[2]) << 16)
|
||||
| ((0xff & value[3]) << 8)
|
||||
| ((0xff & value[4]) << 0));
|
||||
}
|
||||
|
||||
public void setFloat(Float value) {
|
||||
this.value = ByteBuffer.allocate(1 + 4).put((byte) 8).putFloat(value).array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[] {8, 0, 0, 0, 0};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaFloat32 copy() {
|
||||
BdaFloat32 copy = new BdaFloat32(objectReference, fc, sAddr, dchg, dupd);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
Data data = new Data();
|
||||
data.setFloatingPoint(new FloatingPoint(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getFloatingPoint() == null || data.getFloatingPoint().value.length != 5) {
|
||||
throw new ServiceError(
|
||||
ServiceError.TYPE_CONFLICT, "expected type: floating_point as an octet string of size 5");
|
||||
}
|
||||
value = data.getFloatingPoint().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription.FloatingPoint floatingPointTypeDescription =
|
||||
new TypeDescription.FloatingPoint();
|
||||
floatingPointTypeDescription.setFormatWidth(new Unsigned8(32));
|
||||
floatingPointTypeDescription.setExponentWidth(new Unsigned8(8));
|
||||
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setFloatingPoint(floatingPointTypeDescription);
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + getFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return getFloat().toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.FloatingPoint;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class BdaFloat64 extends BasicDataAttribute {
|
||||
|
||||
private volatile byte[] value = new byte[] {11, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
public BdaFloat64(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.FLOAT64;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
byte[] srcValue = ((BdaFloat64) bda).getValue();
|
||||
if (value.length != srcValue.length) {
|
||||
value = new byte[srcValue.length];
|
||||
}
|
||||
System.arraycopy(srcValue, 0, value, 0, srcValue.length);
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
if (value != null && value.length != 9) {
|
||||
throw new IllegalArgumentException("value does not have length 9");
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Double getDouble() {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return Double.longBitsToDouble(
|
||||
((0xffL & value[1]) << 56)
|
||||
| ((0xffL & value[2]) << 48)
|
||||
| ((0xffL & value[3]) << 40)
|
||||
| ((0xffL & value[4]) << 32)
|
||||
| ((0xffL & value[5]) << 24)
|
||||
| ((0xffL & value[6]) << 16)
|
||||
| ((0xffL & value[7]) << 8)
|
||||
| ((0xffL & value[8]) << 0));
|
||||
}
|
||||
|
||||
public void setDouble(Double value) {
|
||||
this.value = ByteBuffer.allocate(1 + 8).put((byte) 11).putDouble(value).array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[] {11, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaFloat64 copy() {
|
||||
BdaFloat64 copy = new BdaFloat64(objectReference, fc, sAddr, dchg, dupd);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
Data data = new Data();
|
||||
data.setFloatingPoint(new FloatingPoint(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getFloatingPoint() == null || data.getFloatingPoint().value.length != 9) {
|
||||
throw new ServiceError(
|
||||
ServiceError.TYPE_CONFLICT, "expected type: floating_point as an octet string of size 9");
|
||||
}
|
||||
value = data.getFloatingPoint().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription.FloatingPoint floatingPointTypeDescription =
|
||||
new TypeDescription.FloatingPoint();
|
||||
floatingPointTypeDescription.setFormatWidth(new Unsigned8(64));
|
||||
floatingPointTypeDescription.setExponentWidth(new Unsigned8(11));
|
||||
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setFloatingPoint(floatingPointTypeDescription);
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + getDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return "" + Arrays.toString(value);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerInteger;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
|
||||
public final class BdaInt128 extends BasicDataAttribute {
|
||||
|
||||
private volatile long value;
|
||||
|
||||
public BdaInt128(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.INT128;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaInt128) bda).getValue();
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaInt128 copy() {
|
||||
BdaInt128 copy = new BdaInt128(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setInteger(new BerInteger(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getInteger() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: integer");
|
||||
}
|
||||
value = data.getInteger().value.longValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setInteger(new Unsigned8(128));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerInteger;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
|
||||
public final class BdaInt16 extends BasicDataAttribute {
|
||||
|
||||
private volatile short value;
|
||||
|
||||
public BdaInt16(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.INT16;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaInt16) bda).getValue();
|
||||
}
|
||||
|
||||
public short getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(short value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaInt16 copy() {
|
||||
BdaInt16 copy = new BdaInt16(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setInteger(new BerInteger(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getInteger() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: integer");
|
||||
}
|
||||
value = data.getInteger().value.shortValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setInteger(new Unsigned8(16));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerInteger;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
|
||||
public final class BdaInt16U extends BasicDataAttribute {
|
||||
|
||||
private volatile int value;
|
||||
|
||||
public BdaInt16U(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.INT16U;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaInt16U) bda).getValue();
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaInt16U copy() {
|
||||
BdaInt16U copy = new BdaInt16U(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setUnsigned(new BerInteger(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getUnsigned() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: unsigned");
|
||||
}
|
||||
value = data.getUnsigned().value.intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setUnsigned(new Unsigned8(16));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerInteger;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
|
||||
public final class BdaInt32 extends BasicDataAttribute {
|
||||
|
||||
private volatile int value;
|
||||
|
||||
public BdaInt32(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.INT32;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaInt32) bda).getValue();
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaInt32 copy() {
|
||||
BdaInt32 copy = new BdaInt32(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setInteger(new BerInteger(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getInteger() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: integer");
|
||||
}
|
||||
value = data.getInteger().value.intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setInteger(new Unsigned8(32));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerInteger;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
|
||||
public final class BdaInt32U extends BasicDataAttribute {
|
||||
|
||||
private volatile long value;
|
||||
|
||||
public BdaInt32U(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.INT32U;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaInt32U) bda).getValue();
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaInt32U copy() {
|
||||
BdaInt32U copy = new BdaInt32U(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setUnsigned(new BerInteger(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getUnsigned() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: unsigned");
|
||||
}
|
||||
value = data.getUnsigned().value.longValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setUnsigned(new Unsigned8(32));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerInteger;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
|
||||
public final class BdaInt64 extends BasicDataAttribute {
|
||||
|
||||
private volatile long value;
|
||||
|
||||
public BdaInt64(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.INT64;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaInt64) bda).getValue();
|
||||
}
|
||||
|
||||
public long getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaInt64 copy() {
|
||||
BdaInt64 copy = new BdaInt64(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setInteger(new BerInteger(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getInteger() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: integer");
|
||||
}
|
||||
value = data.getInteger().value.longValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setInteger(new Unsigned8(64));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerInteger;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
|
||||
public final class BdaInt8 extends BasicDataAttribute {
|
||||
|
||||
private volatile byte value;
|
||||
|
||||
public BdaInt8(ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.INT8;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaInt8) bda).getValue();
|
||||
}
|
||||
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaInt8 copy() {
|
||||
BdaInt8 copy = new BdaInt8(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setInteger(new BerInteger(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getInteger() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: integer");
|
||||
}
|
||||
value = data.getInteger().value.byteValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setInteger(new Unsigned8(8));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerInteger;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned8;
|
||||
|
||||
public final class BdaInt8U extends BasicDataAttribute {
|
||||
|
||||
private volatile short value;
|
||||
|
||||
public BdaInt8U(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.INT8U;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
value = ((BdaInt8U) bda).getValue();
|
||||
}
|
||||
|
||||
public short getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(short value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaInt8U copy() {
|
||||
BdaInt8U copy = new BdaInt8U(objectReference, fc, sAddr, dchg, dupd);
|
||||
copy.setValue(value);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setUnsigned(new BerInteger(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getUnsigned() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: unsigned");
|
||||
}
|
||||
value = data.getUnsigned().value.shortValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setUnsigned(new Unsigned8(8));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerOctetString;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Integer32;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class BdaOctetString extends BasicDataAttribute {
|
||||
|
||||
private final int maxLength;
|
||||
private volatile byte[] value;
|
||||
|
||||
public BdaOctetString(
|
||||
ObjectReference objectReference,
|
||||
Fc fc,
|
||||
String sAddr,
|
||||
int maxLength,
|
||||
boolean dchg,
|
||||
boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.OCTET_STRING;
|
||||
this.maxLength = maxLength;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
if (value != null && value.length > maxLength) {
|
||||
throw new IllegalArgumentException(
|
||||
"OCTET_STRING value size exceeds maxLength of " + maxLength);
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
byte[] srcValue = ((BdaOctetString) bda).getValue();
|
||||
if (value.length != srcValue.length) {
|
||||
value = new byte[srcValue.length];
|
||||
}
|
||||
System.arraycopy(srcValue, 0, value, 0, srcValue.length);
|
||||
}
|
||||
|
||||
public int getMaxLength() {
|
||||
return maxLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaOctetString copy() {
|
||||
BdaOctetString copy = new BdaOctetString(objectReference, fc, sAddr, maxLength, dchg, dupd);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setOctetString(new BerOctetString(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getOctetString() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: octet_string");
|
||||
}
|
||||
value = data.getOctetString().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setOctetString(new Integer32(maxLength * -1));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getReference().toString() + ": " + Arrays.toString(value);
|
||||
}
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class BdaOptFlds extends BdaBitString {
|
||||
|
||||
public BdaOptFlds(ObjectReference objectReference, Fc fc) {
|
||||
super(objectReference, fc, null, 10, false, false);
|
||||
basicType = BdaType.OPTFLDS;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
/* default of buffer overflow is true by default in IEC 61850-6 sec. 9.3.8 */
|
||||
value = new byte[] {0x02, 0x00};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaOptFlds copy() {
|
||||
BdaOptFlds copy = new BdaOptFlds(objectReference, fc);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public boolean isSequenceNumber() {
|
||||
return (value[0] & 0x40) == 0x40;
|
||||
}
|
||||
|
||||
public void setSequenceNumber(boolean sequenceNumber) {
|
||||
if (sequenceNumber) {
|
||||
value[0] = (byte) (value[0] | 0x40);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xbf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReportTimestamp() {
|
||||
return (value[0] & 0x20) == 0x20;
|
||||
}
|
||||
|
||||
public void setReportTimestamp(boolean reportTimestamp) {
|
||||
if (reportTimestamp) {
|
||||
value[0] = (byte) (value[0] | 0x20);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xdf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReasonForInclusion() {
|
||||
return (value[0] & 0x10) == 0x10;
|
||||
}
|
||||
|
||||
public void setReasonForInclusion(boolean reasonForInclusion) {
|
||||
if (reasonForInclusion) {
|
||||
value[0] = (byte) (value[0] | 0x10);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will the data set reference (not just the name) be included in the report.
|
||||
*
|
||||
* @return true if the data set reference (not just the name) will be included in the report
|
||||
*/
|
||||
public boolean isDataSetName() {
|
||||
return (value[0] & 0x08) == 0x08;
|
||||
}
|
||||
|
||||
public void setDataSetName(boolean dataSetName) {
|
||||
if (dataSetName) {
|
||||
value[0] = (byte) (value[0] | 0x08);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xf7);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDataReference() {
|
||||
return (value[0] & 0x04) == 0x04;
|
||||
}
|
||||
|
||||
public void setDataReference(boolean dataReference) {
|
||||
if (dataReference) {
|
||||
value[0] = (byte) (value[0] | 0x04);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfb);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBufferOverflow() {
|
||||
return (value[0] & 0x02) == 0x02;
|
||||
}
|
||||
|
||||
public void setBufferOverflow(boolean bufferOverflow) {
|
||||
if (bufferOverflow) {
|
||||
value[0] = (byte) (value[0] | 0x02);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfd);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEntryId() {
|
||||
return (value[0] & 0x01) == 0x01;
|
||||
}
|
||||
|
||||
public void setEntryId(boolean entryId) {
|
||||
if (entryId) {
|
||||
value[0] = (byte) (value[0] | 0x01);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfe);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConfigRevision() {
|
||||
return (value[1] & 0x80) == 0x80;
|
||||
}
|
||||
|
||||
public void setConfigRevision(boolean configRevision) {
|
||||
if (configRevision) {
|
||||
value[1] = (byte) (value[1] | 0x80);
|
||||
} else {
|
||||
value[1] = (byte) (value[1] & 0x7f);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSegmentation() {
|
||||
return (value[1] & 0x40) == 0x40;
|
||||
}
|
||||
|
||||
public void setSegmentation(boolean segmentation) {
|
||||
if (segmentation) {
|
||||
value[1] = (byte) (value[1] | 0x40);
|
||||
} else {
|
||||
value[1] = (byte) (value[1] & 0xbf);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class BdaQuality extends BdaBitString {
|
||||
|
||||
public BdaQuality(ObjectReference objectReference, Fc fc, String sAddr, boolean qchg) {
|
||||
super(objectReference, fc, sAddr, 13, qchg, false);
|
||||
this.qchg = qchg;
|
||||
basicType = BdaType.QUALITY;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[] {0x00, 0x00};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaQuality copy() {
|
||||
BdaQuality copy = new BdaQuality(objectReference, fc, sAddr, qchg);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public Validity getValidity() {
|
||||
if ((value[0] & 0xC0) == 0xC0) {
|
||||
return Validity.QUESTIONABLE;
|
||||
}
|
||||
|
||||
if ((value[0] & 0x80) == 0x80) {
|
||||
return Validity.RESERVED;
|
||||
}
|
||||
|
||||
if ((value[0] & 0x40) == 0x40) {
|
||||
return Validity.INVALID;
|
||||
}
|
||||
|
||||
return Validity.GOOD;
|
||||
}
|
||||
|
||||
public void setValidity(Validity validity) {
|
||||
if (validity == Validity.QUESTIONABLE) {
|
||||
value[0] = (byte) (value[0] | 0xC0);
|
||||
} else if (validity == Validity.RESERVED) {
|
||||
value[0] = (byte) (value[0] | 0x80);
|
||||
value[0] = (byte) (value[0] & 0xbf);
|
||||
} else if (validity == Validity.INVALID) {
|
||||
value[0] = (byte) (value[0] & 0x7f);
|
||||
value[0] = (byte) (value[0] | 0x40);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0x03);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOverflow() {
|
||||
return (value[0] & 0x20) == 0x20;
|
||||
}
|
||||
|
||||
public void setOverflow(boolean overflow) {
|
||||
if (overflow) {
|
||||
value[0] = (byte) (value[0] | 0x20);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xdf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOutOfRange() {
|
||||
return (value[0] & 0x10) == 0x10;
|
||||
}
|
||||
|
||||
public void setOutOfRange(boolean outOfRange) {
|
||||
if (outOfRange) {
|
||||
value[0] = (byte) (value[0] | 0x10);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xef);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBadReference() {
|
||||
return (value[0] & 0x08) == 0x08;
|
||||
}
|
||||
|
||||
public void setBadReference(boolean badReference) {
|
||||
if (badReference) {
|
||||
value[0] = (byte) (value[0] | 0x08);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xf7);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOscillatory() {
|
||||
return (value[0] & 0x04) == 0x04;
|
||||
}
|
||||
|
||||
public void setOscillatory(boolean oscillatory) {
|
||||
if (oscillatory) {
|
||||
value[0] = (byte) (value[0] | 0x04);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfb);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFailure() {
|
||||
return (value[0] & 0x02) == 0x02;
|
||||
}
|
||||
|
||||
public void setFailure(boolean failure) {
|
||||
if (failure) {
|
||||
value[0] = (byte) (value[0] | 0x02);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfd);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOldData() {
|
||||
return (value[0] & 0x01) == 0x01;
|
||||
}
|
||||
|
||||
public void setOldData(boolean oldData) {
|
||||
if (oldData) {
|
||||
value[0] = (byte) (value[0] | 0x01);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfe);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInconsistent() {
|
||||
return (value[1] & 0x80) == 0x80;
|
||||
}
|
||||
|
||||
public void setInconsistent(boolean inconsistent) {
|
||||
if (inconsistent) {
|
||||
value[1] = (byte) (value[0] | 0x80);
|
||||
} else {
|
||||
value[1] = (byte) (value[0] & 0x7f);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInaccurate() {
|
||||
return (value[1] & 0x40) == 0x40;
|
||||
}
|
||||
|
||||
public void setInaccurate(boolean inaccurate) {
|
||||
if (inaccurate) {
|
||||
value[1] = (byte) (value[0] | 0x40);
|
||||
} else {
|
||||
value[1] = (byte) (value[0] & 0xbf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSubstituted() {
|
||||
return (value[1] & 0x20) == 0x20;
|
||||
}
|
||||
|
||||
public void setSubstituted(boolean substituted) {
|
||||
if (substituted) {
|
||||
value[1] = (byte) (value[0] | 0x20);
|
||||
} else {
|
||||
value[1] = (byte) (value[0] & 0xdf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTest() {
|
||||
return (value[1] & 0x10) == 0x10;
|
||||
}
|
||||
|
||||
public void setTest(boolean test) {
|
||||
if (test) {
|
||||
value[1] = (byte) (value[0] | 0x10);
|
||||
} else {
|
||||
value[1] = (byte) (value[0] & 0xef);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOperatorBlocked() {
|
||||
return (value[1] & 0x08) == 0x08;
|
||||
}
|
||||
|
||||
public void setOperatorBlocked(boolean operatorBlocked) {
|
||||
if (operatorBlocked) {
|
||||
value[1] = (byte) (value[0] | 0x08);
|
||||
} else {
|
||||
value[1] = (byte) (value[0] & 0xf7);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return getValidity().toString();
|
||||
}
|
||||
|
||||
public enum Validity {
|
||||
GOOD(0),
|
||||
INVALID(1),
|
||||
RESERVED(2),
|
||||
QUESTIONABLE(3);
|
||||
private final int value;
|
||||
|
||||
Validity(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getIntValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class BdaReasonForInclusion extends BdaBitString {
|
||||
|
||||
public BdaReasonForInclusion(ObjectReference objectReference) {
|
||||
super(objectReference, null, null, 7, false, false);
|
||||
basicType = BdaType.REASON_FOR_INCLUSION;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaReasonForInclusion copy() {
|
||||
BdaReasonForInclusion copy = new BdaReasonForInclusion(objectReference);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public boolean isDataChange() {
|
||||
return (value[0] & 0x40) == 0x40;
|
||||
}
|
||||
|
||||
public void setDataChange(boolean dataChange) {
|
||||
if (dataChange) {
|
||||
value[0] = (byte) (value[0] | 0x40);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xbf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isQualityChange() {
|
||||
return (value[0] & 0x20) == 0x20;
|
||||
}
|
||||
|
||||
public void setQualityChange(boolean qualityChange) {
|
||||
if (qualityChange) {
|
||||
value[0] = (byte) (value[0] | 0x20);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xdf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDataUpdate() {
|
||||
return (value[0] & 0x10) == 0x10;
|
||||
}
|
||||
|
||||
public void setDataUpdate(boolean dataUpdate) {
|
||||
if (dataUpdate) {
|
||||
value[0] = (byte) (value[0] | 0x10);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xef);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIntegrity() {
|
||||
return (value[0] & 0x08) == 0x08;
|
||||
}
|
||||
|
||||
public void setIntegrity(boolean integrity) {
|
||||
if (integrity) {
|
||||
value[0] = (byte) (value[0] | 0x08);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xf7);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isGeneralInterrogation() {
|
||||
return (value[0] & 0x04) == 0x04;
|
||||
}
|
||||
|
||||
public void setGeneralInterrogation(boolean generalInterrogation) {
|
||||
if (generalInterrogation) {
|
||||
value[0] = (byte) (value[0] | 0x04);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfb);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isApplicationTrigger() {
|
||||
return (value[0] & 0x02) == 0x02;
|
||||
}
|
||||
|
||||
public void setApplicationTrigger(boolean applicationTrigger) {
|
||||
if (applicationTrigger) {
|
||||
value[0] = (byte) (value[0] | 0x02);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
if (isDataChange()) {
|
||||
if (!first) {
|
||||
sb.append(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
sb.append("data-change");
|
||||
}
|
||||
|
||||
if (isDataUpdate()) {
|
||||
if (!first) {
|
||||
sb.append(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
sb.append("data-update");
|
||||
}
|
||||
|
||||
if (isQualityChange()) {
|
||||
if (!first) {
|
||||
sb.append(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
sb.append("quality-change");
|
||||
}
|
||||
|
||||
if (isIntegrity()) {
|
||||
if (!first) {
|
||||
sb.append(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
sb.append("integrity");
|
||||
}
|
||||
|
||||
if (isGeneralInterrogation()) {
|
||||
if (!first) {
|
||||
sb.append(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
sb.append("general-interrogation");
|
||||
}
|
||||
|
||||
if (isApplicationTrigger()) {
|
||||
if (!first) {
|
||||
sb.append(",");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
sb.append("application-trigger");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class BdaTapCommand extends BdaBitString {
|
||||
|
||||
public BdaTapCommand(
|
||||
ObjectReference objectReference, Fc fc, String sAddr, boolean dchg, boolean dupd) {
|
||||
super(objectReference, fc, sAddr, 2, dchg, dupd);
|
||||
basicType = BdaType.TAP_COMMAND;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
/** Sets the value to TapCommand.STOP */
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[] {0x00};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaTapCommand copy() {
|
||||
BdaTapCommand copy = new BdaTapCommand(objectReference, fc, sAddr, dchg, dupd);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public TapCommand getTapCommand() {
|
||||
|
||||
if ((value[0] & 0xC0) == 0xC0) {
|
||||
return TapCommand.RESERVED;
|
||||
}
|
||||
|
||||
if ((value[0] & 0x80) == 0x80) {
|
||||
return TapCommand.HIGHER;
|
||||
}
|
||||
|
||||
if ((value[0] & 0x40) == 0x40) {
|
||||
return TapCommand.LOWER;
|
||||
}
|
||||
|
||||
return TapCommand.STOP;
|
||||
}
|
||||
|
||||
public void setTapCommand(TapCommand tapCommand) {
|
||||
if (tapCommand == TapCommand.RESERVED) {
|
||||
value[0] = (byte) 0xC0;
|
||||
} else if (tapCommand == TapCommand.HIGHER) {
|
||||
value[0] = (byte) 0x80;
|
||||
} else if (tapCommand == TapCommand.LOWER) {
|
||||
value[0] = (byte) 0x40;
|
||||
} else {
|
||||
value[0] = (byte) 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
public enum TapCommand {
|
||||
STOP(0),
|
||||
LOWER(1),
|
||||
HIGHER(2),
|
||||
RESERVED(3);
|
||||
private final int value;
|
||||
|
||||
TapCommand(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getIntValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class BdaTriggerConditions extends BdaBitString {
|
||||
|
||||
public BdaTriggerConditions(ObjectReference objectReference, Fc fc) {
|
||||
super(objectReference, fc, null, 6, false, false);
|
||||
basicType = BdaType.TRIGGER_CONDITIONS;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
/* default of GI is true by default in IEC 61850-6 sec. 9.3.8 */
|
||||
value = new byte[] {0x04};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaTriggerConditions copy() {
|
||||
BdaTriggerConditions copy = new BdaTriggerConditions(objectReference, fc);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
public boolean isDataChange() {
|
||||
return (value[0] & 0x40) == 0x40;
|
||||
}
|
||||
|
||||
public void setDataChange(boolean dataChange) {
|
||||
if (dataChange) {
|
||||
value[0] = (byte) (value[0] | 0x40);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xbf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isQualityChange() {
|
||||
return (value[0] & 0x20) == 0x20;
|
||||
}
|
||||
|
||||
public void setQualityChange(boolean qualityChange) {
|
||||
if (qualityChange) {
|
||||
value[0] = (byte) (value[0] | 0x20);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xdf);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDataUpdate() {
|
||||
return (value[0] & 0x10) == 0x10;
|
||||
}
|
||||
|
||||
public void setDataUpdate(boolean dataUpdate) {
|
||||
if (dataUpdate) {
|
||||
value[0] = (byte) (value[0] | 0x10);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xef);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isIntegrity() {
|
||||
return (value[0] & 0x08) == 0x08;
|
||||
}
|
||||
|
||||
public void setIntegrity(boolean integrity) {
|
||||
if (integrity) {
|
||||
value[0] = (byte) (value[0] | 0x08);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xf7);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isGeneralInterrogation() {
|
||||
return (value[0] & 0x04) == 0x04;
|
||||
}
|
||||
|
||||
public void setGeneralInterrogation(boolean generalInterrogation) {
|
||||
if (generalInterrogation) {
|
||||
value[0] = (byte) (value[0] | 0x04);
|
||||
} else {
|
||||
value[0] = (byte) (value[0] & 0xfb);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return super.toString()
|
||||
+ ", data change: "
|
||||
+ isDataChange()
|
||||
+ ", data update: "
|
||||
+ isDataUpdate()
|
||||
+ ", quality change:"
|
||||
+ isQualityChange()
|
||||
+ ", integrity period: "
|
||||
+ isIntegrity()
|
||||
+ ", GI: "
|
||||
+ isGeneralInterrogation();
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
/**
|
||||
* This Enumeration includes all possible Types for IEC 61850 leave nodes ( {@link
|
||||
* BasicDataAttribute}). This includes BasicTypes and CommonACSITypes as defined in part 7-2.
|
||||
*/
|
||||
public enum BdaType {
|
||||
BOOLEAN,
|
||||
INT8,
|
||||
INT16,
|
||||
INT32,
|
||||
INT64,
|
||||
INT128,
|
||||
INT8U,
|
||||
INT16U,
|
||||
INT32U,
|
||||
FLOAT32,
|
||||
FLOAT64,
|
||||
OCTET_STRING,
|
||||
VISIBLE_STRING,
|
||||
UNICODE_STRING,
|
||||
TIMESTAMP,
|
||||
ENTRY_TIME,
|
||||
CHECK,
|
||||
QUALITY,
|
||||
DOUBLE_BIT_POS,
|
||||
TAP_COMMAND,
|
||||
TRIGGER_CONDITIONS,
|
||||
OPTFLDS,
|
||||
REASON_FOR_INCLUSION
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Integer32;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.MMSString;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
|
||||
public final class BdaUnicodeString extends BasicDataAttribute {
|
||||
|
||||
private final int maxLength;
|
||||
private byte[] value;
|
||||
|
||||
public BdaUnicodeString(
|
||||
ObjectReference objectReference,
|
||||
Fc fc,
|
||||
String sAddr,
|
||||
int maxLength,
|
||||
boolean dchg,
|
||||
boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.UNICODE_STRING;
|
||||
this.maxLength = maxLength;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
if (value == null || value.length > maxLength) {
|
||||
throw new IllegalArgumentException(
|
||||
"Value was null or UNICODE_STRING value size exceeds maxLength of " + maxLength);
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
byte[] srcValue = ((BdaUnicodeString) bda).getValue();
|
||||
if (value.length != srcValue.length) {
|
||||
value = new byte[srcValue.length];
|
||||
}
|
||||
System.arraycopy(srcValue, 0, value, 0, srcValue.length);
|
||||
}
|
||||
|
||||
public int getMaxLength() {
|
||||
return maxLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaUnicodeString copy() {
|
||||
BdaUnicodeString copy = new BdaUnicodeString(objectReference, fc, sAddr, maxLength, dchg, dupd);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setMMSString(new MMSString(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getMMSString() == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.TYPE_CONFLICT, "expected type: mms_string/unicode_string");
|
||||
}
|
||||
value = data.getMMSString().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setMMSString(new Integer32(maxLength * -1));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (value == null) {
|
||||
return getReference().toString() + ": null";
|
||||
}
|
||||
return getReference().toString() + ": " + new String(value, UTF_8);
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.string.BerVisibleString;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Integer32;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
|
||||
public final class BdaVisibleString extends BasicDataAttribute {
|
||||
|
||||
private final int maxLength;
|
||||
private byte[] value;
|
||||
|
||||
public BdaVisibleString(
|
||||
ObjectReference objectReference,
|
||||
Fc fc,
|
||||
String sAddr,
|
||||
int maxLength,
|
||||
boolean dchg,
|
||||
boolean dupd) {
|
||||
super(objectReference, fc, sAddr, dchg, dupd);
|
||||
basicType = BdaType.VISIBLE_STRING;
|
||||
this.maxLength = maxLength;
|
||||
setDefault();
|
||||
}
|
||||
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(byte[] value) {
|
||||
if (value == null || value.length > maxLength) {
|
||||
throw new IllegalArgumentException(
|
||||
"value was null or VISIBLE_STRING value size exceeds maxLength of " + maxLength);
|
||||
}
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
setValue(value.getBytes(UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueFrom(BasicDataAttribute bda) {
|
||||
byte[] srcValue = ((BdaVisibleString) bda).getValue();
|
||||
if (value.length != srcValue.length) {
|
||||
value = new byte[srcValue.length];
|
||||
}
|
||||
System.arraycopy(srcValue, 0, value, 0, srcValue.length);
|
||||
}
|
||||
|
||||
public int getMaxLength() {
|
||||
return maxLength;
|
||||
}
|
||||
|
||||
public String getStringValue() {
|
||||
return new String(value, UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefault() {
|
||||
value = new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public BdaVisibleString copy() {
|
||||
BdaVisibleString copy = new BdaVisibleString(objectReference, fc, sAddr, maxLength, dchg, dupd);
|
||||
byte[] valueCopy = new byte[value.length];
|
||||
System.arraycopy(value, 0, valueCopy, 0, value.length);
|
||||
copy.setValue(valueCopy);
|
||||
if (mirror == null) {
|
||||
copy.mirror = this;
|
||||
} else {
|
||||
copy.mirror = mirror;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data data = new Data();
|
||||
data.setVisibleString(new BerVisibleString(value));
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getVisibleString() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: visible_string");
|
||||
}
|
||||
value = data.getVisibleString().value;
|
||||
}
|
||||
|
||||
@Override
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setVisibleString(new Integer32(maxLength * -1));
|
||||
return typeDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (value == null) {
|
||||
return getReference().toString() + ": null";
|
||||
}
|
||||
if (value.length == 0 || value[0] == (byte) 0) {
|
||||
return getReference().toString() + ": ''";
|
||||
}
|
||||
return getReference().toString() + ": " + new String(value, UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueString() {
|
||||
return new String(value, UTF_8);
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Brcb extends Rcb {
|
||||
|
||||
public Brcb(ObjectReference objectReference, List<FcModelNode> children) {
|
||||
super(objectReference, Fc.BR, children);
|
||||
}
|
||||
|
||||
public BdaBoolean getPurgeBuf() {
|
||||
return (BdaBoolean) children.get("PurgeBuf");
|
||||
}
|
||||
|
||||
public BdaOctetString getEntryId() {
|
||||
return (BdaOctetString) children.get("EntryID");
|
||||
}
|
||||
|
||||
public BdaEntryTime getTimeOfEntry() {
|
||||
return (BdaEntryTime) children.get("TimeOfEntry");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ResvTms attribute. This attribute is optional. Will return NULL if the attribute is
|
||||
* not available.
|
||||
*
|
||||
* @return the ResvTms attribute, null if not available.
|
||||
*/
|
||||
public BdaInt16 getResvTms() {
|
||||
return (BdaInt16) children.get("ResvTms");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FcDataObject copy() {
|
||||
List<FcModelNode> childCopies = new ArrayList<>(children.size());
|
||||
for (ModelNode childNode : children.values()) {
|
||||
childCopies.add((FcModelNode) childNode.copy());
|
||||
}
|
||||
Brcb brcb = new Brcb(objectReference, childCopies);
|
||||
brcb.dataSet = dataSet;
|
||||
return brcb;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* The listener interface for receiving incoming reports and association closed events. A listener
|
||||
* is registered through the {@link ClientSap#associate(java.net.InetAddress, int, String,
|
||||
* ClientEventListener) associate} method.
|
||||
*
|
||||
* @author Stefan Feuerhahn
|
||||
*/
|
||||
public interface ClientEventListener {
|
||||
|
||||
/**
|
||||
* Invoked when a new report arrives. Note that the implementation of this method needs to be
|
||||
* thread safe as it can be called in parallel if a new report arrives while an old one is still
|
||||
* being processed.
|
||||
*
|
||||
* @param report the report that arrived.
|
||||
*/
|
||||
void newReport(Report report);
|
||||
|
||||
/**
|
||||
* Invoked when an IOException occurred for the association. An IOException implies that the
|
||||
* ClientAssociation that feeds this listener was automatically closed and can no longer be used
|
||||
* to receive reports.
|
||||
*
|
||||
* @param e the exception that occured.
|
||||
*/
|
||||
void associationClosed(IOException e);
|
||||
}
|
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.josistack.ClientAcseSap;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
/**
|
||||
* The <code>ClientSap</code> class represents the IEC 61850 service access point for client
|
||||
* applications. A client application that wants to connect to a server should first create an
|
||||
* instance of <code>ClientSap</code>. Next all the necessary configuration parameters can be set.
|
||||
* Finally the <code>associate</code> function is called to connect to the server. An instance of
|
||||
* <code>ClientSap</code> can be used to create an unlimited number of associations. Changing the
|
||||
* parameters of a ClientSap has no affect on associations that have already been created.
|
||||
*/
|
||||
public final class ClientSap {
|
||||
|
||||
static final int MINIMUM_MMS_PDU_SIZE = 64;
|
||||
private static final int MAXIMUM_MMS_PDU_SIZE = 65000;
|
||||
|
||||
private static final byte[] DEFAULT_TSEL_LOCAL = new byte[] {0, 0};
|
||||
private static final byte[] DEFAULT_TSEL_REMOTE = new byte[] {0, 1};
|
||||
private static final int DEFAULT_TPDU_SIZE_PARAMETER = 10; // size = 1024
|
||||
private final ClientAcseSap acseSap;
|
||||
private int proposedMaxServOutstandingCalling = 5;
|
||||
private int proposedMaxServOutstandingCalled = 5;
|
||||
private int proposedDataStructureNestingLevel = 10;
|
||||
private int proposedMaxMmsPduSize = 65000;
|
||||
private byte[] servicesSupportedCalling =
|
||||
new byte[] {(byte) 0xee, 0x1c, 0, 0, 0x04, 0x08, 0, 0, 0x79, (byte) 0xef, 0x18};
|
||||
private int messageFragmentTimeout = 10000;
|
||||
private int responseTimeout = 20000;
|
||||
|
||||
/** Use this constructor to create a default client SAP. */
|
||||
public ClientSap() {
|
||||
acseSap = new ClientAcseSap();
|
||||
acseSap.tSap.tSelLocal = DEFAULT_TSEL_LOCAL;
|
||||
acseSap.tSap.tSelRemote = DEFAULT_TSEL_REMOTE;
|
||||
acseSap.tSap.setMaxTPDUSizeParam(DEFAULT_TPDU_SIZE_PARAMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this constructor to create a client SAP that uses the given <code>SocketFactory</code> to
|
||||
* connect to servers. You could pass an SSLSocketFactory to enable SSL.
|
||||
*
|
||||
* @param socketFactory the socket factory to construct the socket
|
||||
*/
|
||||
public ClientSap(SocketFactory socketFactory) {
|
||||
acseSap = new ClientAcseSap(socketFactory);
|
||||
acseSap.tSap.tSelLocal = DEFAULT_TSEL_LOCAL;
|
||||
acseSap.tSap.tSelRemote = DEFAULT_TSEL_REMOTE;
|
||||
acseSap.tSap.setMaxTPDUSizeParam(DEFAULT_TPDU_SIZE_PARAMETER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum MMS PDU size.
|
||||
*
|
||||
* @return the maximum MMS PDU size.
|
||||
*/
|
||||
public int getMaxMmsPduSize() {
|
||||
return proposedMaxMmsPduSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum MMS PDU size in bytes that the client association will support. The client
|
||||
* proposes this value to the server during association. If the server requires the use of a
|
||||
* smaller maximum MMS PDU size, then the smaller size will be accepted by the client. The default
|
||||
* size is 65000.
|
||||
*
|
||||
* @param size cannot be less than 64. The upper limit is 65000 so that segmentation at the lower
|
||||
* transport layer is avoided. The Transport Layer's maximum PDU size is 65531.
|
||||
*/
|
||||
public void setMaxMmsPduSize(int size) {
|
||||
if (size >= MINIMUM_MMS_PDU_SIZE && size <= MAXIMUM_MMS_PDU_SIZE) {
|
||||
proposedMaxMmsPduSize = size;
|
||||
} else {
|
||||
throw new IllegalArgumentException("maximum size is out of bound");
|
||||
}
|
||||
}
|
||||
|
||||
public void setProposedMaxServOutstandingCalling(int proposedMaxServOutstandingCalling) {
|
||||
this.proposedMaxServOutstandingCalling = proposedMaxServOutstandingCalling;
|
||||
}
|
||||
|
||||
public void setProposedMaxServOutstandingCalled(int proposedMaxServOutstandingCalled) {
|
||||
this.proposedMaxServOutstandingCalled = proposedMaxServOutstandingCalled;
|
||||
}
|
||||
|
||||
public void setProposedDataStructureNestingLevel(int proposedDataStructureNestingLevel) {
|
||||
this.proposedDataStructureNestingLevel = proposedDataStructureNestingLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ServicesSupportedCalling parameter.
|
||||
*
|
||||
* @return the ServicesSupportedCalling parameter.
|
||||
*/
|
||||
public byte[] getServicesSupportedCalling() {
|
||||
return servicesSupportedCalling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SevicesSupportedCalling parameter. The given parameter is sent to the server but has
|
||||
* no affect on the functionality of this client.
|
||||
*
|
||||
* @param services the ServicesSupportedCalling parameter
|
||||
*/
|
||||
public void setServicesSupportedCalling(byte[] services) {
|
||||
if (services.length != 11) {
|
||||
throw new IllegalArgumentException("The services parameter needs to be of lenth 11");
|
||||
}
|
||||
servicesSupportedCalling = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the remote/called Session-Selector (S-SEL). The default remote S-SEL is byte[] { 0, 1 }.
|
||||
*
|
||||
* @param sSelRemote the remote/called S-SEL.
|
||||
*/
|
||||
public void setSSelRemote(byte[] sSelRemote) {
|
||||
acseSap.sSelRemote = sSelRemote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the local/calling Session-Selector (S-SEL). The default local S-SEL is byte[] { 0, 1 }.
|
||||
*
|
||||
* @param sSelLocal the local/calling S-SEL.
|
||||
*/
|
||||
public void setSSelLocal(byte[] sSelLocal) {
|
||||
acseSap.sSelLocal = sSelLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the remote/called Presentation-Selector (P-SEL). The default remote P-SEL is byte[] { 0,
|
||||
* 0, 0, 1 }.
|
||||
*
|
||||
* @param pSelRemote the remote/called P-SEL.
|
||||
*/
|
||||
public void setPSelRemote(byte[] pSelRemote) {
|
||||
acseSap.pSelRemote = pSelRemote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the local/calling Presentation-Selector (P-SEL). The default local P-SEL is byte[] { 0, 0,
|
||||
* 0, 1 }.
|
||||
*
|
||||
* @param pSelLocal the local/calling P-SEL.
|
||||
*/
|
||||
public void setPSelLocal(byte[] pSelLocal) {
|
||||
acseSap.pSelLocal = pSelLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the remote/called Transport-Selector (T-SEL). It is optionally transmitted in the OSI
|
||||
* Transport Layer connection request (CR). The default remote T-SEL is byte[] { 0, 1 }.
|
||||
*
|
||||
* @param tSelRemote the remote/called T-SEL. If null the T-SEL will be omitted. No maximum size
|
||||
* is defined by the standard.
|
||||
*/
|
||||
public void setTSelRemote(byte[] tSelRemote) {
|
||||
acseSap.tSap.tSelRemote = tSelRemote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the local/calling Transport-Selector (T-SEL). It is optionally transmitted in the OSI
|
||||
* Transport Layer connection request (CR). The default local T-SEL byte[] { 0, 0 }.
|
||||
*
|
||||
* @param tSelLocal the local/calling T-SEL. If null the T-SEL will be omitted. No maximum size is
|
||||
* defined by the standard.
|
||||
*/
|
||||
public void setTSelLocal(byte[] tSelLocal) {
|
||||
acseSap.tSap.tSelLocal = tSelLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maxTPDUSize. The default maxTPduSize is 65531 (see RFC 1006).
|
||||
*
|
||||
* @param maxTPduSizeParam The maximum length is equal to 2^(maxTPduSizeParam) octets. Note that
|
||||
* the actual TSDU size that can be transfered is equal to TPduSize-3. Default is 65531 octets
|
||||
* (see RFC 1006), 7 <= maxTPduSizeParam <= 16, needs to be set before listening or
|
||||
* connecting
|
||||
*/
|
||||
public void setMaxTPduSizeParameter(int maxTPduSizeParam) {
|
||||
acseSap.tSap.setMaxTPDUSizeParam(maxTPduSizeParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the remote/called Application Process Title. The default value is int[] { 1, 1, 999, 1, 1
|
||||
* }
|
||||
*
|
||||
* @param title the remote/called AP title.
|
||||
*/
|
||||
public void setApTitleCalled(int[] title) {
|
||||
acseSap.setApTitleCalled(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the local/calling Application Process Title. The default value is int[] { 1, 1, 999, 1 }
|
||||
*
|
||||
* @param title the local/calling AP title.
|
||||
*/
|
||||
public void setApTitleCalling(int[] title) {
|
||||
acseSap.setApTitleCalling(title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the remote/called Application Entity Qualifier. The default value is 12.
|
||||
*
|
||||
* @param qualifier the remote/called AE Qualifier
|
||||
*/
|
||||
public void setAeQualifierCalled(int qualifier) {
|
||||
acseSap.setAeQualifierCalled(qualifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the local/calling Application Entity Qualifier. The default value is 12.
|
||||
*
|
||||
* @param qualifier the local/calling AE Qualifier
|
||||
*/
|
||||
public void setAeQualifierCalling(int qualifier) {
|
||||
acseSap.setAeQualifierCalling(qualifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default response timeout of the <code>ClientAssociation</code> that is created using
|
||||
* this ClientSap.
|
||||
*
|
||||
* @param timeout the response timeout in milliseconds. The default is 20000.
|
||||
*/
|
||||
public void setResponseTimeout(int timeout) {
|
||||
responseTimeout = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the message fragment timeout. This is the timeout that the socket timeout is set to after
|
||||
* the first byte of a message has been received. A request function (e.g. setDataValues()) will
|
||||
* throw an IOException if the socket throws this timeout because the association/connection
|
||||
* cannot recover from this kind of error.
|
||||
*
|
||||
* @param timeout the timeout in milliseconds. The default is 10000.
|
||||
*/
|
||||
public void setMessageFragmentTimeout(int timeout) {
|
||||
messageFragmentTimeout = timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the IEC 61850 MMS server at the given address and port and returns the resulting
|
||||
* association object.
|
||||
*
|
||||
* @param address the address to connect to.
|
||||
* @param port the port to connect to. Usually the MMS port is 102.
|
||||
* @param authenticationParameter an optional authentication parameters that is transmitted. It
|
||||
* will be omitted if equal to null.
|
||||
* @param reportListener the listener to be notified of incoming reports
|
||||
* @return the association object
|
||||
* @throws IOException if any kind of error occurs trying build up the association
|
||||
*/
|
||||
public ClientAssociation associate(
|
||||
InetAddress address,
|
||||
int port,
|
||||
String authenticationParameter,
|
||||
ClientEventListener reportListener)
|
||||
throws IOException {
|
||||
return associate(address, port, authenticationParameter, null, -1, reportListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects to the IEC 61850 MMS server at the given address and port and returns the resulting
|
||||
* association object.
|
||||
*
|
||||
* @param address the address to connect to
|
||||
* @param port the port to connect to. Usually the MMS port is 102.
|
||||
* @param authenticationParameter an optional authentication parameters that is transmitted. It
|
||||
* will be omitted if equal to null.
|
||||
* @param localAddr the local address to use
|
||||
* @param localPort the local port to use
|
||||
* @param reportListener the listener to be notified of incoming reports
|
||||
* @return the association object.
|
||||
* @throws IOException if any kind of error occurs trying build up the association
|
||||
*/
|
||||
public ClientAssociation associate(
|
||||
InetAddress address,
|
||||
int port,
|
||||
String authenticationParameter,
|
||||
InetAddress localAddr,
|
||||
int localPort,
|
||||
ClientEventListener reportListener)
|
||||
throws IOException {
|
||||
|
||||
if (port < 0 || port > 65535) {
|
||||
throw new IllegalArgumentException("invalid port");
|
||||
}
|
||||
|
||||
if (address == null) {
|
||||
throw new IllegalArgumentException("address may not be null");
|
||||
}
|
||||
|
||||
if (acseSap.sSelRemote == null) {
|
||||
throw new IllegalArgumentException("sSelRemote may not be null");
|
||||
}
|
||||
|
||||
if (acseSap.sSelRemote.length != 2) {
|
||||
throw new IllegalArgumentException("sSelRemote lenght must be two");
|
||||
}
|
||||
|
||||
if (acseSap.sSelLocal == null) {
|
||||
throw new IllegalArgumentException("sSelLocal may not be null");
|
||||
}
|
||||
|
||||
if (acseSap.sSelLocal.length != 2) {
|
||||
throw new IllegalArgumentException("sSelLocal lenght must be two");
|
||||
}
|
||||
|
||||
ClientAssociation clientAssociation =
|
||||
new ClientAssociation(
|
||||
address,
|
||||
port,
|
||||
localAddr,
|
||||
localPort,
|
||||
authenticationParameter,
|
||||
acseSap,
|
||||
proposedMaxMmsPduSize,
|
||||
proposedMaxServOutstandingCalling,
|
||||
proposedMaxServOutstandingCalled,
|
||||
proposedDataStructureNestingLevel,
|
||||
servicesSupportedCalling,
|
||||
responseTimeout,
|
||||
messageFragmentTimeout,
|
||||
reportListener);
|
||||
|
||||
return clientAssociation;
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data.Structure;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public final class ConstructedDataAttribute extends FcModelNode {
|
||||
|
||||
public ConstructedDataAttribute(
|
||||
ObjectReference objectReference, Fc fc, List<FcModelNode> children) {
|
||||
this.objectReference = objectReference;
|
||||
this.fc = fc;
|
||||
this.children = new LinkedHashMap<>((int) ((children.size() / 0.75) + 1));
|
||||
for (ModelNode child : children) {
|
||||
this.children.put(child.getName(), child);
|
||||
child.setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstructedDataAttribute copy() {
|
||||
List<FcModelNode> subDataAttributesCopy = new ArrayList<>();
|
||||
for (ModelNode subDA : children.values()) {
|
||||
subDataAttributesCopy.add((FcModelNode) subDA.copy());
|
||||
}
|
||||
return new ConstructedDataAttribute(getReference(), fc, subDataAttributesCopy);
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Structure structure = new Structure();
|
||||
List<Data> seq = structure.getData();
|
||||
|
||||
for (ModelNode modelNode : getChildren()) {
|
||||
Data child = modelNode.getMmsDataObj();
|
||||
if (child == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to convert Child: " + modelNode.objectReference + " to MMS Data Object.");
|
||||
}
|
||||
seq.add(child);
|
||||
}
|
||||
if (seq.size() == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Converting ModelNode: "
|
||||
+ objectReference
|
||||
+ " to MMS Data Object resulted in Sequence of size zero.");
|
||||
}
|
||||
|
||||
Data data = new Data();
|
||||
data.setStructure(structure);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getStructure() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: structure");
|
||||
}
|
||||
if (data.getStructure().getData().size() != children.size()) {
|
||||
throw new ServiceError(
|
||||
ServiceError.TYPE_CONFLICT,
|
||||
"expected type: structure with " + children.size() + " elements");
|
||||
}
|
||||
|
||||
Iterator<Data> iterator = data.getStructure().getData().iterator();
|
||||
for (ModelNode child : children.values()) {
|
||||
child.setValueFromMmsDataObj(iterator.next());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,274 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.ConfirmedServiceResponse;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.GetVariableAccessAttributesResponse;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription.Structure.Components;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeSpecification;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
final class DataDefinitionResParser {
|
||||
|
||||
static LogicalNode parseGetDataDefinitionResponse(
|
||||
ConfirmedServiceResponse confirmedServiceResponse, ObjectReference lnRef)
|
||||
throws ServiceError {
|
||||
|
||||
if (confirmedServiceResponse.getGetVariableAccessAttributes() == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
|
||||
"decodeGetDataDefinitionResponse: Error decoding GetDataDefinitionResponsePdu");
|
||||
}
|
||||
|
||||
GetVariableAccessAttributesResponse varAccAttrs =
|
||||
confirmedServiceResponse.getGetVariableAccessAttributes();
|
||||
TypeDescription typeSpec = varAccAttrs.getTypeDescription();
|
||||
if (typeSpec.getStructure() == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
|
||||
"decodeGetDataDefinitionResponse: Error decoding GetDataDefinitionResponsePdu");
|
||||
}
|
||||
|
||||
Components structure = typeSpec.getStructure().getComponents();
|
||||
|
||||
List<FcDataObject> fcDataObjects = new ArrayList<>();
|
||||
|
||||
Fc fc;
|
||||
for (TypeDescription.Structure.Components.SEQUENCE fcComponent : structure.getSEQUENCE()) {
|
||||
if (fcComponent.getComponentName() == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"Error decoding GetDataDefinitionResponsePdu");
|
||||
}
|
||||
|
||||
if (fcComponent.getComponentType().getTypeDescription().getStructure() == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"Error decoding GetDataDefinitionResponsePdu");
|
||||
}
|
||||
|
||||
String fcString = fcComponent.getComponentName().toString();
|
||||
if (fcString.equals("LG")
|
||||
|| fcString.equals("GO")
|
||||
|| fcString.equals("GS")
|
||||
|| fcString.equals("MS")
|
||||
|| fcString.equals("US")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fc = Fc.fromString(fcComponent.getComponentName().toString());
|
||||
Components subStructure =
|
||||
fcComponent.getComponentType().getTypeDescription().getStructure().getComponents();
|
||||
|
||||
fcDataObjects.addAll(getFcDataObjectsFromSubStructure(lnRef, fc, subStructure));
|
||||
}
|
||||
|
||||
LogicalNode ln = new LogicalNode(lnRef, fcDataObjects);
|
||||
|
||||
return ln;
|
||||
}
|
||||
|
||||
private static List<FcDataObject> getFcDataObjectsFromSubStructure(
|
||||
ObjectReference lnRef, Fc fc, Components components) throws ServiceError {
|
||||
|
||||
List<TypeDescription.Structure.Components.SEQUENCE> structComponents = components.getSEQUENCE();
|
||||
List<FcDataObject> dataObjects = new ArrayList<>(structComponents.size());
|
||||
|
||||
for (TypeDescription.Structure.Components.SEQUENCE doComp : structComponents) {
|
||||
if (doComp.getComponentName() == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"Error decoding GetDataDefinitionResponsePdu");
|
||||
}
|
||||
if (doComp.getComponentType().getTypeDescription() == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"Error decoding GetDataDefinitionResponsePdu");
|
||||
}
|
||||
|
||||
ObjectReference doRef =
|
||||
new ObjectReference(lnRef + "." + doComp.getComponentName().toString());
|
||||
List<FcModelNode> children =
|
||||
getDoSubModelNodesFromSubStructure(
|
||||
doRef,
|
||||
fc,
|
||||
doComp.getComponentType().getTypeDescription().getStructure().getComponents());
|
||||
if (fc == Fc.RP) {
|
||||
dataObjects.add(new Urcb(doRef, children));
|
||||
} else if (fc == Fc.BR) {
|
||||
dataObjects.add(new Brcb(doRef, children));
|
||||
} else {
|
||||
dataObjects.add(new FcDataObject(doRef, fc, children));
|
||||
}
|
||||
}
|
||||
|
||||
return dataObjects;
|
||||
}
|
||||
|
||||
private static List<FcModelNode> getDoSubModelNodesFromSubStructure(
|
||||
ObjectReference parentRef, Fc fc, Components structure) throws ServiceError {
|
||||
|
||||
Collection<TypeDescription.Structure.Components.SEQUENCE> structComponents =
|
||||
structure.getSEQUENCE();
|
||||
List<FcModelNode> dataObjects = new ArrayList<>(structComponents.size());
|
||||
|
||||
for (TypeDescription.Structure.Components.SEQUENCE component : structComponents) {
|
||||
if (component.getComponentName() == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"Error decoding GetDataDefinitionResponsePdu");
|
||||
}
|
||||
|
||||
String childName = component.getComponentName().toString();
|
||||
dataObjects.add(
|
||||
getModelNodesFromTypeSpecification(
|
||||
new ObjectReference(parentRef + "." + childName), fc, component.getComponentType()));
|
||||
}
|
||||
return dataObjects;
|
||||
}
|
||||
|
||||
private static FcModelNode getModelNodesFromTypeSpecification(
|
||||
ObjectReference ref, Fc fc, TypeSpecification mmsTypeSpec) throws ServiceError {
|
||||
|
||||
if (mmsTypeSpec.getTypeDescription().getArray() != null) {
|
||||
|
||||
int numArrayElements =
|
||||
mmsTypeSpec.getTypeDescription().getArray().getNumberOfElements().intValue();
|
||||
List<FcModelNode> arrayChildren = new ArrayList<>(numArrayElements);
|
||||
for (int i = 0; i < numArrayElements; i++) {
|
||||
arrayChildren.add(
|
||||
getModelNodesFromTypeSpecification(
|
||||
new ObjectReference(ref + "(" + i + ")"),
|
||||
fc,
|
||||
mmsTypeSpec.getTypeDescription().getArray().getElementType()));
|
||||
}
|
||||
|
||||
return new Array(ref, fc, arrayChildren);
|
||||
}
|
||||
|
||||
if (mmsTypeSpec.getTypeDescription().getStructure() != null) {
|
||||
List<FcModelNode> children =
|
||||
getDoSubModelNodesFromSubStructure(
|
||||
ref, fc, mmsTypeSpec.getTypeDescription().getStructure().getComponents());
|
||||
return (new ConstructedDataAttribute(ref, fc, children));
|
||||
}
|
||||
|
||||
// it is a single element
|
||||
BasicDataAttribute bt = convertMmsBasicTypeSpec(ref, fc, mmsTypeSpec.getTypeDescription());
|
||||
if (bt == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"decodeGetDataDefinitionResponse: Unknown data type received " + ref);
|
||||
}
|
||||
return (bt);
|
||||
}
|
||||
|
||||
private static BasicDataAttribute convertMmsBasicTypeSpec(
|
||||
ObjectReference ref, Fc fc, TypeDescription mmsTypeSpec) throws ServiceError {
|
||||
|
||||
if (mmsTypeSpec.getBool() != null) {
|
||||
return new BdaBoolean(ref, fc, null, false, false);
|
||||
}
|
||||
if (mmsTypeSpec.getBitString() != null) {
|
||||
int bitStringMaxLength = Math.abs(mmsTypeSpec.getBitString().intValue());
|
||||
|
||||
if (bitStringMaxLength == 13) {
|
||||
return new BdaQuality(ref, fc, null, false);
|
||||
} else if (bitStringMaxLength == 10) {
|
||||
return new BdaOptFlds(ref, fc);
|
||||
} else if (bitStringMaxLength == 6) {
|
||||
return new BdaTriggerConditions(ref, fc);
|
||||
} else if (bitStringMaxLength == 2) {
|
||||
if (fc == Fc.CO) {
|
||||
// if name == ctlVal
|
||||
if (ref.getName().charAt(1) == 't') {
|
||||
return new BdaTapCommand(ref, fc, null, false, false);
|
||||
}
|
||||
// name == Check
|
||||
else {
|
||||
return new BdaCheck(ref);
|
||||
}
|
||||
} else {
|
||||
return new BdaDoubleBitPos(ref, fc, null, false, false);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} else if (mmsTypeSpec.getInteger() != null) {
|
||||
switch (mmsTypeSpec.getInteger().intValue()) {
|
||||
case 8:
|
||||
return new BdaInt8(ref, fc, null, false, false);
|
||||
case 16:
|
||||
return new BdaInt16(ref, fc, null, false, false);
|
||||
case 32:
|
||||
return new BdaInt32(ref, fc, null, false, false);
|
||||
case 64:
|
||||
return new BdaInt64(ref, fc, null, false, false);
|
||||
case 128:
|
||||
return new BdaInt128(ref, fc, null, false, false);
|
||||
}
|
||||
} else if (mmsTypeSpec.getUnsigned() != null) {
|
||||
switch (mmsTypeSpec.getUnsigned().intValue()) {
|
||||
case 8:
|
||||
return new BdaInt8U(ref, fc, null, false, false);
|
||||
case 16:
|
||||
return new BdaInt16U(ref, fc, null, false, false);
|
||||
case 32:
|
||||
return new BdaInt32U(ref, fc, null, false, false);
|
||||
}
|
||||
} else if (mmsTypeSpec.getFloatingPoint() != null) {
|
||||
int floatSize = mmsTypeSpec.getFloatingPoint().getFormatWidth().intValue();
|
||||
if (floatSize == 32) {
|
||||
return new BdaFloat32(ref, fc, null, false, false);
|
||||
} else if (floatSize == 64) {
|
||||
return new BdaFloat64(ref, fc, null, false, false);
|
||||
}
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"FLOAT of size: " + floatSize + " is not supported.");
|
||||
} else if (mmsTypeSpec.getOctetString() != null) {
|
||||
int stringSize = mmsTypeSpec.getOctetString().intValue();
|
||||
if (stringSize > 255 || stringSize < -255) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"OCTET_STRING of size: " + stringSize + " is not supported.");
|
||||
}
|
||||
return new BdaOctetString(ref, fc, null, Math.abs(stringSize), false, false);
|
||||
|
||||
} else if (mmsTypeSpec.getVisibleString() != null) {
|
||||
int stringSize = mmsTypeSpec.getVisibleString().intValue();
|
||||
if (stringSize > 255 || stringSize < -255) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"VISIBLE_STRING of size: " + stringSize + " is not supported.");
|
||||
}
|
||||
return new BdaVisibleString(ref, fc, null, Math.abs(stringSize), false, false);
|
||||
} else if (mmsTypeSpec.getMMSString() != null) {
|
||||
int stringSize = mmsTypeSpec.getMMSString().intValue();
|
||||
if (stringSize > 255 || stringSize < -255) {
|
||||
throw new ServiceError(
|
||||
ServiceError.PARAMETER_VALUE_INAPPROPRIATE,
|
||||
"UNICODE_STRING of size: " + stringSize + " is not supported.");
|
||||
}
|
||||
return new BdaUnicodeString(ref, fc, null, Math.abs(stringSize), false, false);
|
||||
} else if (mmsTypeSpec.getUtcTime() != null) {
|
||||
return new BdaTimestamp(ref, fc, null, false, false);
|
||||
} else if (mmsTypeSpec.getBinaryTime() != null) {
|
||||
return new BdaEntryTime(ref, fc, null, false, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Identifier;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.ObjectName;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class DataSet implements Iterable<FcModelNode> {
|
||||
|
||||
private final String dataSetReference;
|
||||
private final List<FcModelNode> members;
|
||||
private final Map<Fc, Map<String, FcModelNode>> membersMap = new EnumMap<>(Fc.class);
|
||||
private final boolean deletable;
|
||||
private ObjectName mmsObjectName = null;
|
||||
|
||||
public DataSet(String dataSetReference, List<FcModelNode> members) {
|
||||
this(dataSetReference, members, true);
|
||||
}
|
||||
|
||||
public DataSet(String dataSetReference, List<FcModelNode> members, boolean deletable) {
|
||||
if (!dataSetReference.startsWith("@") && dataSetReference.indexOf('/') == -1) {
|
||||
throw new IllegalArgumentException(
|
||||
"DataSet reference "
|
||||
+ dataSetReference
|
||||
+ " is invalid. Must either start with @ or contain a slash.");
|
||||
}
|
||||
this.members = new ArrayList<>();
|
||||
this.dataSetReference = dataSetReference;
|
||||
this.deletable = deletable;
|
||||
|
||||
for (Fc myfc : Fc.values()) {
|
||||
membersMap.put(myfc, new LinkedHashMap<String, FcModelNode>());
|
||||
}
|
||||
|
||||
for (FcModelNode member : members) {
|
||||
this.members.add(member);
|
||||
membersMap.get(member.getFc()).put(member.getReference().toString(), member);
|
||||
}
|
||||
}
|
||||
|
||||
public String getReferenceStr() {
|
||||
return dataSetReference;
|
||||
}
|
||||
|
||||
public DataSet copy() {
|
||||
List<FcModelNode> membersCopy = new ArrayList<>(members.size());
|
||||
for (FcModelNode node : members) {
|
||||
membersCopy.add((FcModelNode) node.copy());
|
||||
}
|
||||
return new DataSet(dataSetReference, membersCopy, deletable);
|
||||
}
|
||||
|
||||
public FcModelNode getMember(ObjectReference memberReference, Fc fc) {
|
||||
if (fc != null) {
|
||||
return membersMap.get(fc).get(memberReference.toString());
|
||||
}
|
||||
for (FcModelNode member : members) {
|
||||
if (member.getReference().toString().equals(memberReference.toString())) {
|
||||
return member;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public FcModelNode getMember(int index) {
|
||||
return members.get(index);
|
||||
}
|
||||
|
||||
public List<FcModelNode> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Those DataSets defined in the SCL file are not deletable. All other DataSets are deletable.
|
||||
* Note that no Reports/Logs may be using the DataSet otherwise it cannot be deleted (but this
|
||||
* function will still return true).
|
||||
*
|
||||
* @return true if deletable
|
||||
*/
|
||||
public boolean isDeletable() {
|
||||
return deletable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<FcModelNode> iterator() {
|
||||
return members.iterator();
|
||||
}
|
||||
|
||||
public List<BasicDataAttribute> getBasicDataAttributes() {
|
||||
List<BasicDataAttribute> subBasicDataAttributes = new ArrayList<>();
|
||||
for (ModelNode member : members) {
|
||||
subBasicDataAttributes.addAll(member.getBasicDataAttributes());
|
||||
}
|
||||
return subBasicDataAttributes;
|
||||
}
|
||||
|
||||
ObjectName getMmsObjectName() {
|
||||
|
||||
if (mmsObjectName != null) {
|
||||
return mmsObjectName;
|
||||
}
|
||||
|
||||
if (dataSetReference.charAt(0) == '@') {
|
||||
mmsObjectName = new ObjectName();
|
||||
mmsObjectName.setAaSpecific(new Identifier(dataSetReference.getBytes(UTF_8)));
|
||||
return mmsObjectName;
|
||||
}
|
||||
|
||||
int slash = dataSetReference.indexOf('/');
|
||||
String domainID = dataSetReference.substring(0, slash);
|
||||
String itemID = dataSetReference.substring(slash + 1).replace('.', '$');
|
||||
|
||||
ObjectName.DomainSpecific domainSpecificObjectName = new ObjectName.DomainSpecific();
|
||||
domainSpecificObjectName.setDomainID(new Identifier(domainID.getBytes(UTF_8)));
|
||||
domainSpecificObjectName.setItemID(new Identifier(itemID.getBytes(UTF_8)));
|
||||
|
||||
mmsObjectName = new ObjectName();
|
||||
mmsObjectName.setDomainSpecific(domainSpecificObjectName);
|
||||
|
||||
return mmsObjectName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getReferenceStr());
|
||||
for (FcModelNode member : members) {
|
||||
sb.append("\n");
|
||||
sb.append(member.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public enum Fc {
|
||||
|
||||
// The following FCs are not part of this enum because they are not really
|
||||
// FCs and only defined in part 8-1:
|
||||
// RP (report), LG (log), BR (buffered report), GO, GS, MS, US
|
||||
|
||||
// FCs according to IEC 61850-7-2:
|
||||
/** Status information */
|
||||
ST,
|
||||
/** Measurands - analogue values */
|
||||
MX,
|
||||
/** Setpoint */
|
||||
SP,
|
||||
/** Substitution */
|
||||
SV,
|
||||
/** Configuration */
|
||||
CF,
|
||||
/** Description */
|
||||
DC,
|
||||
/** Setting group */
|
||||
SG,
|
||||
/** Setting group editable */
|
||||
SE,
|
||||
/** Service response / Service tracking */
|
||||
SR,
|
||||
/** Operate received */
|
||||
OR,
|
||||
/** Blocking */
|
||||
BL,
|
||||
/** Extended definition */
|
||||
EX,
|
||||
/** Control, deprecated but kept here for backward compatibility */
|
||||
CO,
|
||||
/** Unbuffered Reporting */
|
||||
RP,
|
||||
/** Buffered Reporting */
|
||||
BR;
|
||||
|
||||
public static Fc fromString(String fc) {
|
||||
try {
|
||||
return Fc.valueOf(fc);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class represents a functionally constraint DataObject. That means it has unique reference
|
||||
* and FunctionalConstraint. A DataObject as defined in part 7-3 is made up of 1..n FcDataObjects
|
||||
* where n is the number of different FunctionalConstraints that the children of the DataObject
|
||||
* have. An FcDataObject can have children of types FcDataObject, Array, ConstructedDataAttribute or
|
||||
* BasicDataAttribute.
|
||||
*
|
||||
* @author Stefan Feuerhahn
|
||||
*/
|
||||
public class FcDataObject extends FcModelNode {
|
||||
|
||||
public FcDataObject(ObjectReference objectReference, Fc fc, List<FcModelNode> children) {
|
||||
|
||||
this.children = new LinkedHashMap<>((int) ((children.size() / 0.75) + 1));
|
||||
this.objectReference = objectReference;
|
||||
for (ModelNode child : children) {
|
||||
this.children.put(child.getReference().getName(), child);
|
||||
child.setParent(this);
|
||||
}
|
||||
this.fc = fc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FcDataObject copy() {
|
||||
List<FcModelNode> childCopies = new ArrayList<>(children.size());
|
||||
for (ModelNode childNode : children.values()) {
|
||||
childCopies.add((FcModelNode) childNode.copy());
|
||||
}
|
||||
return new FcDataObject(objectReference, fc, childCopies);
|
||||
}
|
||||
|
||||
@Override
|
||||
Data getMmsDataObj() {
|
||||
Data.Structure dataStructure = new Data.Structure();
|
||||
List<Data> seq = dataStructure.getData();
|
||||
|
||||
for (ModelNode modelNode : getChildren()) {
|
||||
Data child = modelNode.getMmsDataObj();
|
||||
if (child == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to convert Child: " + modelNode.objectReference + " to MMS Data Object.");
|
||||
}
|
||||
seq.add(child);
|
||||
}
|
||||
if (seq.size() == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Converting ModelNode: "
|
||||
+ objectReference
|
||||
+ " to MMS Data Object resulted in Sequence of size zero.");
|
||||
}
|
||||
|
||||
Data data = new Data();
|
||||
data.setStructure(dataStructure);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {
|
||||
if (data.getStructure() == null) {
|
||||
throw new ServiceError(ServiceError.TYPE_CONFLICT, "expected type: structure");
|
||||
}
|
||||
if (data.getStructure().getData().size() != children.size()) {
|
||||
throw new ServiceError(
|
||||
ServiceError.TYPE_CONFLICT,
|
||||
"expected type: structure with " + children.size() + " elements");
|
||||
}
|
||||
|
||||
Iterator<Data> iterator = data.getStructure().getData().iterator();
|
||||
for (ModelNode child : children.values()) {
|
||||
child.setValueFromMmsDataObj(iterator.next());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccess;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection.SelectAccess;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection.SelectAccess.Component;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.BasicIdentifier;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Identifier;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.ObjectName;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Unsigned32;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.VariableDefs;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.VariableSpecification;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public abstract class FcModelNode extends ModelNode {
|
||||
|
||||
Fc fc;
|
||||
private VariableDefs.SEQUENCE variableDef = null;
|
||||
private ServerAssociation selected = null;
|
||||
private TimerTask task = null;
|
||||
|
||||
public Fc getFc() {
|
||||
return fc;
|
||||
}
|
||||
|
||||
boolean select(ServerAssociation association, Timer timer) {
|
||||
if (selected != null) {
|
||||
if (selected != association) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
selected = association;
|
||||
association.selects.add(this);
|
||||
}
|
||||
|
||||
ModelNode sboTimeoutNode =
|
||||
association.serverModel.findModelNode(objectReference, Fc.CF).getChild("sboTimeout");
|
||||
|
||||
if (sboTimeoutNode == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
long sboTimeout = ((BdaInt32U) sboTimeoutNode).getValue();
|
||||
|
||||
if (sboTimeout == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
class SelectResetTask extends TimerTask {
|
||||
ServerAssociation association;
|
||||
|
||||
SelectResetTask(ServerAssociation association) {
|
||||
this.association = association;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (association.serverModel) {
|
||||
if (task == this) {
|
||||
task = null;
|
||||
deselectAndRemove(association);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
}
|
||||
|
||||
task = new SelectResetTask(association);
|
||||
timer.schedule(task, sboTimeout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void deselectAndRemove(ServerAssociation association) {
|
||||
selected = null;
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
association.selects.remove(this);
|
||||
}
|
||||
|
||||
void deselect() {
|
||||
selected = null;
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
task = null;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isSelected() {
|
||||
return selected != null;
|
||||
}
|
||||
|
||||
boolean isSelectedBy(ServerAssociation association) {
|
||||
return selected == association;
|
||||
}
|
||||
|
||||
VariableDefs.SEQUENCE getMmsVariableDef() {
|
||||
|
||||
if (variableDef != null) {
|
||||
return variableDef;
|
||||
}
|
||||
|
||||
AlternateAccess alternateAccess = null;
|
||||
|
||||
StringBuilder preArrayIndexItemId = new StringBuilder(objectReference.get(1));
|
||||
preArrayIndexItemId.append("$");
|
||||
preArrayIndexItemId.append(fc);
|
||||
|
||||
int arrayIndexPosition = objectReference.getArrayIndexPosition();
|
||||
if (arrayIndexPosition != -1) {
|
||||
|
||||
for (int i = 2; i < arrayIndexPosition; i++) {
|
||||
preArrayIndexItemId.append("$");
|
||||
preArrayIndexItemId.append(objectReference.get(i));
|
||||
}
|
||||
|
||||
alternateAccess = new AlternateAccess();
|
||||
List<AlternateAccess.CHOICE> subSeqOfAlternateAccess = alternateAccess.getCHOICE();
|
||||
Unsigned32 indexBerInteger =
|
||||
new Unsigned32(Integer.parseInt(objectReference.get(arrayIndexPosition)));
|
||||
|
||||
if (arrayIndexPosition < (objectReference.size() - 1)) {
|
||||
// this reference points to a sub-node of an array element
|
||||
|
||||
StringBuilder postArrayIndexItemId =
|
||||
new StringBuilder(objectReference.get(arrayIndexPosition + 1));
|
||||
|
||||
for (int i = (arrayIndexPosition + 2); i < objectReference.size(); i++) {
|
||||
postArrayIndexItemId.append("$");
|
||||
postArrayIndexItemId.append(objectReference.get(i));
|
||||
}
|
||||
|
||||
BasicIdentifier subIndexReference =
|
||||
new BasicIdentifier(postArrayIndexItemId.toString().getBytes(UTF_8));
|
||||
|
||||
AlternateAccessSelection.SelectAccess subIndexReferenceSelectAccess =
|
||||
new AlternateAccessSelection.SelectAccess();
|
||||
Component component = new Component();
|
||||
component.setBasic(subIndexReference);
|
||||
subIndexReferenceSelectAccess.setComponent(component);
|
||||
|
||||
AlternateAccessSelection subIndexReferenceAlternateAccessSelection =
|
||||
new AlternateAccessSelection();
|
||||
subIndexReferenceAlternateAccessSelection.setSelectAccess(subIndexReferenceSelectAccess);
|
||||
|
||||
AlternateAccess.CHOICE subIndexReferenceAlternateAccessSubChoice =
|
||||
new AlternateAccess.CHOICE();
|
||||
subIndexReferenceAlternateAccessSubChoice.setUnnamed(
|
||||
subIndexReferenceAlternateAccessSelection);
|
||||
|
||||
AlternateAccess subIndexReferenceAlternateAccess = new AlternateAccess();
|
||||
|
||||
List<AlternateAccess.CHOICE> subIndexReferenceAlternateAccessSubSeqOf =
|
||||
subIndexReferenceAlternateAccess.getCHOICE();
|
||||
subIndexReferenceAlternateAccessSubSeqOf.add(subIndexReferenceAlternateAccessSubChoice);
|
||||
|
||||
// set array index:
|
||||
|
||||
AlternateAccessSelection.SelectAlternateAccess.AccessSelection indexAccessSelectionChoice =
|
||||
new AlternateAccessSelection.SelectAlternateAccess.AccessSelection();
|
||||
indexAccessSelectionChoice.setIndex(indexBerInteger);
|
||||
|
||||
AlternateAccessSelection.SelectAlternateAccess indexAndLowerReferenceSelectAlternateAccess =
|
||||
new AlternateAccessSelection.SelectAlternateAccess();
|
||||
indexAndLowerReferenceSelectAlternateAccess.setAccessSelection(indexAccessSelectionChoice);
|
||||
indexAndLowerReferenceSelectAlternateAccess.setAlternateAccess(
|
||||
subIndexReferenceAlternateAccess);
|
||||
|
||||
AlternateAccessSelection indexAndLowerReferenceAlternateAccessSelection =
|
||||
new AlternateAccessSelection();
|
||||
indexAndLowerReferenceAlternateAccessSelection.setSelectAlternateAccess(
|
||||
indexAndLowerReferenceSelectAlternateAccess);
|
||||
|
||||
AlternateAccess.CHOICE indexAndLowerReferenceAlternateAccessChoice =
|
||||
new AlternateAccess.CHOICE();
|
||||
indexAndLowerReferenceAlternateAccessChoice.setUnnamed(
|
||||
indexAndLowerReferenceAlternateAccessSelection);
|
||||
|
||||
subSeqOfAlternateAccess.add(indexAndLowerReferenceAlternateAccessChoice);
|
||||
|
||||
} else {
|
||||
SelectAccess selectAccess = new SelectAccess();
|
||||
selectAccess.setIndex(indexBerInteger);
|
||||
|
||||
AlternateAccessSelection alternateAccessSelection = new AlternateAccessSelection();
|
||||
alternateAccessSelection.setSelectAccess(selectAccess);
|
||||
|
||||
AlternateAccess.CHOICE alternateAccessChoice = new AlternateAccess.CHOICE();
|
||||
alternateAccessChoice.setUnnamed(alternateAccessSelection);
|
||||
|
||||
subSeqOfAlternateAccess.add(alternateAccessChoice);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
for (int i = 2; i < objectReference.size(); i++) {
|
||||
preArrayIndexItemId.append("$");
|
||||
preArrayIndexItemId.append(objectReference.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
ObjectName.DomainSpecific domainSpecificObjectName = new ObjectName.DomainSpecific();
|
||||
domainSpecificObjectName.setDomainID(new Identifier(objectReference.get(0).getBytes(UTF_8)));
|
||||
domainSpecificObjectName.setItemID(
|
||||
new Identifier(preArrayIndexItemId.toString().getBytes(UTF_8)));
|
||||
|
||||
ObjectName objectName = new ObjectName();
|
||||
objectName.setDomainSpecific(domainSpecificObjectName);
|
||||
|
||||
VariableSpecification varSpec = new VariableSpecification();
|
||||
varSpec.setName(objectName);
|
||||
|
||||
variableDef = new VariableDefs.SEQUENCE();
|
||||
variableDef.setAlternateAccess(alternateAccess);
|
||||
variableDef.setVariableSpecification(varSpec);
|
||||
|
||||
return variableDef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getReference().toString()).append(" [").append(fc).append("]");
|
||||
for (ModelNode childNode : children.values()) {
|
||||
sb.append("\n");
|
||||
sb.append(childNode.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
/** Contains file information received by the GetFileDirectory service */
|
||||
public class FileInformation {
|
||||
|
||||
private final String filename;
|
||||
|
||||
private final long fileSize;
|
||||
|
||||
private final Calendar lastModified;
|
||||
|
||||
public FileInformation(String filename, long fileSize, Calendar lastModified) {
|
||||
super();
|
||||
this.filename = filename;
|
||||
this.fileSize = fileSize;
|
||||
this.lastModified = lastModified;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public long getFileSize() {
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time stamp of last modification. As it is an optional attribute the return value can be
|
||||
* null
|
||||
*
|
||||
* @return the time stamp of last modification, or null if the time stamp is not present
|
||||
*/
|
||||
public Calendar getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
/** 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);
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
public final class LogicalDevice extends ModelNode {
|
||||
|
||||
public LogicalDevice(ObjectReference objectReference, List<LogicalNode> logicalNodes) {
|
||||
children = new LinkedHashMap<>((int) ((logicalNodes.size() / 0.75) + 1));
|
||||
this.objectReference = objectReference;
|
||||
for (LogicalNode logicalNode : logicalNodes) {
|
||||
children.put(logicalNode.getReference().getName(), logicalNode);
|
||||
logicalNode.setParent(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicalDevice copy() {
|
||||
List<LogicalNode> childCopies = new ArrayList<>(children.size());
|
||||
for (ModelNode childNode : children.values()) {
|
||||
childCopies.add((LogicalNode) childNode.copy());
|
||||
}
|
||||
return new LogicalDevice(objectReference, childCopies);
|
||||
}
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class LogicalNode extends ModelNode {
|
||||
|
||||
private final Map<Fc, Map<String, FcDataObject>> fcDataObjects = new EnumMap<>(Fc.class);
|
||||
|
||||
private final Map<String, Urcb> urcbs = new HashMap<>();
|
||||
private final Map<String, Brcb> brcbs = new HashMap<>();
|
||||
|
||||
public LogicalNode(ObjectReference objectReference, List<FcDataObject> fcDataObjects) {
|
||||
children = new LinkedHashMap<>();
|
||||
for (Fc fc : Fc.values()) {
|
||||
this.fcDataObjects.put(fc, new LinkedHashMap<String, FcDataObject>());
|
||||
}
|
||||
|
||||
this.objectReference = objectReference;
|
||||
|
||||
for (FcDataObject fcDataObject : fcDataObjects) {
|
||||
children.put(
|
||||
fcDataObject.getReference().getName() + fcDataObject.fc.toString(), fcDataObject);
|
||||
this.fcDataObjects
|
||||
.get(fcDataObject.getFc())
|
||||
.put(fcDataObject.getReference().getName(), fcDataObject);
|
||||
fcDataObject.setParent(this);
|
||||
if (fcDataObject.getFc() == Fc.RP) {
|
||||
addUrcb((Urcb) fcDataObject, false);
|
||||
} else if (fcDataObject.getFc() == Fc.BR) {
|
||||
addBrcb((Brcb) fcDataObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicalNode copy() {
|
||||
|
||||
List<FcDataObject> dataObjectsCopy = new ArrayList<>();
|
||||
for (ModelNode obj : children.values()) {
|
||||
dataObjectsCopy.add((FcDataObject) obj.copy());
|
||||
}
|
||||
|
||||
LogicalNode copy = new LogicalNode(objectReference, dataObjectsCopy);
|
||||
return copy;
|
||||
}
|
||||
|
||||
public List<FcDataObject> getChildren(Fc fc) {
|
||||
Map<String, FcDataObject> requestedDataObjectsMap = fcDataObjects.get(fc);
|
||||
if (requestedDataObjectsMap == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Collection<FcDataObject> fcChildren = requestedDataObjectsMap.values();
|
||||
if (fcChildren.size() == 0) {
|
||||
return null;
|
||||
} else {
|
||||
return new ArrayList<>(fcChildren);
|
||||
}
|
||||
}
|
||||
|
||||
void addUrcb(Urcb urcb, boolean addDataSet) {
|
||||
urcbs.put(urcb.getReference().getName(), urcb);
|
||||
if (addDataSet) {
|
||||
String dataSetRef = urcb.getDatSet().getStringValue();
|
||||
if (dataSetRef != null) {
|
||||
urcb.dataSet =
|
||||
((ServerModel) getParent().getParent()).getDataSet(dataSetRef.replace('$', '.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<Urcb> getUrcbs() {
|
||||
return urcbs.values();
|
||||
}
|
||||
|
||||
public Urcb getUrcb(String urcbName) {
|
||||
return urcbs.get(urcbName);
|
||||
}
|
||||
|
||||
void addBrcb(Brcb brcb) {
|
||||
brcbs.put(brcb.getReference().getName(), brcb);
|
||||
}
|
||||
|
||||
public Brcb getBrcb(String brcbName) {
|
||||
return brcbs.get(brcbName);
|
||||
}
|
||||
|
||||
public Collection<Brcb> getBrcbs() {
|
||||
return brcbs.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelNode getChild(String childName, Fc fc) {
|
||||
if (fc != null) {
|
||||
return fcDataObjects.get(fc).get(childName);
|
||||
}
|
||||
for (Map<String, FcDataObject> map : fcDataObjects.values()) {
|
||||
FcDataObject fcDataObject = map.get(childName);
|
||||
if (fcDataObject != null) {
|
||||
return fcDataObject;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getReference().toString());
|
||||
for (Map<String, FcDataObject> fcChildNodes : fcDataObjects.values()) {
|
||||
for (ModelNode childNode : fcChildNodes.values()) {
|
||||
sb.append("\n");
|
||||
sb.append(childNode.toString());
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Identifier;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription.Structure;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeDescription.Structure.Components;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.TypeSpecification;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class ModelNode implements Iterable<ModelNode> {
|
||||
|
||||
protected ObjectReference objectReference;
|
||||
protected Map<String, ModelNode> children;
|
||||
ModelNode parent;
|
||||
|
||||
/**
|
||||
* Returns a copy of model node with all of its children. Creates new BasicDataAttribute values
|
||||
* but reuses ObjectReferences, FunctionalConstraints.
|
||||
*
|
||||
* @return a copy of model node with all of its children.
|
||||
*/
|
||||
public abstract ModelNode copy();
|
||||
|
||||
/**
|
||||
* Returns the child node with the given name. Will always return null if called on a logical node
|
||||
* because a logical node need the functional constraint to uniquely identify a child. For logical
|
||||
* nodes use <code>getChild(String name, Fc fc)</code> instead.
|
||||
*
|
||||
* @param name the name of the requested child node
|
||||
* @return the child node with the given name.
|
||||
*/
|
||||
public ModelNode getChild(String name) {
|
||||
return getChild(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child node with the given name and functional constraint. The fc is ignored if this
|
||||
* function is called on any model node other than logical node.
|
||||
*
|
||||
* @param name the name of the requested child node
|
||||
* @param fc the functional constraint of the requested child node
|
||||
* @return the child node with the given name and functional constrain
|
||||
*/
|
||||
public ModelNode getChild(String name, Fc fc) {
|
||||
return children.get(name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<ModelNode> getChildren() {
|
||||
if (children == null) {
|
||||
return null;
|
||||
}
|
||||
return children.values();
|
||||
}
|
||||
|
||||
protected Iterator<Iterator<? extends ModelNode>> getIterators() {
|
||||
List<Iterator<? extends ModelNode>> iterators = new ArrayList<>();
|
||||
if (children != null) {
|
||||
iterators.add(children.values().iterator());
|
||||
}
|
||||
return iterators.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reference of the model node.
|
||||
*
|
||||
* @return the reference of the model node.
|
||||
*/
|
||||
public ObjectReference getReference() {
|
||||
return objectReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the model node.
|
||||
*
|
||||
* @return the name of the model node.
|
||||
*/
|
||||
public String getName() {
|
||||
return objectReference.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<ModelNode> iterator() {
|
||||
return children.values().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all leaf nodes (basic data attributes) contained in the subtree of this model
|
||||
* node.
|
||||
*
|
||||
* @return a list of all leaf nodes (basic data attributes) contained in the subtree of this model
|
||||
* node.
|
||||
*/
|
||||
public List<BasicDataAttribute> getBasicDataAttributes() {
|
||||
List<BasicDataAttribute> subBasicDataAttributes = new ArrayList<>();
|
||||
for (ModelNode child : children.values()) {
|
||||
subBasicDataAttributes.addAll(child.getBasicDataAttributes());
|
||||
}
|
||||
return subBasicDataAttributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getReference().toString());
|
||||
for (ModelNode childNode : children.values()) {
|
||||
sb.append("\n");
|
||||
sb.append(childNode.toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent node of this node.
|
||||
*
|
||||
* @return the parent node of this node.
|
||||
*/
|
||||
public ModelNode getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
void setParent(ModelNode parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
Data getMmsDataObj() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void setValueFromMmsDataObj(Data data) throws ServiceError {}
|
||||
|
||||
TypeDescription getMmsTypeSpec() {
|
||||
|
||||
Components componentsSequenceType = new Components();
|
||||
|
||||
List<TypeDescription.Structure.Components.SEQUENCE> structComponents =
|
||||
componentsSequenceType.getSEQUENCE();
|
||||
for (ModelNode child : children.values()) {
|
||||
TypeSpecification typeSpecification = new TypeSpecification();
|
||||
typeSpecification.setTypeDescription(child.getMmsTypeSpec());
|
||||
|
||||
TypeDescription.Structure.Components.SEQUENCE component =
|
||||
new TypeDescription.Structure.Components.SEQUENCE();
|
||||
component.setComponentName(new Identifier(child.getName().getBytes(UTF_8)));
|
||||
component.setComponentType(typeSpecification);
|
||||
|
||||
structComponents.add(component);
|
||||
}
|
||||
|
||||
Structure structure = new Structure();
|
||||
structure.setComponents(componentsSequenceType);
|
||||
|
||||
TypeDescription typeDescription = new TypeDescription();
|
||||
typeDescription.setStructure(structure);
|
||||
|
||||
return typeDescription;
|
||||
}
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/** ObjectReference syntax: LDName/LNName.DOName[.Name[. ...]] */
|
||||
public final class ObjectReference implements Iterable<String> {
|
||||
|
||||
private final String objectReference;
|
||||
private List<String> nodeNames = null;
|
||||
|
||||
// if the ObjectReference contains an array index this variable will save
|
||||
// its position in the nodeNames List
|
||||
private int arrayIndexPosition = -1;
|
||||
|
||||
public ObjectReference(String objectReference) {
|
||||
if (objectReference == null || objectReference.isEmpty()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.objectReference = objectReference;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name part of the reference.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
return nodeNames.get(nodeNames.size() - 1);
|
||||
}
|
||||
|
||||
public String getLdName() {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
|
||||
return nodeNames.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return objectReference;
|
||||
}
|
||||
|
||||
public boolean isLogicalDeviceRef() {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
return (nodeNames.size() == 1);
|
||||
}
|
||||
|
||||
public boolean isLogicalNodeRef() {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
return (nodeNames.size() == 2);
|
||||
}
|
||||
|
||||
public boolean isDataRef() {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
return (nodeNames.size() > 2);
|
||||
}
|
||||
|
||||
int getArrayIndexPosition() {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
return arrayIndexPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> iterator() {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
return nodeNames.iterator();
|
||||
}
|
||||
|
||||
public String get(int i) {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
return nodeNames.get(i);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
if (nodeNames == null) {
|
||||
parseForNameList();
|
||||
}
|
||||
return nodeNames.size();
|
||||
}
|
||||
|
||||
private void parseForNameList() {
|
||||
|
||||
nodeNames = new ArrayList<>();
|
||||
|
||||
int lastDelim = -1;
|
||||
int nextDelim = objectReference.indexOf('/');
|
||||
if (nextDelim == -1) {
|
||||
nodeNames.add(objectReference.substring(lastDelim + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
nodeNames.add(objectReference.substring(lastDelim + 1, nextDelim));
|
||||
|
||||
int dotIndex = -1;
|
||||
int openingbracketIndex = -1;
|
||||
int closingbracketIndex = -1;
|
||||
while (true) {
|
||||
lastDelim = nextDelim;
|
||||
if (dotIndex == -1) {
|
||||
dotIndex = objectReference.indexOf('.', lastDelim + 1);
|
||||
if (dotIndex == -1) {
|
||||
dotIndex = objectReference.length();
|
||||
}
|
||||
}
|
||||
if (openingbracketIndex == -1) {
|
||||
openingbracketIndex = objectReference.indexOf('(', lastDelim + 1);
|
||||
if (openingbracketIndex == -1) {
|
||||
openingbracketIndex = objectReference.length();
|
||||
}
|
||||
}
|
||||
if (closingbracketIndex == -1) {
|
||||
closingbracketIndex = objectReference.indexOf(')', lastDelim + 1);
|
||||
if (closingbracketIndex == -1) {
|
||||
closingbracketIndex = objectReference.length();
|
||||
}
|
||||
}
|
||||
|
||||
if (dotIndex == openingbracketIndex && dotIndex == closingbracketIndex) {
|
||||
nodeNames.add(objectReference.substring(lastDelim + 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (dotIndex < openingbracketIndex && dotIndex < closingbracketIndex) {
|
||||
nextDelim = dotIndex;
|
||||
dotIndex = -1;
|
||||
} else if (openingbracketIndex < dotIndex && openingbracketIndex < closingbracketIndex) {
|
||||
nextDelim = openingbracketIndex;
|
||||
openingbracketIndex = -1;
|
||||
arrayIndexPosition = nodeNames.size() + 1;
|
||||
} else if (closingbracketIndex < dotIndex && closingbracketIndex < openingbracketIndex) {
|
||||
if (closingbracketIndex == (objectReference.length() - 1)) {
|
||||
nodeNames.add(objectReference.substring(lastDelim + 1, closingbracketIndex));
|
||||
return;
|
||||
}
|
||||
nextDelim = closingbracketIndex + 1;
|
||||
closingbracketIndex = -1;
|
||||
dotIndex = -1;
|
||||
nodeNames.add(objectReference.substring(lastDelim + 1, nextDelim - 1));
|
||||
continue;
|
||||
}
|
||||
nodeNames.add(objectReference.substring(lastDelim + 1, nextDelim));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class Rcb extends FcDataObject {
|
||||
|
||||
DataSet dataSet;
|
||||
|
||||
protected Rcb(ObjectReference objectReference, Fc fc, List<FcModelNode> children) {
|
||||
super(objectReference, fc, children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the RptID (Report ID). The RptID will be included in every report sent by the server. If
|
||||
* it is equal to NULL, then the RptID sent will be equal to the reference of the RCB.
|
||||
*
|
||||
* @return the report ID
|
||||
*/
|
||||
public BdaVisibleString getRptId() {
|
||||
return (BdaVisibleString) children.get("RptID");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the boolean value which states whether reporting is enabled.
|
||||
*
|
||||
* @return BdaBoolean that contains true as value if reporting is enabled.
|
||||
*/
|
||||
public BdaBoolean getRptEna() {
|
||||
return (BdaBoolean) children.get("RptEna");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object reference of the DataSet that is to be monitored for reporting events.
|
||||
*
|
||||
* @return the object reference of the DataSet
|
||||
*/
|
||||
public BdaVisibleString getDatSet() {
|
||||
return (BdaVisibleString) children.get("DatSet");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration revision The attribute ConfRev shall represent a count of the number of times
|
||||
* that the configuration of the DATA-SET referenced by DatSet has been changed. Changes that
|
||||
* shall be counted are:
|
||||
*
|
||||
* <ul>
|
||||
* <li>any deletion of a member of the DATA-SET;
|
||||
* <li>the reordering of members of the DATA-SET; and
|
||||
* <li>Successful SetBRCBValues of the DatSet attribute where the DatSet attribute value
|
||||
* changes.
|
||||
* </ul>
|
||||
*
|
||||
* The counter shall be incremented when the configuration changes. At configuration time, the
|
||||
* configuration tool will be responsible for incrementing/maintaining the ConfRev value. When
|
||||
* configuration changes occur due to SetBRCBValues, the IED shall be responsible for incrementing
|
||||
* the value of ConfRev.
|
||||
*
|
||||
* @return the configuration revision
|
||||
*/
|
||||
public BdaInt32U getConfRev() {
|
||||
return (BdaInt32U) children.get("ConfRev");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the optional fields parameter which specifies which optional fields should be included in
|
||||
* the reports sent by this RCB.
|
||||
*
|
||||
* @return the optional fields parameter
|
||||
*/
|
||||
public BdaOptFlds getOptFlds() {
|
||||
return (BdaOptFlds) children.get("OptFlds");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer time - The attribute BufTm (see Figure 27) shall specify the time interval in
|
||||
* milliseconds for the buffering of internal notifications caused by data-change (dchg),
|
||||
* quality-change (qchg), data update (dupd) by the BRCB for inclusion into a single report.
|
||||
*
|
||||
* @return the buffer time
|
||||
*/
|
||||
public BdaInt32U getBufTm() {
|
||||
return (BdaInt32U) children.get("BufTm");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the sequence number - The attribute SqNum shall specify the sequence number for each BRCB
|
||||
* that has report enable set to TRUE. This number is to be incremented by the BRCB for each
|
||||
* report generated and sent. The increment shall occur once the BRCB has formatted the report and
|
||||
* requested for transmission.
|
||||
*
|
||||
* @return the sequence number
|
||||
*/
|
||||
public BdaInt8U getSqNum() {
|
||||
return (BdaInt8U) children.get("SqNum");
|
||||
}
|
||||
|
||||
public BdaTriggerConditions getTrgOps() {
|
||||
return (BdaTriggerConditions) children.get("TrgOps");
|
||||
}
|
||||
|
||||
public BdaInt32U getIntgPd() {
|
||||
return (BdaInt32U) children.get("IntgPd");
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public class ReportEntryData {
|
||||
|
||||
/** Not specified in IEC61850 but useful for data persistence */
|
||||
private long id;
|
||||
/** Reference to to {@link DataSet}-member */
|
||||
private String dataRef;
|
||||
/** Attribute value to be reported */
|
||||
private ModelNode value;
|
||||
/** Trigger that caused the data to be put into the report */
|
||||
// private TriggerConditions reasonCode;
|
||||
private ReasonCode reasonCode;
|
||||
/** Backreference to report */
|
||||
private Report report;
|
||||
|
||||
public String getDataRef() {
|
||||
return dataRef;
|
||||
}
|
||||
|
||||
public void setDataRef(String dataRef) {
|
||||
this.dataRef = dataRef;
|
||||
}
|
||||
|
||||
public ModelNode getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(ModelNode value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public ReasonCode getReasonCode() {
|
||||
return reasonCode;
|
||||
}
|
||||
|
||||
public void setReasonCode(ReasonCode reasonCode) {
|
||||
this.reasonCode = reasonCode;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Report getReport() {
|
||||
return report;
|
||||
}
|
||||
|
||||
public void setReport(Report report) {
|
||||
this.report = report;
|
||||
}
|
||||
|
||||
public enum ReasonCode {
|
||||
DCHG,
|
||||
QCHG,
|
||||
DUPD,
|
||||
INTEGRITY,
|
||||
GI,
|
||||
APPTRIGGER
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class SclParseException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 8499804369026418082L;
|
||||
|
||||
public SclParseException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
public SclParseException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ServerEventListener {
|
||||
|
||||
/**
|
||||
* The write callback function is called if one of more basic data attributes are written using
|
||||
* either the setDataValue, setDataSetValues or control services. If the complete write process
|
||||
* was successful write returns either an empty list or null. If an error occurs writing one or
|
||||
* more attributes then a list shall be returned that is of equal size as the list of basic data
|
||||
* attributes. The returned list's element shall be null if writing the corresponding BDA was
|
||||
* successful and a service error otherwise.
|
||||
*
|
||||
* @param bdas the list of basic data attributes that are to be set.
|
||||
* @return a list of service errors indicating errors writing the corresponding basic data
|
||||
* attributes.
|
||||
*/
|
||||
List<ServiceError> write(List<BasicDataAttribute> bdas);
|
||||
|
||||
void serverStoppedListening(ServerSap serverSAP);
|
||||
}
|
@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.AlternateAccessSelection;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.ObjectName;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.ObjectName.DomainSpecific;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.VariableDefs;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public final class ServerModel extends ModelNode {
|
||||
|
||||
private final Map<String, DataSet> dataSets = new LinkedHashMap<>();
|
||||
|
||||
private final Map<String, Urcb> urcbs = new HashMap<>();
|
||||
private final Map<String, Brcb> brcbs = new HashMap<>();
|
||||
|
||||
public ServerModel(List<LogicalDevice> logicalDevices, Collection<DataSet> dataSets) {
|
||||
children = new LinkedHashMap<>();
|
||||
objectReference = null;
|
||||
for (LogicalDevice logicalDevice : logicalDevices) {
|
||||
children.put(logicalDevice.getReference().getName(), logicalDevice);
|
||||
logicalDevice.setParent(this);
|
||||
}
|
||||
|
||||
if (dataSets != null) {
|
||||
addDataSets(dataSets);
|
||||
}
|
||||
|
||||
for (LogicalDevice ld : logicalDevices) {
|
||||
for (ModelNode ln : ld.getChildren()) {
|
||||
for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
|
||||
urcbs.put(urcb.getReference().toString(), urcb);
|
||||
urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
|
||||
}
|
||||
for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
|
||||
brcbs.put(brcb.getReference().toString(), brcb);
|
||||
brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerModel copy() {
|
||||
List<LogicalDevice> childCopies = new ArrayList<>(children.size());
|
||||
for (ModelNode childNode : children.values()) {
|
||||
childCopies.add((LogicalDevice) childNode.copy());
|
||||
}
|
||||
|
||||
List<DataSet> dataSetCopies = new ArrayList<>(dataSets.size());
|
||||
for (DataSet dataSet : dataSets.values()) {
|
||||
dataSetCopies.add(dataSet);
|
||||
}
|
||||
|
||||
return new ServerModel(childCopies, dataSetCopies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data set with the given reference. Return null if none is found.
|
||||
*
|
||||
* @param reference the reference of the requested data set.
|
||||
* @return the data set with the given reference.
|
||||
*/
|
||||
public DataSet getDataSet(String reference) {
|
||||
return dataSets.get(reference);
|
||||
}
|
||||
|
||||
void addDataSet(DataSet dataSet) {
|
||||
dataSets.put(dataSet.getReferenceStr().replace('$', '.'), dataSet);
|
||||
for (ModelNode ld : children.values()) {
|
||||
for (ModelNode ln : ld.getChildren()) {
|
||||
for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
|
||||
urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
|
||||
}
|
||||
for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
|
||||
brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addDataSets(Collection<DataSet> dataSets) {
|
||||
for (DataSet dataSet : dataSets) {
|
||||
addDataSet(dataSet);
|
||||
}
|
||||
for (ModelNode ld : children.values()) {
|
||||
for (ModelNode ln : ld.getChildren()) {
|
||||
for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
|
||||
urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
|
||||
}
|
||||
for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
|
||||
brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<String> getDataSetNames(String ldName) {
|
||||
// TODO make thread save
|
||||
List<String> dataSetNames = new ArrayList<>();
|
||||
for (String dataSetRef : dataSets.keySet()) {
|
||||
if (dataSetRef.startsWith(ldName)) {
|
||||
dataSetNames.add(dataSetRef.substring(dataSetRef.indexOf('/') + 1).replace('.', '$'));
|
||||
}
|
||||
}
|
||||
return dataSetNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of all data sets that exist in this model.
|
||||
*
|
||||
* @return a collection of all data sets
|
||||
*/
|
||||
public Collection<DataSet> getDataSets() {
|
||||
return dataSets.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dataSetReference the data set reference
|
||||
* @return returns the DataSet that was removed, null if no DataSet with the given reference was
|
||||
* found or the data set is not deletable.
|
||||
*/
|
||||
DataSet removeDataSet(String dataSetReference) {
|
||||
DataSet dataSet = dataSets.get(dataSetReference);
|
||||
if (dataSet == null || !dataSet.isDeletable()) {
|
||||
return null;
|
||||
}
|
||||
DataSet removedDataSet = dataSets.remove(dataSetReference);
|
||||
for (ModelNode ld : children.values()) {
|
||||
for (ModelNode ln : ld.getChildren()) {
|
||||
for (Urcb urcb : ((LogicalNode) ln).getUrcbs()) {
|
||||
urcb.dataSet = getDataSet(urcb.getDatSet().getStringValue().replace('$', '.'));
|
||||
}
|
||||
for (Brcb brcb : ((LogicalNode) ln).getBrcbs()) {
|
||||
brcb.dataSet = getDataSet(brcb.getDatSet().getStringValue().replace('$', '.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
return removedDataSet;
|
||||
}
|
||||
|
||||
void addUrcb(Urcb urcb) {
|
||||
urcbs.put(urcb.getReference().getName(), urcb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unbuffered report control block (URCB) with the given reference.
|
||||
*
|
||||
* @param reference the reference of the requested URCB.
|
||||
* @return the reference to the requested URCB or null if none with the given reference is found.
|
||||
*/
|
||||
public Urcb getUrcb(String reference) {
|
||||
return urcbs.get(reference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of all unbuffered report control blocks (URCB) that exist in this model.
|
||||
*
|
||||
* @return a collection of all unbuffered report control blocks (URCB)
|
||||
*/
|
||||
public Collection<Urcb> getUrcbs() {
|
||||
return urcbs.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the buffered report control block (BRCB) with the given reference.
|
||||
*
|
||||
* @param reference the reference of the requested BRCB.
|
||||
* @return the reference to the requested BRCB or null if none with the given reference is found.
|
||||
*/
|
||||
public Brcb getBrcb(String reference) {
|
||||
return brcbs.get(reference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of all buffered report control blocks (BRCB) that exist in this model.
|
||||
*
|
||||
* @return a collection of all buffered report control blocks (BRCB)
|
||||
*/
|
||||
public Collection<Brcb> getBrcbs() {
|
||||
return brcbs.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (ModelNode logicalDevice : children.values()) {
|
||||
sb.append(logicalDevice.toString());
|
||||
}
|
||||
sb.append("\n\n\n---------------------\nURCBs:");
|
||||
for (Urcb urcb : getUrcbs()) {
|
||||
sb.append("\n\n").append(urcb);
|
||||
}
|
||||
|
||||
sb.append("\n\n\n---------------------\nBRCBs:");
|
||||
for (Brcb brcb : getBrcbs()) {
|
||||
sb.append("\n\n").append(brcb);
|
||||
}
|
||||
|
||||
sb.append("\n\n\n---------------------\nData sets:");
|
||||
for (DataSet dataSet : getDataSets()) {
|
||||
sb.append("\n\n").append(dataSet);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches and returns the model node with the given object reference and FC. If searching for
|
||||
* Logical Devices and Logical Nodes the given fc parameter may be <code>null</code>.
|
||||
*
|
||||
* @param objectReference the object reference of the node that is being searched for. It has a
|
||||
* syntax like "ldname/ln.do....".
|
||||
* @param fc the functional constraint of the requested model node. May be null for Logical Device
|
||||
* and Logical Node references.
|
||||
* @return the model node if it was found or null otherwise
|
||||
*/
|
||||
public ModelNode findModelNode(ObjectReference objectReference, Fc fc) {
|
||||
|
||||
ModelNode currentNode = this;
|
||||
Iterator<String> searchedNodeReferenceIterator = objectReference.iterator();
|
||||
|
||||
while (searchedNodeReferenceIterator.hasNext()) {
|
||||
currentNode = currentNode.getChild(searchedNodeReferenceIterator.next(), fc);
|
||||
if (currentNode == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches and returns the model node with the given object reference and FC. If searching for
|
||||
* Logical Devices and Logical Nodes the given fc parameter may be <code>null</code>.
|
||||
*
|
||||
* @param objectReference the object reference of the node that is being searched for. It has a
|
||||
* syntax like "ldname/ln.do....".
|
||||
* @param fc the functional constraint of the requested model node. May be null for Logical Device
|
||||
* and Logical Node references.
|
||||
* @return the model node if it was found or null otherwise
|
||||
*/
|
||||
public ModelNode findModelNode(String objectReference, Fc fc) {
|
||||
return findModelNode(new ObjectReference(objectReference), fc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subModelNode that is referenced by the given VariableDef. Return null in case the
|
||||
* referenced ModelNode is not found.
|
||||
*
|
||||
* @param variableDef the variableDef
|
||||
* @return the subModelNode that is referenced by the given VariableDef
|
||||
* @throws ServiceError if an error occurs
|
||||
*/
|
||||
FcModelNode getNodeFromVariableDef(VariableDefs.SEQUENCE variableDef) throws ServiceError {
|
||||
|
||||
ObjectName objectName = variableDef.getVariableSpecification().getName();
|
||||
|
||||
if (objectName == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
|
||||
"name in objectName is not selected");
|
||||
}
|
||||
|
||||
DomainSpecific domainSpecific = objectName.getDomainSpecific();
|
||||
|
||||
if (domainSpecific == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
|
||||
"domain_specific in name is not selected");
|
||||
}
|
||||
|
||||
ModelNode modelNode = getChild(domainSpecific.getDomainID().toString());
|
||||
|
||||
if (modelNode == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String mmsItemId = domainSpecific.getItemID().toString();
|
||||
int index1 = mmsItemId.indexOf('$');
|
||||
|
||||
if (index1 == -1) {
|
||||
throw new ServiceError(
|
||||
ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
|
||||
"invalid mms item id: " + domainSpecific.getItemID());
|
||||
}
|
||||
|
||||
LogicalNode ln = (LogicalNode) modelNode.getChild(mmsItemId.substring(0, index1));
|
||||
|
||||
if (ln == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int index2 = mmsItemId.indexOf('$', index1 + 1);
|
||||
|
||||
if (index2 == -1) {
|
||||
throw new ServiceError(
|
||||
ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT, "invalid mms item id");
|
||||
}
|
||||
|
||||
Fc fc = Fc.fromString(mmsItemId.substring(index1 + 1, index2));
|
||||
|
||||
if (fc == null) {
|
||||
throw new ServiceError(
|
||||
ServiceError.FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT,
|
||||
"unknown functional constraint: " + mmsItemId.substring(index1 + 1, index2));
|
||||
}
|
||||
|
||||
index1 = index2;
|
||||
|
||||
index2 = mmsItemId.indexOf('$', index1 + 1);
|
||||
|
||||
if (index2 == -1) {
|
||||
if (fc == Fc.RP) {
|
||||
return ln.getUrcb(mmsItemId.substring(index1 + 1));
|
||||
}
|
||||
if (fc == Fc.BR) {
|
||||
return ln.getBrcb(mmsItemId.substring(index1 + 1));
|
||||
}
|
||||
return (FcModelNode) ln.getChild(mmsItemId.substring(index1 + 1), fc);
|
||||
}
|
||||
|
||||
if (fc == Fc.RP) {
|
||||
modelNode = ln.getUrcb(mmsItemId.substring(index1 + 1, index2));
|
||||
} else if (fc == Fc.BR) {
|
||||
modelNode = ln.getBrcb(mmsItemId.substring(index1 + 1, index2));
|
||||
} else {
|
||||
modelNode = ln.getChild(mmsItemId.substring(index1 + 1, index2), fc);
|
||||
}
|
||||
|
||||
index1 = index2;
|
||||
index2 = mmsItemId.indexOf('$', index1 + 1);
|
||||
while (index2 != -1) {
|
||||
modelNode = modelNode.getChild(mmsItemId.substring(index1 + 1, index2));
|
||||
index1 = index2;
|
||||
index2 = mmsItemId.indexOf('$', index1 + 1);
|
||||
}
|
||||
|
||||
modelNode = modelNode.getChild(mmsItemId.substring(index1 + 1));
|
||||
|
||||
if (variableDef.getAlternateAccess() == null) {
|
||||
// no array is in this node path
|
||||
return (FcModelNode) modelNode;
|
||||
}
|
||||
|
||||
AlternateAccessSelection altAccIt =
|
||||
variableDef.getAlternateAccess().getCHOICE().get(0).getUnnamed();
|
||||
|
||||
if (altAccIt.getSelectAlternateAccess() != null) {
|
||||
// path to node below an array element
|
||||
modelNode =
|
||||
((Array) modelNode)
|
||||
.getChild(
|
||||
altAccIt.getSelectAlternateAccess().getAccessSelection().getIndex().intValue());
|
||||
|
||||
String mmsSubArrayItemId =
|
||||
altAccIt
|
||||
.getSelectAlternateAccess()
|
||||
.getAlternateAccess()
|
||||
.getCHOICE()
|
||||
.get(0)
|
||||
.getUnnamed()
|
||||
.getSelectAccess()
|
||||
.getComponent()
|
||||
.getBasic()
|
||||
.toString();
|
||||
|
||||
index1 = -1;
|
||||
index2 = mmsSubArrayItemId.indexOf('$');
|
||||
while (index2 != -1) {
|
||||
modelNode = modelNode.getChild(mmsSubArrayItemId.substring(index1 + 1, index2));
|
||||
index1 = index2;
|
||||
index2 = mmsItemId.indexOf('$', index1 + 1);
|
||||
}
|
||||
|
||||
return (FcModelNode) modelNode.getChild(mmsSubArrayItemId.substring(index1 + 1));
|
||||
} else {
|
||||
// path to an array element
|
||||
return (FcModelNode)
|
||||
((Array) modelNode).getChild(altAccIt.getSelectAccess().getIndex().intValue());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import com.beanit.josistack.AcseAssociation;
|
||||
import com.beanit.josistack.ServerAcseSap;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
/**
|
||||
* The <code>ServerSap</code> class represents the IEC 61850 service access point for server
|
||||
* applications. It corresponds to the AccessPoint defined in the ICD/SCL file. A server application
|
||||
* that is to listen for client connections should first get an instance of <code>ServerSap</code>
|
||||
* using the static function ServerSap.getSapsFromSclFile(). Next all the necessary configuration
|
||||
* parameters can be set. Finally the <code>startListening</code> function is called to listen for
|
||||
* client associations. Changing properties of a ServerSap after starting to listen is not
|
||||
* recommended and has unknown effects.
|
||||
*/
|
||||
public final class ServerSap {
|
||||
|
||||
static final int MINIMUM_MMS_PDU_SIZE = 64;
|
||||
private static final int MAXIMUM_MMS_PDU_SIZE = 65000;
|
||||
final ServerModel serverModel;
|
||||
final List<ServerAssociation> associations = new ArrayList<>();
|
||||
byte[] servicesSupportedCalled =
|
||||
new byte[] {(byte) 0xee, 0x1c, 0, 0, 0x04, 0x08, 0, 0, 0x79, (byte) 0xef, 0x18};
|
||||
byte[] cbbBitString = {(byte) 0xfb, 0x00};
|
||||
ServerEventListener serverEventListener;
|
||||
Timer timer;
|
||||
boolean listening = false;
|
||||
private int proposedMaxMmsPduSize = 65000;
|
||||
private int proposedMaxServOutstandingCalling = 5;
|
||||
private int proposedMaxServOutstandingCalled = 5;
|
||||
private int proposedDataStructureNestingLevel = 10;
|
||||
private int maxAssociations = 100;
|
||||
private ServerAcseSap acseSap;
|
||||
private int port = 102;
|
||||
private int backlog = 0;
|
||||
private InetAddress bindAddr = null;
|
||||
private ServerSocketFactory serverSocketFactory = null;
|
||||
|
||||
/**
|
||||
* Creates a ServerSap.
|
||||
*
|
||||
* @param port local port to listen on for new connections
|
||||
* @param backlog The maximum queue length for incoming connection indications (a request to
|
||||
* connect) is set to the backlog parameter. If a connection indication arrives when the queue
|
||||
* is full, the connection is refused. Set to 0 or less for the default value.
|
||||
* @param bindAddr local IP address to bind to, pass null to bind to all
|
||||
* @param serverModel the server model
|
||||
* @param serverSocketFactory the factory class to generate the ServerSocket. Could be used to
|
||||
* create SSLServerSockets. null = default
|
||||
*/
|
||||
public ServerSap(
|
||||
int port,
|
||||
int backlog,
|
||||
InetAddress bindAddr,
|
||||
ServerModel serverModel,
|
||||
ServerSocketFactory serverSocketFactory) {
|
||||
this.port = port;
|
||||
this.backlog = backlog;
|
||||
this.bindAddr = bindAddr;
|
||||
this.serverSocketFactory = serverSocketFactory;
|
||||
this.serverModel = serverModel;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets local port to listen on for new connections.
|
||||
*
|
||||
* @param port local port to listen on for new connections
|
||||
*/
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public int getBacklog() {
|
||||
return backlog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum queue length for incoming connection indications (a request to connect) is set
|
||||
* to the backlog parameter. If a connection indication arrives when the queue is full, the
|
||||
* connection is refused. Set to 0 or less for the default value.
|
||||
*
|
||||
* @param backlog the maximum queue length for incoming connections.
|
||||
*/
|
||||
public void setBacklog(int backlog) {
|
||||
this.backlog = backlog;
|
||||
}
|
||||
|
||||
public InetAddress getBindAddress() {
|
||||
return bindAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the local IP address to bind to, pass null to bind to all
|
||||
*
|
||||
* @param bindAddr the local IP address to bind to
|
||||
*/
|
||||
public void setBindAddress(InetAddress bindAddr) {
|
||||
this.bindAddr = bindAddr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the factory class to generate the ServerSocket. The ServerSocketFactory could be used to
|
||||
* create SSLServerSockets. Set to <code>null</code> to use <code>ServerSocketFactory.getDefault()
|
||||
* </code>.
|
||||
*
|
||||
* @param serverSocketFactory the factory class to generate the ServerSocket.
|
||||
*/
|
||||
public void setServerSocketFactory(ServerSocketFactory serverSocketFactory) {
|
||||
this.serverSocketFactory = serverSocketFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum MMS PDU size.
|
||||
*
|
||||
* @return the maximum MMS PDU size.
|
||||
*/
|
||||
public int getMaxMmsPduSize() {
|
||||
return proposedMaxMmsPduSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum MMS PDU size in bytes that the server will support. If the client requires the
|
||||
* use of a smaller maximum MMS PDU size, then the smaller size will be accepted by the server.
|
||||
* The default size is 65000.
|
||||
*
|
||||
* @param size cannot be less than 64. The upper limit is 65000 so that segmentation at the lower
|
||||
* transport layer is avoided. The Transport Layer's maximum PDU size is 65531.
|
||||
*/
|
||||
public void setMaxMmsPduSize(int size) {
|
||||
if (size >= MINIMUM_MMS_PDU_SIZE && size <= MAXIMUM_MMS_PDU_SIZE) {
|
||||
proposedMaxMmsPduSize = size;
|
||||
} else {
|
||||
throw new IllegalArgumentException("maximum size is out of bound");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of associations that are allowed in parallel by the server.
|
||||
*
|
||||
* @param maxAssociations the number of associations allowed (default is 100)
|
||||
*/
|
||||
public void setMaxAssociations(int maxAssociations) {
|
||||
this.maxAssociations = maxAssociations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the message fragment timeout. This is the timeout that the socket timeout is set to after
|
||||
* the first byte of a message has been received. If such a timeout is thrown, the
|
||||
* association/socket is closed.
|
||||
*
|
||||
* @param timeout the message fragment timeout in milliseconds. The default is 60000.
|
||||
*/
|
||||
public void setMessageFragmentTimeout(int timeout) {
|
||||
acseSap.serverTSap.setMessageFragmentTimeout(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ProposedMaxServOutstandingCalling parameter.
|
||||
*
|
||||
* @return the ProposedMaxServOutstandingCalling parameter.
|
||||
*/
|
||||
public int getProposedMaxServOutstandingCalling() {
|
||||
return proposedMaxServOutstandingCalling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ProposedMaxServOutstandingCalling parameter. The given parameter has no affect on the
|
||||
* functionality of this server.
|
||||
*
|
||||
* @param maxCalling the ProposedMaxServOutstandingCalling parameter. The default is 5.
|
||||
*/
|
||||
public void setProposedMaxServOutstandingCalling(int maxCalling) {
|
||||
proposedMaxServOutstandingCalling = maxCalling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ProposedMaxServOutstandingCalled parameter.
|
||||
*
|
||||
* @return the ProposedMaxServOutstandingCalled parameter.
|
||||
*/
|
||||
public int getProposedMaxServOutstandingCalled() {
|
||||
return proposedMaxServOutstandingCalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ProposedMaxServOutstandingCalled parameter.The given parameter has no affect on the
|
||||
* functionality of this server.
|
||||
*
|
||||
* @param maxCalled the ProposedMaxServOutstandingCalled parameter. The default is 5.
|
||||
*/
|
||||
public void setProposedMaxServOutstandingCalled(int maxCalled) {
|
||||
proposedMaxServOutstandingCalled = maxCalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ProposedDataStructureNestingLevel parameter.
|
||||
*
|
||||
* @return the ProposedDataStructureNestingLevel parameter.
|
||||
*/
|
||||
public int getProposedDataStructureNestingLevel() {
|
||||
return proposedDataStructureNestingLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the ProposedDataStructureNestingLevel parameter. The given parameter has no affect on the
|
||||
* functionality of this server.runServer
|
||||
*
|
||||
* @param nestingLevel the ProposedDataStructureNestingLevel parameter. The default is 10.
|
||||
*/
|
||||
public void setProposedDataStructureNestingLevel(int nestingLevel) {
|
||||
proposedDataStructureNestingLevel = nestingLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ServicesSupportedCalled parameter.
|
||||
*
|
||||
* @return the ServicesSupportedCalled parameter.
|
||||
*/
|
||||
public byte[] getServicesSupportedCalled() {
|
||||
return servicesSupportedCalled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SevicesSupportedCalled parameter. The given parameter has no affect on the
|
||||
* functionality of this server.
|
||||
*
|
||||
* @param services the ServicesSupportedCalled parameter
|
||||
*/
|
||||
public void setServicesSupportedCalled(byte[] services) {
|
||||
if (services.length != 11) {
|
||||
throw new IllegalArgumentException("The services parameter needs to be of lenth 11");
|
||||
}
|
||||
servicesSupportedCalled = services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a server socket waiting on the configured port for incoming association requests.
|
||||
*
|
||||
* @param serverEventListener the listener that is notified of incoming writes and when the server
|
||||
* stopped listening for new connections.
|
||||
* @throws IOException if an error occurs binding to the port.
|
||||
*/
|
||||
public void startListening(ServerEventListener serverEventListener) throws IOException {
|
||||
timer = new Timer();
|
||||
if (serverSocketFactory == null) {
|
||||
serverSocketFactory = ServerSocketFactory.getDefault();
|
||||
}
|
||||
acseSap =
|
||||
new ServerAcseSap(port, backlog, bindAddr, new AcseListener(this), serverSocketFactory);
|
||||
acseSap.serverTSap.setMaxConnections(maxAssociations);
|
||||
this.serverEventListener = serverEventListener;
|
||||
listening = true;
|
||||
acseSap.startListening();
|
||||
}
|
||||
|
||||
/** Stops listening for new connections and closes all existing connections/associations. */
|
||||
public void stop() {
|
||||
acseSap.stopListening();
|
||||
synchronized (associations) {
|
||||
listening = false;
|
||||
for (ServerAssociation association : associations) {
|
||||
association.close();
|
||||
}
|
||||
associations.clear();
|
||||
}
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
}
|
||||
|
||||
void connectionIndication(AcseAssociation acseAssociation, ByteBuffer psdu) {
|
||||
|
||||
ServerAssociation association;
|
||||
synchronized (associations) {
|
||||
if (listening) {
|
||||
association = new ServerAssociation(this);
|
||||
associations.add(association);
|
||||
} else {
|
||||
acseAssociation.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
association.handleNewAssociation(acseAssociation, psdu);
|
||||
} catch (Exception e) {
|
||||
// Association closed because of an unexpected exception.
|
||||
}
|
||||
|
||||
association.close();
|
||||
synchronized (associations) {
|
||||
associations.remove(association);
|
||||
}
|
||||
}
|
||||
|
||||
void serverStoppedListeningIndication(IOException e) {
|
||||
if (serverEventListener != null) {
|
||||
serverEventListener.serverStoppedListening(this);
|
||||
}
|
||||
}
|
||||
|
||||
public ServerModel getModelCopy() {
|
||||
return serverModel.copy();
|
||||
}
|
||||
|
||||
public void setValues(List<BasicDataAttribute> bdas) {
|
||||
synchronized (serverModel) {
|
||||
for (BasicDataAttribute bda : bdas) {
|
||||
// if (bda.getFunctionalConstraint() != FunctionalConstraint.ST) {
|
||||
// logger.debug("fc:" + bda.getFunctionalConstraint());
|
||||
// throw new IllegalArgumentException(
|
||||
// "One can only set values of BDAs with Functional Constraint ST(status)");
|
||||
// }
|
||||
|
||||
BasicDataAttribute bdaMirror = bda.mirror;
|
||||
|
||||
if (bdaMirror.dchg && bdaMirror.chgRcbs.size() != 0 && !bda.equals(bdaMirror)) {
|
||||
bdaMirror.setValueFrom(bda);
|
||||
synchronized (bdaMirror.chgRcbs) {
|
||||
for (Urcb urcb : bdaMirror.chgRcbs) {
|
||||
if (bdaMirror.dupd && urcb.getTrgOps().isDataUpdate()) {
|
||||
urcb.report(bdaMirror, true, false, true);
|
||||
} else {
|
||||
urcb.report(bdaMirror, true, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (bdaMirror.dupd && bdaMirror.dupdRcbs.size() != 0) {
|
||||
bdaMirror.setValueFrom(bda);
|
||||
synchronized (bdaMirror.dupdRcbs) {
|
||||
for (Urcb urcb : bdaMirror.dupdRcbs) {
|
||||
urcb.report(bdaMirror, false, false, true);
|
||||
}
|
||||
}
|
||||
} else if (bdaMirror.qchg && bdaMirror.chgRcbs.size() != 0 && !bda.equals(bdaMirror)) {
|
||||
bdaMirror.setValueFrom(bda);
|
||||
synchronized (bdaMirror.chgRcbs) {
|
||||
for (Urcb urcb : bdaMirror.chgRcbs) {
|
||||
urcb.report(bdaMirror, false, true, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bdaMirror.setValueFrom(bda);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class ServiceError extends Exception {
|
||||
|
||||
public static final int NO_ERROR = 0;
|
||||
public static final int INSTANCE_NOT_AVAILABLE = 1;
|
||||
public static final int INSTANCE_IN_USE = 2;
|
||||
public static final int ACCESS_VIOLATION = 3;
|
||||
public static final int ACCESS_NOT_ALLOWED_IN_CURRENT_STATE = 4;
|
||||
public static final int PARAMETER_VALUE_INAPPROPRIATE = 5;
|
||||
public static final int PARAMETER_VALUE_INCONSISTENT = 6;
|
||||
public static final int CLASS_NOT_SUPPORTED = 7;
|
||||
public static final int INSTANCE_LOCKED_BY_OTHER_CLIENT = 8;
|
||||
public static final int CONTROL_MUST_BE_SELECTED = 9;
|
||||
public static final int TYPE_CONFLICT = 10;
|
||||
public static final int FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT = 11;
|
||||
public static final int FAILED_DUE_TO_SERVER_CONSTRAINT = 12;
|
||||
public static final int APPLICATION_UNREACHABLE = 13;
|
||||
public static final int CONNECTION_LOST = 14;
|
||||
public static final int MEMORY_UNAVAILABLE = 15;
|
||||
public static final int PROCESSOR_RESOURCE_UNAVAILABLE = 16;
|
||||
public static final int FILE_NONE_EXISTENT = 17;
|
||||
public static final int FATAL = 20;
|
||||
// added to handle data access errors mentioned in iec61850-8-1
|
||||
// public static final int DATA_ACCESS_ERROR = 21;
|
||||
// added to report timeouts
|
||||
public static final int TIMEOUT = 22;
|
||||
public static final int UNKNOWN = 23;
|
||||
|
||||
private static final long serialVersionUID = 4290107163231828564L;
|
||||
private final int errorCode;
|
||||
|
||||
public ServiceError(int errorCode) {
|
||||
this(errorCode, "", null);
|
||||
}
|
||||
|
||||
public ServiceError(int errorCode, String s) {
|
||||
this(errorCode, s, null);
|
||||
}
|
||||
|
||||
public ServiceError(int errorCode, Throwable cause) {
|
||||
this(errorCode, "", cause);
|
||||
}
|
||||
|
||||
public ServiceError(int errorCode, String s, Throwable cause) {
|
||||
super(
|
||||
"Service error: "
|
||||
+ getErrorName(errorCode)
|
||||
+ "("
|
||||
+ errorCode
|
||||
+ ")"
|
||||
+ (s.isEmpty() ? "" : (" " + s)),
|
||||
cause);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
private static String getErrorName(int code) {
|
||||
switch (code) {
|
||||
case NO_ERROR:
|
||||
return "NO_ERROR";
|
||||
case INSTANCE_NOT_AVAILABLE:
|
||||
return "INSTANCE_NOT_AVAILABLE";
|
||||
case INSTANCE_IN_USE:
|
||||
return "INSTANCE_IN_USE";
|
||||
case ACCESS_VIOLATION:
|
||||
return "ACCESS_VIOLATION";
|
||||
case ACCESS_NOT_ALLOWED_IN_CURRENT_STATE:
|
||||
return "ACCESS_NOT_ALLOWED_IN_CURRENT_STATE";
|
||||
case PARAMETER_VALUE_INAPPROPRIATE:
|
||||
return "PARAMETER_VALUE_INAPPROPRIATE";
|
||||
case PARAMETER_VALUE_INCONSISTENT:
|
||||
return "PARAMETER_VALUE_INCONSISTENT";
|
||||
case CLASS_NOT_SUPPORTED:
|
||||
return "CLASS_NOT_SUPPORTED";
|
||||
case INSTANCE_LOCKED_BY_OTHER_CLIENT:
|
||||
return "INSTANCE_LOCKED_BY_OTHER_CLIENT";
|
||||
case CONTROL_MUST_BE_SELECTED:
|
||||
return "CONTROL_MUST_BE_SELECTED";
|
||||
case TYPE_CONFLICT:
|
||||
return "TYPE_CONFLICT";
|
||||
case FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT:
|
||||
return "FAILED_DUE_TO_COMMUNICATIONS_CONSTRAINT";
|
||||
case FAILED_DUE_TO_SERVER_CONSTRAINT:
|
||||
return "FAILED_DUE_TO_SERVER_CONSTRAINT";
|
||||
case APPLICATION_UNREACHABLE:
|
||||
return "APPLICATION_UNREACHABLE";
|
||||
case CONNECTION_LOST:
|
||||
return "CONNECTION_LOST";
|
||||
case MEMORY_UNAVAILABLE:
|
||||
return "MEMORY_UNAVAILABLE";
|
||||
case PROCESSOR_RESOURCE_UNAVAILABLE:
|
||||
return "PROCESSOR_RESOURCE_UNAVAILABLE";
|
||||
case FILE_NONE_EXISTENT:
|
||||
return "FILE_NONE_EXISTENT";
|
||||
case FATAL:
|
||||
return "FATAL";
|
||||
case TIMEOUT:
|
||||
return "TIMEOUT_ERROR";
|
||||
case UNKNOWN:
|
||||
return "UNKNOWN";
|
||||
default:
|
||||
return "Unknown ServiceError code";
|
||||
}
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
public final class ServiceSupport {
|
||||
|
||||
public boolean dynAssociation = false;
|
||||
public boolean getDirectory = false;
|
||||
public boolean getDataObjectDefinition = false;
|
||||
public boolean getDataSetValue = false;
|
||||
public boolean dataSetDirectory = false;
|
||||
public boolean readWrite = false;
|
||||
public boolean getCBValues = false;
|
||||
public boolean goose = false;
|
||||
public int gooseMax = 0;
|
||||
}
|
@ -0,0 +1,388 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.beanit.asn1bean.ber.types.BerBitString;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.AccessResult;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Data;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.Identifier;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.InformationReport;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.MMSpdu;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.ObjectName;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.UnconfirmedPDU;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.UnconfirmedService;
|
||||
import com.beanit.iec61850bean.internal.mms.asn1.VariableAccessSpecification;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Urcb extends Rcb {
|
||||
|
||||
final HashMap<FcModelNode, BdaReasonForInclusion> membersToBeReported = new LinkedHashMap<>();
|
||||
ServerAssociation reserved = null;
|
||||
boolean enabled = false;
|
||||
private Timer integrityTimer;
|
||||
// private ScheduledFuture<?> integrityFuture = null;
|
||||
private ScheduledFuture<?> bufTmFuture = null;
|
||||
|
||||
public Urcb(ObjectReference objectReference, List<FcModelNode> children) {
|
||||
super(objectReference, Fc.RP, children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reserve URCB - The attribute Resv (if set to TRUE) shall indicate that the URCB is currently
|
||||
* exclusively reserved for the client that has set the value to TRUE. Other clients shall not be
|
||||
* allowed to set any attribute of that URCB.
|
||||
*
|
||||
* @return the Resv child
|
||||
*/
|
||||
public BdaBoolean getResv() {
|
||||
return (BdaBoolean) children.get("Resv");
|
||||
}
|
||||
|
||||
void enable() {
|
||||
|
||||
for (FcModelNode dataSetMember : dataSet) {
|
||||
for (BasicDataAttribute bda : dataSetMember.getBasicDataAttributes()) {
|
||||
if (bda.dchg) {
|
||||
if (getTrgOps().isDataChange()) {
|
||||
synchronized (bda.chgRcbs) {
|
||||
bda.chgRcbs.add(this);
|
||||
}
|
||||
}
|
||||
} else if (bda.qchg) {
|
||||
if (getTrgOps().isQualityChange()) {
|
||||
synchronized (bda.chgRcbs) {
|
||||
bda.chgRcbs.add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bda.dupd) {
|
||||
if (getTrgOps().isDataUpdate()) {
|
||||
synchronized (bda.dupdRcbs) {
|
||||
bda.dupdRcbs.add(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getTrgOps().isIntegrity() && !(getIntgPd().getValue() < 10l)) {
|
||||
integrityTimer = new Timer();
|
||||
|
||||
integrityTimer.schedule(
|
||||
new TimerTask() {
|
||||
// integrityFuture = reserved.executor.scheduleAtFixedRate(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (Urcb.this) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
reserved.sendAnMmsPdu(getMmsReport(true, false));
|
||||
}
|
||||
}
|
||||
// }, getIntgPd().getValue(), getIntgPd().getValue(), TimeUnit.MILLISECONDS);
|
||||
},
|
||||
getIntgPd().getValue(),
|
||||
getIntgPd().getValue());
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
void disable() {
|
||||
|
||||
for (FcModelNode dataSetMember : dataSet) {
|
||||
for (BasicDataAttribute bda : dataSetMember.getBasicDataAttributes()) {
|
||||
if (bda.dchg) {
|
||||
if (getTrgOps().isDataChange()) {
|
||||
synchronized (bda.chgRcbs) {
|
||||
bda.chgRcbs.remove(this);
|
||||
}
|
||||
}
|
||||
} else if (bda.qchg) {
|
||||
if (getTrgOps().isQualityChange()) {
|
||||
synchronized (bda.chgRcbs) {
|
||||
bda.chgRcbs.remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bda.dupd) {
|
||||
if (getTrgOps().isDataUpdate()) {
|
||||
synchronized (bda.dupdRcbs) {
|
||||
bda.dupdRcbs.remove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (integrityFuture != null) {
|
||||
// integrityFuture.cancel(false);
|
||||
// }
|
||||
if (integrityTimer != null) {
|
||||
integrityTimer.cancel();
|
||||
}
|
||||
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
void generalInterrogation() {
|
||||
reserved.executor.execute(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (Urcb.this) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
reserved.sendAnMmsPdu(getMmsReport(false, true));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private MMSpdu getMmsReport(boolean integrity, boolean gi) {
|
||||
|
||||
InformationReport.ListOfAccessResult listOfAccessResult =
|
||||
new InformationReport.ListOfAccessResult();
|
||||
|
||||
List<AccessResult> accessResults = listOfAccessResult.getAccessResult();
|
||||
|
||||
AccessResult accessResult = new AccessResult();
|
||||
accessResult.setSuccess(getRptId().getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(getOptFlds().getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
|
||||
if (getOptFlds().isSequenceNumber()) {
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(getSqNum().getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
}
|
||||
getSqNum().setValue((short) (getSqNum().getValue() + 1));
|
||||
|
||||
if (getOptFlds().isReportTimestamp()) {
|
||||
BdaEntryTime entryTime = new BdaEntryTime(null, null, null, false, false);
|
||||
entryTime.setTimestamp(System.currentTimeMillis());
|
||||
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(entryTime.getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
}
|
||||
|
||||
if (getOptFlds().isDataSetName()) {
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(getDatSet().getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
}
|
||||
|
||||
if (getOptFlds().isConfigRevision()) {
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(getConfRev().getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
}
|
||||
|
||||
// segmentation not supported
|
||||
|
||||
List<FcModelNode> dataSetMembers = dataSet.getMembers();
|
||||
int dataSetSize = dataSetMembers.size();
|
||||
|
||||
// inclusion bitstring
|
||||
byte[] inclusionStringArray = new byte[(dataSetSize - 1) / 8 + 1];
|
||||
|
||||
if (integrity || gi) {
|
||||
|
||||
for (int i = 0; i < dataSetSize; i++) {
|
||||
inclusionStringArray[i / 8] = (byte) (inclusionStringArray[i / 8] | 1 << (7 - i % 8));
|
||||
}
|
||||
BerBitString inclusionString = new BerBitString(inclusionStringArray, dataSetSize);
|
||||
|
||||
Data data = new Data();
|
||||
data.setBitString(inclusionString);
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(data);
|
||||
accessResults.add(accessResult);
|
||||
|
||||
// data reference sending not supported for now
|
||||
|
||||
for (FcModelNode dataSetMember : dataSetMembers) {
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(dataSetMember.getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
}
|
||||
|
||||
BdaReasonForInclusion reasonForInclusion = new BdaReasonForInclusion(null);
|
||||
if (integrity) {
|
||||
reasonForInclusion.setIntegrity(true);
|
||||
} else {
|
||||
reasonForInclusion.setGeneralInterrogation(true);
|
||||
}
|
||||
|
||||
if (getOptFlds().isReasonForInclusion()) {
|
||||
for (int i = 0; i < dataSetMembers.size(); i++) {
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(reasonForInclusion.getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
int index = 0;
|
||||
for (FcModelNode dataSetMember : dataSet) {
|
||||
if (membersToBeReported.get(dataSetMember) != null) {
|
||||
inclusionStringArray[index / 8] =
|
||||
(byte) (inclusionStringArray[index / 8] | 1 << (7 - index % 8));
|
||||
}
|
||||
index++;
|
||||
}
|
||||
BerBitString inclusionString = new BerBitString(inclusionStringArray, dataSetSize);
|
||||
|
||||
Data data = new Data();
|
||||
data.setBitString(inclusionString);
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(data);
|
||||
accessResults.add(accessResult);
|
||||
|
||||
// data reference sending not supported for now
|
||||
|
||||
for (FcModelNode dataSetMember : dataSetMembers) {
|
||||
if (membersToBeReported.get(dataSetMember) != null) {
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(dataSetMember.getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
}
|
||||
}
|
||||
|
||||
if (getOptFlds().isReasonForInclusion()) {
|
||||
for (FcModelNode dataSetMember : dataSetMembers) {
|
||||
BdaReasonForInclusion reasonForInclusion = membersToBeReported.get(dataSetMember);
|
||||
if (reasonForInclusion != null) {
|
||||
accessResult = new AccessResult();
|
||||
accessResult.setSuccess(reasonForInclusion.getMmsDataObj());
|
||||
accessResults.add(accessResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
membersToBeReported.clear();
|
||||
bufTmFuture = null;
|
||||
}
|
||||
|
||||
ObjectName objectName = new ObjectName();
|
||||
objectName.setVmdSpecific(new Identifier("RPT".getBytes(UTF_8)));
|
||||
|
||||
VariableAccessSpecification varAccSpec = new VariableAccessSpecification();
|
||||
varAccSpec.setVariableListName(objectName);
|
||||
|
||||
InformationReport infoReport = new InformationReport();
|
||||
infoReport.setVariableAccessSpecification(varAccSpec);
|
||||
infoReport.setListOfAccessResult(listOfAccessResult);
|
||||
|
||||
UnconfirmedService unconfirmedService = new UnconfirmedService();
|
||||
unconfirmedService.setInformationReport(infoReport);
|
||||
|
||||
UnconfirmedPDU unconfirmedPDU = new UnconfirmedPDU();
|
||||
unconfirmedPDU.setService(unconfirmedService);
|
||||
|
||||
MMSpdu mmsPdu = new MMSpdu();
|
||||
mmsPdu.setUnconfirmedPDU(unconfirmedPDU);
|
||||
|
||||
return mmsPdu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FcDataObject copy() {
|
||||
List<FcModelNode> childCopies = new ArrayList<>(children.size());
|
||||
for (ModelNode childNode : children.values()) {
|
||||
childCopies.add((FcModelNode) childNode.copy());
|
||||
}
|
||||
Urcb urcb = new Urcb(objectReference, childCopies);
|
||||
urcb.dataSet = dataSet;
|
||||
return urcb;
|
||||
}
|
||||
|
||||
void report(BasicDataAttribute bda, boolean dchg, boolean qchg, boolean dupd) {
|
||||
|
||||
synchronized (this) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
FcModelNode memberFound = null;
|
||||
FcModelNode fcModelNode = bda;
|
||||
while (memberFound == null) {
|
||||
for (FcModelNode member : dataSet) {
|
||||
if (member == fcModelNode) {
|
||||
memberFound = fcModelNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (memberFound != null) {
|
||||
break;
|
||||
}
|
||||
if (!(fcModelNode.parent instanceof FcModelNode)) {
|
||||
// Unable to report Basic Data Attribute because it is not part of the referenced data set
|
||||
return;
|
||||
}
|
||||
fcModelNode = (FcModelNode) fcModelNode.parent;
|
||||
}
|
||||
|
||||
BdaReasonForInclusion reasonForInclusion = membersToBeReported.get(fcModelNode);
|
||||
if (reasonForInclusion == null) {
|
||||
reasonForInclusion = new BdaReasonForInclusion(null);
|
||||
membersToBeReported.put(fcModelNode, reasonForInclusion);
|
||||
}
|
||||
|
||||
if (dchg) {
|
||||
reasonForInclusion.setDataChange(true);
|
||||
}
|
||||
if (dupd) {
|
||||
reasonForInclusion.setDataUpdate(true);
|
||||
} else if (qchg) {
|
||||
reasonForInclusion.setQualityChange(true);
|
||||
}
|
||||
|
||||
// if bufTmFuture is not null then it is already scheduled and will send the combined report
|
||||
if (bufTmFuture == null) {
|
||||
bufTmFuture =
|
||||
reserved.executor.schedule(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (Urcb.this) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
reserved.sendAnMmsPdu(getMmsReport(false, false));
|
||||
}
|
||||
}
|
||||
},
|
||||
getBufTm().getValue(),
|
||||
TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,436 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.app;
|
||||
|
||||
import com.beanit.iec61850bean.BdaTriggerConditions;
|
||||
import com.beanit.iec61850bean.Brcb;
|
||||
import com.beanit.iec61850bean.ClientAssociation;
|
||||
import com.beanit.iec61850bean.ClientEventListener;
|
||||
import com.beanit.iec61850bean.ClientSap;
|
||||
import com.beanit.iec61850bean.DataSet;
|
||||
import com.beanit.iec61850bean.Fc;
|
||||
import com.beanit.iec61850bean.FcModelNode;
|
||||
import com.beanit.iec61850bean.ModelNode;
|
||||
import com.beanit.iec61850bean.Report;
|
||||
import com.beanit.iec61850bean.SclParseException;
|
||||
import com.beanit.iec61850bean.SclParser;
|
||||
import com.beanit.iec61850bean.ServerModel;
|
||||
import com.beanit.iec61850bean.ServiceError;
|
||||
import com.beanit.iec61850bean.Urcb;
|
||||
import com.beanit.iec61850bean.internal.cli.Action;
|
||||
import com.beanit.iec61850bean.internal.cli.ActionException;
|
||||
import com.beanit.iec61850bean.internal.cli.ActionListener;
|
||||
import com.beanit.iec61850bean.internal.cli.ActionProcessor;
|
||||
import com.beanit.iec61850bean.internal.cli.CliParameter;
|
||||
import com.beanit.iec61850bean.internal.cli.CliParameterBuilder;
|
||||
import com.beanit.iec61850bean.internal.cli.CliParseException;
|
||||
import com.beanit.iec61850bean.internal.cli.CliParser;
|
||||
import com.beanit.iec61850bean.internal.cli.IntCliParameter;
|
||||
import com.beanit.iec61850bean.internal.cli.StringCliParameter;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConsoleClient {
|
||||
|
||||
private static final String PRINT_MODEL_KEY = "m";
|
||||
private static final String PRINT_MODEL_KEY_DESCRIPTION = "print model";
|
||||
private static final String GET_DATA_VALUES_KEY = "g";
|
||||
private static final String GET_DATA_VALUES_KEY_DESCRIPTION = "send GetDataValues request";
|
||||
private static final String READ_ALL_DATA_KEY = "ga";
|
||||
private static final String READ_ALL_DATA_KEY_DESCRIPTION = "update all data in the model";
|
||||
private static final String CREATE_DATA_SET_KEY = "cds";
|
||||
private static final String CREATE_DATA_SET_KEY_DESCRIPTION = "create data set";
|
||||
private static final String DELETE_DATA_SET_KEY = "dds";
|
||||
private static final String DELETE_DATA_SET_KEY_DESCRIPTION = "delete data set";
|
||||
private static final String REPORTING_KEY = "r";
|
||||
private static final String REPORTING_KEY_DESCRIPTION = "configure reporting";
|
||||
|
||||
private static final StringCliParameter hostParam =
|
||||
new CliParameterBuilder("-h")
|
||||
.setDescription("The IP/domain address of the server you want to access.")
|
||||
.setMandatory()
|
||||
.buildStringParameter("host");
|
||||
private static final IntCliParameter portParam =
|
||||
new CliParameterBuilder("-p")
|
||||
.setDescription("The port to connect to.")
|
||||
.buildIntParameter("port", 102);
|
||||
private static final StringCliParameter modelFileParam =
|
||||
new CliParameterBuilder("-m")
|
||||
.setDescription(
|
||||
"The file name of the SCL file to read the model from. If this parameter is omitted the model will be read from the server device after connection.")
|
||||
.buildStringParameter("model-file");
|
||||
private static final ActionProcessor actionProcessor = new ActionProcessor(new ActionExecutor());
|
||||
private static volatile ClientAssociation association;
|
||||
private static ServerModel serverModel;
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
List<CliParameter> cliParameters = new ArrayList<>();
|
||||
cliParameters.add(hostParam);
|
||||
cliParameters.add(portParam);
|
||||
cliParameters.add(modelFileParam);
|
||||
|
||||
CliParser cliParser =
|
||||
new CliParser(
|
||||
"iec61850bean-console-client", "A client application to access IEC 61850 MMS servers.");
|
||||
cliParser.addParameters(cliParameters);
|
||||
|
||||
try {
|
||||
cliParser.parseArguments(args);
|
||||
} catch (CliParseException e1) {
|
||||
System.err.println("Error parsing command line parameters: " + e1.getMessage());
|
||||
System.out.println(cliParser.getUsageString());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
InetAddress address;
|
||||
try {
|
||||
address = InetAddress.getByName(hostParam.getValue());
|
||||
} catch (UnknownHostException e) {
|
||||
System.out.println("Unknown host: " + hostParam.getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
ClientSap clientSap = new ClientSap();
|
||||
|
||||
try {
|
||||
association = clientSap.associate(address, portParam.getValue(), null, new EventListener());
|
||||
} catch (IOException e) {
|
||||
System.out.println("Unable to connect to remote host.");
|
||||
return;
|
||||
}
|
||||
|
||||
Runtime.getRuntime()
|
||||
.addShutdownHook(
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
association.close();
|
||||
}
|
||||
});
|
||||
|
||||
System.out.println("successfully connected");
|
||||
|
||||
if (modelFileParam.isSelected()) {
|
||||
System.out.println("reading model from file...");
|
||||
|
||||
try {
|
||||
serverModel = SclParser.parse(modelFileParam.getValue()).get(0);
|
||||
} catch (SclParseException e1) {
|
||||
System.out.println("Error parsing SCL file: " + e1.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
association.setServerModel(serverModel);
|
||||
|
||||
System.out.println("successfully read model");
|
||||
|
||||
} else {
|
||||
System.out.println("retrieving model...");
|
||||
|
||||
try {
|
||||
serverModel = association.retrieveModel();
|
||||
} catch (ServiceError e) {
|
||||
System.out.println("Service error: " + e.getMessage());
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
System.out.println("Fatal error: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("successfully read model");
|
||||
}
|
||||
|
||||
actionProcessor.addAction(new Action(PRINT_MODEL_KEY, PRINT_MODEL_KEY_DESCRIPTION));
|
||||
actionProcessor.addAction(new Action(GET_DATA_VALUES_KEY, GET_DATA_VALUES_KEY_DESCRIPTION));
|
||||
actionProcessor.addAction(new Action(READ_ALL_DATA_KEY, READ_ALL_DATA_KEY_DESCRIPTION));
|
||||
actionProcessor.addAction(new Action(CREATE_DATA_SET_KEY, CREATE_DATA_SET_KEY_DESCRIPTION));
|
||||
actionProcessor.addAction(new Action(DELETE_DATA_SET_KEY, DELETE_DATA_SET_KEY_DESCRIPTION));
|
||||
actionProcessor.addAction(new Action(REPORTING_KEY, REPORTING_KEY_DESCRIPTION));
|
||||
|
||||
actionProcessor.start();
|
||||
}
|
||||
|
||||
private static class EventListener implements ClientEventListener {
|
||||
|
||||
@Override
|
||||
public void newReport(Report report) {
|
||||
System.out.println("\n----------------");
|
||||
System.out.println("Received report: ");
|
||||
System.err.println(report);
|
||||
System.out.println("------------------");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void associationClosed(IOException e) {
|
||||
System.out.print("Received connection closed signal. Reason: ");
|
||||
if (!e.getMessage().isEmpty()) {
|
||||
System.out.println(e.getMessage());
|
||||
} else {
|
||||
System.out.println("unknown");
|
||||
}
|
||||
actionProcessor.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static class ActionExecutor implements ActionListener {
|
||||
|
||||
@Override
|
||||
public void actionCalled(String actionKey) throws ActionException {
|
||||
try {
|
||||
switch (actionKey) {
|
||||
case PRINT_MODEL_KEY:
|
||||
System.out.println(serverModel);
|
||||
break;
|
||||
case READ_ALL_DATA_KEY:
|
||||
System.out.print("Reading all data...");
|
||||
try {
|
||||
association.getAllDataValues();
|
||||
} catch (ServiceError e) {
|
||||
System.err.println("Service error: " + e.getMessage());
|
||||
}
|
||||
System.out.println("done");
|
||||
break;
|
||||
case GET_DATA_VALUES_KEY:
|
||||
{
|
||||
if (serverModel == null) {
|
||||
System.out.println("You have to retrieve the model before reading data.");
|
||||
return;
|
||||
}
|
||||
|
||||
FcModelNode fcModelNode = askForFcModelNode();
|
||||
|
||||
System.out.println("Sending GetDataValues request...");
|
||||
|
||||
try {
|
||||
association.getDataValues(fcModelNode);
|
||||
} catch (ServiceError e) {
|
||||
System.out.println("Service error: " + e.getMessage());
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
System.out.println("Fatal error: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Successfully read data.");
|
||||
System.out.println(fcModelNode);
|
||||
|
||||
break;
|
||||
}
|
||||
case CREATE_DATA_SET_KEY:
|
||||
{
|
||||
System.out.println(
|
||||
"Enter the reference of the data set to create (e.g. myld/MYLN0.dataset1): ");
|
||||
String reference = actionProcessor.getReader().readLine();
|
||||
|
||||
System.out.println("How many entries shall the data set have: ");
|
||||
String numberOfEntriesString = actionProcessor.getReader().readLine();
|
||||
int numDataSetEntries = Integer.parseInt(numberOfEntriesString);
|
||||
|
||||
List<FcModelNode> dataSetMembers = new ArrayList<>();
|
||||
for (int i = 0; i < numDataSetEntries; i++) {
|
||||
dataSetMembers.add(askForFcModelNode());
|
||||
}
|
||||
|
||||
DataSet dataSet = new DataSet(reference, dataSetMembers);
|
||||
System.out.print("Creating data set..");
|
||||
association.createDataSet(dataSet);
|
||||
System.out.println("done");
|
||||
|
||||
break;
|
||||
}
|
||||
case DELETE_DATA_SET_KEY:
|
||||
{
|
||||
System.out.println(
|
||||
"Enter the reference of the data set to delete (e.g. myld/MYLN0.dataset1): ");
|
||||
String reference = actionProcessor.getReader().readLine();
|
||||
|
||||
DataSet dataSet = serverModel.getDataSet(reference);
|
||||
if (dataSet == null) {
|
||||
throw new ActionException("Unable to find data set with the given reference.");
|
||||
}
|
||||
System.out.print("Deleting data set..");
|
||||
association.deleteDataSet(dataSet);
|
||||
System.out.println("done");
|
||||
|
||||
break;
|
||||
}
|
||||
case REPORTING_KEY:
|
||||
{
|
||||
System.out.println("Enter the URCB reference: ");
|
||||
String reference = actionProcessor.getReader().readLine();
|
||||
Urcb urcb = serverModel.getUrcb(reference);
|
||||
if (urcb == null) {
|
||||
Brcb brcb = serverModel.getBrcb(reference);
|
||||
if (brcb != null) {
|
||||
throw new ActionException(
|
||||
"Though buffered reporting is supported by the library it is not yet supported by the console application.");
|
||||
}
|
||||
throw new ActionException("Unable to find RCB with the given reference.");
|
||||
}
|
||||
|
||||
while (true) {
|
||||
association.getRcbValues(urcb);
|
||||
System.out.println();
|
||||
System.out.println(urcb);
|
||||
System.out.println();
|
||||
System.out.println("What do you want to configure?");
|
||||
System.out.println("1 - reserve");
|
||||
System.out.println("2 - cancel reservation");
|
||||
System.out.println("3 - enable");
|
||||
System.out.println("4 - disable");
|
||||
System.out.println("5 - set data set");
|
||||
System.out.println("6 - set trigger options");
|
||||
System.out.println("7 - set integrity period");
|
||||
System.out.println("8 - send general interrogation");
|
||||
System.out.println("0 - quit");
|
||||
try {
|
||||
int rcbAction = Integer.parseInt(actionProcessor.getReader().readLine());
|
||||
switch (rcbAction) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
System.out.print("Reserving RCB..");
|
||||
association.reserveUrcb(urcb);
|
||||
System.out.println("done");
|
||||
break;
|
||||
case 2:
|
||||
System.out.print("Canceling RCB reservation..");
|
||||
association.cancelUrcbReservation(urcb);
|
||||
System.out.println("done");
|
||||
break;
|
||||
case 3:
|
||||
System.out.print("Enabling reporting..");
|
||||
association.enableReporting(urcb);
|
||||
System.out.println("done");
|
||||
break;
|
||||
case 4:
|
||||
System.out.print("Disabling reporting..");
|
||||
association.disableReporting(urcb);
|
||||
System.out.println("done");
|
||||
break;
|
||||
case 5:
|
||||
{
|
||||
System.out.print("Set data set reference:");
|
||||
String dataSetReference = actionProcessor.getReader().readLine();
|
||||
urcb.getDatSet().setValue(dataSetReference);
|
||||
List<ServiceError> serviceErrors =
|
||||
association.setRcbValues(
|
||||
urcb, false, true, false, false, false, false, false, false);
|
||||
if (serviceErrors.get(0) != null) {
|
||||
throw serviceErrors.get(0);
|
||||
}
|
||||
System.out.println("done");
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
System.out.print(
|
||||
"Set the trigger options (data change, data update, quality change, interity, GI):");
|
||||
String triggerOptionsString = actionProcessor.getReader().readLine();
|
||||
String[] triggerOptionsStrings = triggerOptionsString.split(",", -1);
|
||||
BdaTriggerConditions triggerOptions = urcb.getTrgOps();
|
||||
triggerOptions.setDataChange(
|
||||
Boolean.parseBoolean(triggerOptionsStrings[0]));
|
||||
triggerOptions.setDataUpdate(
|
||||
Boolean.parseBoolean(triggerOptionsStrings[1]));
|
||||
triggerOptions.setQualityChange(
|
||||
Boolean.parseBoolean(triggerOptionsStrings[2]));
|
||||
triggerOptions.setIntegrity(Boolean.parseBoolean(triggerOptionsStrings[3]));
|
||||
triggerOptions.setGeneralInterrogation(
|
||||
Boolean.parseBoolean(triggerOptionsStrings[4]));
|
||||
List<ServiceError> serviceErrors =
|
||||
association.setRcbValues(
|
||||
urcb, false, false, false, false, true, false, false, false);
|
||||
if (serviceErrors.get(0) != null) {
|
||||
throw serviceErrors.get(0);
|
||||
}
|
||||
System.out.println("done");
|
||||
break;
|
||||
}
|
||||
case 7:
|
||||
{
|
||||
System.out.print("Specify integrity period in ms:");
|
||||
String integrityPeriodString = actionProcessor.getReader().readLine();
|
||||
urcb.getIntgPd().setValue(Long.parseLong(integrityPeriodString));
|
||||
List<ServiceError> serviceErrors =
|
||||
association.setRcbValues(
|
||||
urcb, false, false, false, false, false, true, false, false);
|
||||
if (serviceErrors.get(0) != null) {
|
||||
throw serviceErrors.get(0);
|
||||
}
|
||||
System.out.println("done");
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
System.out.print("Sending GI..");
|
||||
association.startGi(urcb);
|
||||
System.out.println("done");
|
||||
break;
|
||||
default:
|
||||
System.err.println("Unknown option.");
|
||||
break;
|
||||
}
|
||||
} catch (ServiceError e) {
|
||||
System.err.println("Service error: " + e.getMessage());
|
||||
} catch (NumberFormatException e) {
|
||||
System.err.println("Cannot parse number: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ActionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private FcModelNode askForFcModelNode() throws IOException, ActionException {
|
||||
System.out.println("Enter reference (e.g. myld/MYLN0.do.da.bda): ");
|
||||
String reference = actionProcessor.getReader().readLine();
|
||||
System.out.println("Enter functional constraint of referenced node: ");
|
||||
String fcString = actionProcessor.getReader().readLine();
|
||||
|
||||
Fc fc = Fc.fromString(fcString);
|
||||
if (fc == null) {
|
||||
throw new ActionException("Unknown functional constraint.");
|
||||
}
|
||||
|
||||
ModelNode modelNode = serverModel.findModelNode(reference, Fc.fromString(fcString));
|
||||
if (modelNode == null) {
|
||||
throw new ActionException(
|
||||
"A model node with the given reference and functional constraint could not be found.");
|
||||
}
|
||||
|
||||
if (!(modelNode instanceof FcModelNode)) {
|
||||
throw new ActionException(
|
||||
"The given model node is not a functionally constraint model node.");
|
||||
}
|
||||
|
||||
FcModelNode fcModelNode = (FcModelNode) modelNode;
|
||||
return fcModelNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void quit() {
|
||||
System.out.println("** Closing connection.");
|
||||
association.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.app;
|
||||
|
||||
import com.beanit.iec61850bean.BasicDataAttribute;
|
||||
import com.beanit.iec61850bean.BdaBoolean;
|
||||
import com.beanit.iec61850bean.BdaFloat32;
|
||||
import com.beanit.iec61850bean.BdaFloat64;
|
||||
import com.beanit.iec61850bean.BdaInt16;
|
||||
import com.beanit.iec61850bean.BdaInt16U;
|
||||
import com.beanit.iec61850bean.BdaInt32;
|
||||
import com.beanit.iec61850bean.BdaInt32U;
|
||||
import com.beanit.iec61850bean.BdaInt64;
|
||||
import com.beanit.iec61850bean.BdaInt8;
|
||||
import com.beanit.iec61850bean.BdaInt8U;
|
||||
import com.beanit.iec61850bean.Fc;
|
||||
import com.beanit.iec61850bean.ModelNode;
|
||||
import com.beanit.iec61850bean.SclParseException;
|
||||
import com.beanit.iec61850bean.SclParser;
|
||||
import com.beanit.iec61850bean.ServerEventListener;
|
||||
import com.beanit.iec61850bean.ServerModel;
|
||||
import com.beanit.iec61850bean.ServerSap;
|
||||
import com.beanit.iec61850bean.ServiceError;
|
||||
import com.beanit.iec61850bean.internal.cli.Action;
|
||||
import com.beanit.iec61850bean.internal.cli.ActionException;
|
||||
import com.beanit.iec61850bean.internal.cli.ActionListener;
|
||||
import com.beanit.iec61850bean.internal.cli.ActionProcessor;
|
||||
import com.beanit.iec61850bean.internal.cli.CliParameter;
|
||||
import com.beanit.iec61850bean.internal.cli.CliParameterBuilder;
|
||||
import com.beanit.iec61850bean.internal.cli.CliParseException;
|
||||
import com.beanit.iec61850bean.internal.cli.CliParser;
|
||||
import com.beanit.iec61850bean.internal.cli.IntCliParameter;
|
||||
import com.beanit.iec61850bean.internal.cli.StringCliParameter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConsoleServer {
|
||||
|
||||
private static final String WRITE_VALUE_KEY = "w";
|
||||
private static final String WRITE_VALUE_KEY_DESCRIPTION = "write value to model node";
|
||||
|
||||
private static final String PRINT_SERVER_MODEL_KEY = "p";
|
||||
private static final String PRINT_SERVER_MODEL_KEY_DESCRIPTION = "print server's model";
|
||||
|
||||
private static final IntCliParameter portParam =
|
||||
new CliParameterBuilder("-p")
|
||||
.setDescription(
|
||||
"The port to listen on. On unix based systems you need root privilages for ports < 1000.")
|
||||
.buildIntParameter("port", 102);
|
||||
|
||||
private static final StringCliParameter modelFileParam =
|
||||
new CliParameterBuilder("-m")
|
||||
.setDescription("The SCL file that contains the server's information model.")
|
||||
.setMandatory()
|
||||
.buildStringParameter("model-file");
|
||||
private static final ActionProcessor actionProcessor = new ActionProcessor(new ActionExecutor());
|
||||
private static ServerModel serverModel;
|
||||
private static ServerSap serverSap = null;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
List<CliParameter> cliParameters = new ArrayList<>();
|
||||
cliParameters.add(modelFileParam);
|
||||
cliParameters.add(portParam);
|
||||
|
||||
CliParser cliParser =
|
||||
new CliParser("iec61850bean-console-server", "An IEC 61850 MMS console server.");
|
||||
cliParser.addParameters(cliParameters);
|
||||
|
||||
try {
|
||||
cliParser.parseArguments(args);
|
||||
} catch (CliParseException e1) {
|
||||
System.err.println("Error parsing command line parameters: " + e1.getMessage());
|
||||
System.out.println(cliParser.getUsageString());
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
List<ServerModel> serverModels = null;
|
||||
try {
|
||||
serverModels = SclParser.parse(modelFileParam.getValue());
|
||||
} catch (SclParseException e) {
|
||||
System.out.println("Error parsing SCL/ICD file: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
serverSap = new ServerSap(102, 0, null, serverModels.get(0), null);
|
||||
serverSap.setPort(portParam.getValue());
|
||||
|
||||
Runtime.getRuntime()
|
||||
.addShutdownHook(
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (serverSap != null) {
|
||||
serverSap.stop();
|
||||
}
|
||||
System.out.println("Server was stopped.");
|
||||
}
|
||||
});
|
||||
|
||||
serverModel = serverSap.getModelCopy();
|
||||
|
||||
serverSap.startListening(new EventListener());
|
||||
|
||||
actionProcessor.addAction(
|
||||
new Action(PRINT_SERVER_MODEL_KEY, PRINT_SERVER_MODEL_KEY_DESCRIPTION));
|
||||
actionProcessor.addAction(new Action(WRITE_VALUE_KEY, WRITE_VALUE_KEY_DESCRIPTION));
|
||||
|
||||
actionProcessor.start();
|
||||
}
|
||||
|
||||
private static class EventListener implements ServerEventListener {
|
||||
|
||||
@Override
|
||||
public void serverStoppedListening(ServerSap serverSap) {
|
||||
System.out.println("The SAP stopped listening");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceError> write(List<BasicDataAttribute> bdas) {
|
||||
for (BasicDataAttribute bda : bdas) {
|
||||
System.out.println("got a write request: " + bda);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ActionExecutor implements ActionListener {
|
||||
|
||||
@Override
|
||||
public void actionCalled(String actionKey) throws ActionException {
|
||||
try {
|
||||
switch (actionKey) {
|
||||
case PRINT_SERVER_MODEL_KEY:
|
||||
System.out.println("** Printing model.");
|
||||
|
||||
System.out.println(serverModel);
|
||||
|
||||
break;
|
||||
case WRITE_VALUE_KEY:
|
||||
System.out.println("Enter reference to write (e.g. myld/MYLN0.do.da.bda): ");
|
||||
String reference = actionProcessor.getReader().readLine();
|
||||
System.out.println("Enter functional constraint of referenced node: ");
|
||||
String fcString = actionProcessor.getReader().readLine();
|
||||
|
||||
Fc fc = Fc.fromString(fcString);
|
||||
if (fc == null) {
|
||||
System.out.println("Unknown functional constraint.");
|
||||
return;
|
||||
}
|
||||
|
||||
ModelNode modelNode = serverModel.findModelNode(reference, Fc.fromString(fcString));
|
||||
if (modelNode == null) {
|
||||
System.out.println(
|
||||
"A model node with the given reference and functional constraint could not be found.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(modelNode instanceof BasicDataAttribute)) {
|
||||
System.out.println("The given model node is not a basic data attribute.");
|
||||
return;
|
||||
}
|
||||
|
||||
BasicDataAttribute bda =
|
||||
(BasicDataAttribute) serverModel.findModelNode(reference, Fc.fromString(fcString));
|
||||
|
||||
System.out.println("Enter value to write: ");
|
||||
String valueString = actionProcessor.getReader().readLine();
|
||||
|
||||
try {
|
||||
setBdaValue(bda, valueString);
|
||||
} catch (Exception e) {
|
||||
System.out.println(
|
||||
"The console server does not support writing this type of basic data attribute.");
|
||||
return;
|
||||
}
|
||||
|
||||
List<BasicDataAttribute> bdas = new ArrayList<>();
|
||||
bdas.add(bda);
|
||||
serverSap.setValues(bdas);
|
||||
|
||||
System.out.println("Successfully wrote data.");
|
||||
System.out.println(bda);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ActionException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setBdaValue(BasicDataAttribute bda, String valueString) {
|
||||
if (bda instanceof BdaFloat32) {
|
||||
float value = Float.parseFloat(valueString);
|
||||
((BdaFloat32) bda).setFloat(value);
|
||||
} else if (bda instanceof BdaFloat64) {
|
||||
double value = Float.parseFloat(valueString);
|
||||
((BdaFloat64) bda).setDouble(value);
|
||||
} else if (bda instanceof BdaInt8) {
|
||||
byte value = Byte.parseByte(valueString);
|
||||
((BdaInt8) bda).setValue(value);
|
||||
} else if (bda instanceof BdaInt8U) {
|
||||
short value = Short.parseShort(valueString);
|
||||
((BdaInt8U) bda).setValue(value);
|
||||
} else if (bda instanceof BdaInt16) {
|
||||
short value = Short.parseShort(valueString);
|
||||
((BdaInt16) bda).setValue(value);
|
||||
} else if (bda instanceof BdaInt16U) {
|
||||
int value = Integer.parseInt(valueString);
|
||||
((BdaInt16U) bda).setValue(value);
|
||||
} else if (bda instanceof BdaInt32) {
|
||||
int value = Integer.parseInt(valueString);
|
||||
((BdaInt32) bda).setValue(value);
|
||||
} else if (bda instanceof BdaInt32U) {
|
||||
long value = Long.parseLong(valueString);
|
||||
((BdaInt32U) bda).setValue(value);
|
||||
} else if (bda instanceof BdaInt64) {
|
||||
long value = Long.parseLong(valueString);
|
||||
((BdaInt64) bda).setValue(value);
|
||||
} else if (bda instanceof BdaBoolean) {
|
||||
boolean value = Boolean.parseBoolean(valueString);
|
||||
((BdaBoolean) bda).setValue(value);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void quit() {
|
||||
System.out.println("** Stopping server.");
|
||||
serverSap.stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui;
|
||||
|
||||
import com.beanit.iec61850bean.BasicDataAttribute;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
public abstract class BasicDataBind<E extends BasicDataAttribute> {
|
||||
protected final E data;
|
||||
|
||||
private JComponent valueField;
|
||||
|
||||
protected BasicDataBind(E data, BdaType type) {
|
||||
if (data.getBasicType() != type) {
|
||||
throw new IllegalArgumentException(data.getName() + " is no " + type);
|
||||
}
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public JLabel getNameLabel() {
|
||||
return new JLabel(data.getName());
|
||||
}
|
||||
|
||||
public JComponent getValueField() {
|
||||
if (valueField == null) {
|
||||
valueField = init();
|
||||
}
|
||||
|
||||
return valueField;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
if (valueField == null) {
|
||||
valueField = init();
|
||||
}
|
||||
|
||||
resetImpl();
|
||||
}
|
||||
|
||||
public void write() {
|
||||
if (valueField == null) {
|
||||
valueField = init();
|
||||
}
|
||||
|
||||
writeImpl();
|
||||
}
|
||||
|
||||
protected abstract JComponent init();
|
||||
|
||||
protected abstract void resetImpl();
|
||||
|
||||
protected abstract void writeImpl();
|
||||
}
|
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui;
|
||||
|
||||
import com.beanit.iec61850bean.ClientAssociation;
|
||||
import com.beanit.iec61850bean.ClientSap;
|
||||
import com.beanit.iec61850bean.ServerModel;
|
||||
import com.beanit.iec61850bean.ServiceError;
|
||||
import com.beanit.iec61850bean.clientgui.util.Counter;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Properties;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.ToolTipManager;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.UnsupportedLookAndFeelException;
|
||||
import javax.swing.event.TreeSelectionEvent;
|
||||
import javax.swing.event.TreeSelectionListener;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
|
||||
public class ClientGui extends JFrame implements ActionListener, TreeSelectionListener {
|
||||
|
||||
private static final String ADDRESS_KEY = "serverAddress";
|
||||
private static final String PORT_KEY = "serverPort";
|
||||
private static final String TSEL_LOCAL_KEY = "tselLocal";
|
||||
private static final String TSEL_REMOTE_KEY = "tselRemote";
|
||||
private static final String LASTCONNECTION_FILE = "lastconnection.properties";
|
||||
|
||||
private static final long serialVersionUID = -1938913902977758367L;
|
||||
|
||||
private final JTextField ipTextField = new JTextField("127.0.0.1");
|
||||
private final JTextField portTextField = new JTextField("10002");
|
||||
private final JTree tree = new JTree(new DefaultMutableTreeNode("No server connected"));
|
||||
private final JPanel detailsPanel = new JPanel();
|
||||
private final GridBagLayout detailsLayout = new GridBagLayout();
|
||||
|
||||
private final SettingsFrame settingsFrame = new SettingsFrame();
|
||||
|
||||
private ClientAssociation association;
|
||||
|
||||
private DataTreeNode selectedNode;
|
||||
|
||||
public ClientGui() {
|
||||
super("IEC61850bean Client GUI");
|
||||
|
||||
Properties lastConnection = new Properties();
|
||||
|
||||
InputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(LASTCONNECTION_FILE);
|
||||
lastConnection.load(in);
|
||||
|
||||
ipTextField.setText(lastConnection.getProperty(ADDRESS_KEY));
|
||||
portTextField.setText(lastConnection.getProperty(PORT_KEY));
|
||||
|
||||
String[] tselString = lastConnection.getProperty(TSEL_LOCAL_KEY).split(",");
|
||||
byte[] tsel =
|
||||
new byte[] {
|
||||
(byte) Integer.parseInt(tselString[0]), (byte) Integer.parseInt(tselString[1])
|
||||
};
|
||||
settingsFrame.setTselLocal(tsel);
|
||||
|
||||
tselString = lastConnection.getProperty(TSEL_REMOTE_KEY).split(",");
|
||||
tsel =
|
||||
new byte[] {
|
||||
(byte) Integer.parseInt(tselString[0]), (byte) Integer.parseInt(tselString[1])
|
||||
};
|
||||
settingsFrame.setTselRemote(tsel);
|
||||
} catch (Exception ex) {
|
||||
// no lastconnection.properties file found, use default.
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
// there is nothing that can be done if closing fails
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.out.println("Class not found: " + e.getMessage());
|
||||
} catch (InstantiationException e) {
|
||||
System.out.println("Object not instantiated: " + e.getMessage());
|
||||
} catch (IllegalAccessException e) {
|
||||
System.out.println("Illegal acces: " + e.getMessage());
|
||||
} catch (UnsupportedLookAndFeelException e) {
|
||||
System.out.println("Unsupported LookAndFeel: " + e.getMessage());
|
||||
}
|
||||
|
||||
GridBagLayout gbl = new GridBagLayout();
|
||||
setLayout(gbl);
|
||||
|
||||
JPanel topPanel = new JPanel();
|
||||
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.X_AXIS));
|
||||
|
||||
GridBagConstraints topPanelConstraint = new GridBagConstraints();
|
||||
topPanelConstraint.fill = GridBagConstraints.HORIZONTAL;
|
||||
topPanelConstraint.gridwidth = GridBagConstraints.REMAINDER;
|
||||
topPanelConstraint.gridx = 0;
|
||||
topPanelConstraint.gridy = 0;
|
||||
topPanelConstraint.insets = new Insets(5, 5, 5, 5);
|
||||
topPanelConstraint.anchor = GridBagConstraints.NORTH;
|
||||
gbl.setConstraints(topPanel, topPanelConstraint);
|
||||
add(topPanel);
|
||||
|
||||
JLabel label = new JLabel("IP: ");
|
||||
topPanel.add(label);
|
||||
topPanel.add(ipTextField);
|
||||
topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
|
||||
|
||||
label = new JLabel("Port: ");
|
||||
topPanel.add(label);
|
||||
topPanel.add(portTextField);
|
||||
topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
|
||||
|
||||
JButton newServerButton = new JButton("Connect to Server");
|
||||
newServerButton.addActionListener(this);
|
||||
newServerButton.setActionCommand("Connect");
|
||||
topPanel.add(newServerButton);
|
||||
topPanel.add(Box.createRigidArea(new Dimension(5, 0)));
|
||||
|
||||
JButton settingsButton = new JButton("Settings");
|
||||
settingsButton.addActionListener(this);
|
||||
settingsButton.setActionCommand("Settings");
|
||||
topPanel.add(settingsButton);
|
||||
|
||||
ToolTipManager.sharedInstance().registerComponent(tree);
|
||||
|
||||
tree.setCellRenderer(new DataObjectTreeCellRenderer());
|
||||
tree.setMinimumSize(new Dimension(100, 0));
|
||||
tree.addTreeSelectionListener(this);
|
||||
JScrollPane treeScrollPane = new JScrollPane(tree);
|
||||
treeScrollPane.setMinimumSize(new Dimension(100, 0));
|
||||
treeScrollPane.setVisible(true);
|
||||
|
||||
GridBagConstraints treeScrollPaneConstraint = new GridBagConstraints();
|
||||
treeScrollPaneConstraint.fill = GridBagConstraints.BOTH;
|
||||
treeScrollPaneConstraint.gridx = 0;
|
||||
treeScrollPaneConstraint.gridy = 1;
|
||||
treeScrollPaneConstraint.weightx = 0.2;
|
||||
treeScrollPaneConstraint.weighty = 1;
|
||||
treeScrollPaneConstraint.insets = new Insets(5, 5, 5, 5);
|
||||
gbl.setConstraints(treeScrollPane, treeScrollPaneConstraint);
|
||||
add(treeScrollPane);
|
||||
|
||||
detailsPanel.setLayout(detailsLayout);
|
||||
detailsPanel.setAlignmentY(TOP_ALIGNMENT);
|
||||
JScrollPane detailsScrollPane = new JScrollPane(detailsPanel);
|
||||
detailsPanel.setMaximumSize(detailsScrollPane.getSize());
|
||||
detailsScrollPane.setMinimumSize(new Dimension(0, 0));
|
||||
detailsScrollPane.setPreferredSize(new Dimension(200, 0));
|
||||
detailsScrollPane.setVisible(true);
|
||||
GridBagConstraints detailsScrollPaneConstraint = new GridBagConstraints();
|
||||
detailsScrollPaneConstraint.fill = GridBagConstraints.BOTH;
|
||||
detailsScrollPaneConstraint.gridx = 1;
|
||||
detailsScrollPaneConstraint.gridy = 1;
|
||||
detailsScrollPaneConstraint.weightx = 0.8;
|
||||
detailsScrollPaneConstraint.weighty = 1;
|
||||
detailsScrollPaneConstraint.insets = new Insets(5, 5, 5, 5);
|
||||
gbl.setConstraints(detailsScrollPane, detailsScrollPaneConstraint);
|
||||
add(detailsScrollPane);
|
||||
|
||||
// Display the window.
|
||||
setSize(700, 500);
|
||||
setMinimumSize(new Dimension(420, 0));
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
ClientGui clientGui = new ClientGui();
|
||||
clientGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
clientGui.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
if ("connect".equalsIgnoreCase(arg0.getActionCommand())) {
|
||||
connect();
|
||||
} else if ("reload".equalsIgnoreCase(arg0.getActionCommand())) {
|
||||
reload();
|
||||
} else if ("write".equalsIgnoreCase(arg0.getActionCommand())) {
|
||||
write();
|
||||
} else if ("settings".equalsIgnoreCase(arg0.getActionCommand())) {
|
||||
settingsFrame.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
detailsPanel.removeAll();
|
||||
detailsPanel.repaint();
|
||||
if (e.getNewLeadSelectionPath() != null) {
|
||||
selectedNode = (DataTreeNode) e.getNewLeadSelectionPath().getLastPathComponent();
|
||||
if (selectedNode.readable()) {
|
||||
showDataDetails(selectedNode, new Counter());
|
||||
|
||||
JPanel filler = new JPanel();
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.fill = GridBagConstraints.BOTH;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = GridBagConstraints.RELATIVE;
|
||||
gbc.gridwidth = 3;
|
||||
gbc.gridheight = 1;
|
||||
gbc.weightx = 0;
|
||||
gbc.weighty = 1;
|
||||
detailsLayout.setConstraints(filler, gbc);
|
||||
detailsPanel.add(filler);
|
||||
|
||||
JButton button = new JButton("Reload values");
|
||||
button.addActionListener(this);
|
||||
button.setActionCommand("reload");
|
||||
gbc = new GridBagConstraints();
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.gridx = 0;
|
||||
gbc.gridy = GridBagConstraints.RELATIVE;
|
||||
gbc.gridwidth = 2;
|
||||
gbc.gridheight = 1;
|
||||
gbc.weightx = 0;
|
||||
gbc.weighty = 0;
|
||||
gbc.anchor = GridBagConstraints.SOUTHWEST;
|
||||
gbc.insets = new Insets(0, 5, 5, 0);
|
||||
detailsLayout.setConstraints(button, gbc);
|
||||
detailsPanel.add(button);
|
||||
|
||||
if (selectedNode.writable()) {
|
||||
button = new JButton("Write values");
|
||||
button.addActionListener(this);
|
||||
button.setActionCommand("write");
|
||||
gbc = new GridBagConstraints();
|
||||
gbc.fill = GridBagConstraints.NONE;
|
||||
gbc.gridx = 2;
|
||||
gbc.gridy = GridBagConstraints.RELATIVE;
|
||||
gbc.gridwidth = 1;
|
||||
gbc.gridheight = 1;
|
||||
gbc.weightx = 0;
|
||||
gbc.weighty = 0;
|
||||
gbc.anchor = GridBagConstraints.SOUTHEAST;
|
||||
gbc.insets = new Insets(0, 0, 5, 5);
|
||||
detailsLayout.setConstraints(button, gbc);
|
||||
detailsPanel.add(button);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
selectedNode = null;
|
||||
}
|
||||
|
||||
validate();
|
||||
}
|
||||
|
||||
private void connect() {
|
||||
ClientSap clientSap = new ClientSap();
|
||||
|
||||
InetAddress address = null;
|
||||
try {
|
||||
address = InetAddress.getByName(ipTextField.getText());
|
||||
} catch (UnknownHostException e1) {
|
||||
e1.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
int remotePort = 10002;
|
||||
try {
|
||||
remotePort = Integer.parseInt(portTextField.getText());
|
||||
if (remotePort < 1 || remotePort > 0xFFFF) {
|
||||
throw new NumberFormatException("port must be in range [1, 65535]");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
clientSap.setTSelLocal(settingsFrame.getTselLocal());
|
||||
clientSap.setTSelRemote(settingsFrame.getTselRemote());
|
||||
|
||||
try {
|
||||
association = clientSap.associate(address, remotePort, null, null);
|
||||
} catch (IOException e) {
|
||||
System.out.println("Error connecting to server: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
ServerModel serverModel;
|
||||
try {
|
||||
serverModel = association.retrieveModel();
|
||||
association.getAllDataValues();
|
||||
} catch (ServiceError e) {
|
||||
System.out.println("Service Error requesting model." + e.getMessage());
|
||||
association.close();
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
System.out.println("Fatal IOException requesting model." + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
ServerModelParser parser = new ServerModelParser(serverModel);
|
||||
tree.setModel(new DefaultTreeModel(parser.getModelTree()));
|
||||
|
||||
Properties lastConnectSettings = new Properties();
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
lastConnectSettings.setProperty(ADDRESS_KEY, ipTextField.getText());
|
||||
lastConnectSettings.setProperty(PORT_KEY, portTextField.getText());
|
||||
byte[] tsel = settingsFrame.getTselLocal();
|
||||
lastConnectSettings.setProperty(TSEL_LOCAL_KEY, tsel[0] + "," + tsel[1]);
|
||||
tsel = settingsFrame.getTselRemote();
|
||||
lastConnectSettings.setProperty(TSEL_REMOTE_KEY, tsel[0] + "," + tsel[1]);
|
||||
|
||||
out = new FileOutputStream(LASTCONNECTION_FILE);
|
||||
lastConnectSettings.store(out, null);
|
||||
} catch (IOException ex) {
|
||||
System.out.println("Writing properties file failed. Reason: " + ex.getMessage());
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// nothing meaningful can be done if closing fails
|
||||
}
|
||||
}
|
||||
|
||||
validate();
|
||||
}
|
||||
|
||||
private void reload() {
|
||||
if (selectedNode.readable()) {
|
||||
try {
|
||||
selectedNode.reset(association);
|
||||
} catch (ServiceError e) {
|
||||
System.out.println("ServiceError on reading" + e.getMessage());
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
System.out.println("IOException on reading" + e.getMessage());
|
||||
return;
|
||||
}
|
||||
validate();
|
||||
}
|
||||
}
|
||||
|
||||
private void write() {
|
||||
if (selectedNode.writable()) {
|
||||
try {
|
||||
selectedNode.writeValues(association);
|
||||
} catch (ServiceError e) {
|
||||
System.out.println("ServiceError on writing" + e.getMessage());
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
System.out.println("IOException on writing" + e.getMessage());
|
||||
return;
|
||||
}
|
||||
validate();
|
||||
}
|
||||
}
|
||||
|
||||
private void showDataDetails(DataTreeNode node, Counter y) {
|
||||
if (node.getData() != null) {
|
||||
BasicDataBind<?> data = node.getData();
|
||||
JLabel nameLabel = data.getNameLabel();
|
||||
nameLabel.setText(nameLabel.getText() + ": ");
|
||||
addDetailsComponent(nameLabel, 0, y.getValue(), 1, 1, 0, 0);
|
||||
addDetailsComponent(data.getValueField(), 1, y.getValue(), 2, 1, 1, 0);
|
||||
y.increment();
|
||||
} else {
|
||||
for (int i = 0; i < node.getChildCount(); i++) {
|
||||
y.increment();
|
||||
DataObjectTreeNode childNode = (DataObjectTreeNode) node.getChildAt(i);
|
||||
showDataDetails(childNode, childNode.toString(), y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showDataDetails(DataTreeNode node, String pre, Counter y) {
|
||||
if (node.getData() != null) {
|
||||
BasicDataBind<?> data = node.getData();
|
||||
JLabel nameLabel = data.getNameLabel();
|
||||
nameLabel.setText(pre + ": ");
|
||||
addDetailsComponent(nameLabel, 0, y.getValue(), 1, 1, 0, 0);
|
||||
addDetailsComponent(data.getValueField(), 1, y.getValue(), 2, 1, 1, 0);
|
||||
y.increment();
|
||||
} else {
|
||||
for (int i = 0; i < node.getChildCount(); i++) {
|
||||
y.increment();
|
||||
DataObjectTreeNode childNode = (DataObjectTreeNode) node.getChildAt(i);
|
||||
showDataDetails(childNode, pre + "." + childNode.toString(), y);
|
||||
detailsPanel.add(new JSeparator());
|
||||
addDetailsComponent(new JSeparator(), 0, y.getValue(), 3, 1, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addDetailsComponent(
|
||||
Component c, int x, int y, int width, int height, double weightx, double weighty) {
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.fill = GridBagConstraints.HORIZONTAL;
|
||||
gbc.gridx = x;
|
||||
gbc.gridy = y;
|
||||
gbc.gridwidth = width;
|
||||
gbc.gridheight = height;
|
||||
gbc.weightx = weightx;
|
||||
gbc.weighty = weighty;
|
||||
gbc.anchor = GridBagConstraints.NORTH;
|
||||
gbc.insets = new Insets(3, 3, 3, 3);
|
||||
detailsLayout.setConstraints(c, gbc);
|
||||
detailsPanel.add(c);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui;
|
||||
|
||||
import com.beanit.iec61850bean.BasicDataAttribute;
|
||||
import com.beanit.iec61850bean.FcModelNode;
|
||||
import java.awt.Component;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.tree.DefaultTreeCellRenderer;
|
||||
|
||||
public class DataObjectTreeCellRenderer extends DefaultTreeCellRenderer {
|
||||
|
||||
private static final long serialVersionUID = 1682378972258556129L;
|
||||
|
||||
@Override
|
||||
public Component getTreeCellRendererComponent(
|
||||
JTree tree,
|
||||
Object value,
|
||||
boolean sel,
|
||||
boolean expanded,
|
||||
boolean leaf,
|
||||
int row,
|
||||
boolean hasFocus) {
|
||||
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||
|
||||
if (value instanceof DataObjectTreeNode) {
|
||||
DataObjectTreeNode treeNode = (DataObjectTreeNode) value;
|
||||
if (!leaf && treeNode.getNode() instanceof FcModelNode) {
|
||||
setIcon(getLeafIcon());
|
||||
}
|
||||
|
||||
if (treeNode.getNode() instanceof BasicDataAttribute) {
|
||||
BasicDataAttribute attribute = (BasicDataAttribute) treeNode.getNode();
|
||||
String tooltip = attribute.getSAddr();
|
||||
setToolTipText(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui;
|
||||
|
||||
import com.beanit.iec61850bean.BasicDataAttribute;
|
||||
import com.beanit.iec61850bean.BdaBoolean;
|
||||
import com.beanit.iec61850bean.BdaCheck;
|
||||
import com.beanit.iec61850bean.BdaDoubleBitPos;
|
||||
import com.beanit.iec61850bean.BdaEntryTime;
|
||||
import com.beanit.iec61850bean.BdaFloat32;
|
||||
import com.beanit.iec61850bean.BdaFloat64;
|
||||
import com.beanit.iec61850bean.BdaInt16;
|
||||
import com.beanit.iec61850bean.BdaInt16U;
|
||||
import com.beanit.iec61850bean.BdaInt32;
|
||||
import com.beanit.iec61850bean.BdaInt32U;
|
||||
import com.beanit.iec61850bean.BdaInt64;
|
||||
import com.beanit.iec61850bean.BdaInt8;
|
||||
import com.beanit.iec61850bean.BdaInt8U;
|
||||
import com.beanit.iec61850bean.BdaOctetString;
|
||||
import com.beanit.iec61850bean.BdaOptFlds;
|
||||
import com.beanit.iec61850bean.BdaQuality;
|
||||
import com.beanit.iec61850bean.BdaReasonForInclusion;
|
||||
import com.beanit.iec61850bean.BdaTapCommand;
|
||||
import com.beanit.iec61850bean.BdaTimestamp;
|
||||
import com.beanit.iec61850bean.BdaTriggerConditions;
|
||||
import com.beanit.iec61850bean.BdaUnicodeString;
|
||||
import com.beanit.iec61850bean.BdaVisibleString;
|
||||
import com.beanit.iec61850bean.ClientAssociation;
|
||||
import com.beanit.iec61850bean.Fc;
|
||||
import com.beanit.iec61850bean.FcModelNode;
|
||||
import com.beanit.iec61850bean.ModelNode;
|
||||
import com.beanit.iec61850bean.ServiceError;
|
||||
import com.beanit.iec61850bean.clientgui.databind.BooleanDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.CheckDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.DoubleBitPosDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.EntryTimeDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Float32DataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Float64DataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Int16DataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Int16UDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Int32DataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Int32UDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Int64DataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Int8DataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.Int8UDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.OctetStringDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.OptfldsDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.QualityDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.ReasonForInclusionDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.TapCommandDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.TimeStampDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.TriggerConditionDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.UnicodeStringDataBind;
|
||||
import com.beanit.iec61850bean.clientgui.databind.VisibleStringDataBind;
|
||||
import java.io.IOException;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
public class DataObjectTreeNode extends DefaultMutableTreeNode implements DataTreeNode {
|
||||
|
||||
private static final long serialVersionUID = -3596243932937737877L;
|
||||
|
||||
private final ModelNode node;
|
||||
private final BasicDataBind<?> data;
|
||||
|
||||
public DataObjectTreeNode(String name, ModelNode node) {
|
||||
super(name);
|
||||
this.node = node;
|
||||
if (node != null && node.getChildren() == null) {
|
||||
// for (ModelNode child : node.getChildren()) {
|
||||
// if (child instanceof BasicDataAttribute) {
|
||||
// data.add(createDataBind((BasicDataAttribute) child));
|
||||
// }
|
||||
// }
|
||||
data = createDataBind((BasicDataAttribute) node);
|
||||
} else {
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static BasicDataBind<?> createDataBind(BasicDataAttribute bda) {
|
||||
switch (bda.getBasicType()) {
|
||||
case BOOLEAN:
|
||||
return new BooleanDataBind((BdaBoolean) bda);
|
||||
case ENTRY_TIME:
|
||||
return new EntryTimeDataBind((BdaEntryTime) bda);
|
||||
case FLOAT32:
|
||||
return new Float32DataBind((BdaFloat32) bda);
|
||||
case FLOAT64:
|
||||
return new Float64DataBind((BdaFloat64) bda);
|
||||
case INT16:
|
||||
return new Int16DataBind((BdaInt16) bda);
|
||||
case INT16U:
|
||||
return new Int16UDataBind((BdaInt16U) bda);
|
||||
case INT32:
|
||||
return new Int32DataBind((BdaInt32) bda);
|
||||
case INT32U:
|
||||
return new Int32UDataBind((BdaInt32U) bda);
|
||||
case INT64:
|
||||
return new Int64DataBind((BdaInt64) bda);
|
||||
case INT8:
|
||||
return new Int8DataBind((BdaInt8) bda);
|
||||
case INT8U:
|
||||
return new Int8UDataBind((BdaInt8U) bda);
|
||||
case OCTET_STRING:
|
||||
return new OctetStringDataBind((BdaOctetString) bda);
|
||||
case TIMESTAMP:
|
||||
return new TimeStampDataBind((BdaTimestamp) bda);
|
||||
case UNICODE_STRING:
|
||||
return new UnicodeStringDataBind((BdaUnicodeString) bda);
|
||||
case VISIBLE_STRING:
|
||||
return new VisibleStringDataBind((BdaVisibleString) bda);
|
||||
case CHECK:
|
||||
return new CheckDataBind((BdaCheck) bda);
|
||||
case DOUBLE_BIT_POS:
|
||||
return new DoubleBitPosDataBind((BdaDoubleBitPos) bda);
|
||||
case OPTFLDS:
|
||||
return new OptfldsDataBind((BdaOptFlds) bda);
|
||||
case QUALITY:
|
||||
return new QualityDataBind((BdaQuality) bda);
|
||||
case REASON_FOR_INCLUSION:
|
||||
return new ReasonForInclusionDataBind((BdaReasonForInclusion) bda);
|
||||
case TAP_COMMAND:
|
||||
return new TapCommandDataBind((BdaTapCommand) bda);
|
||||
case TRIGGER_CONDITIONS:
|
||||
return new TriggerConditionDataBind((BdaTriggerConditions) bda);
|
||||
default:
|
||||
throw new IllegalArgumentException("BasicType " + bda.getBasicType() + " unknown");
|
||||
}
|
||||
}
|
||||
|
||||
public ModelNode getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicDataBind<?> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(ClientAssociation association) throws ServiceError, IOException {
|
||||
if (association != null) {
|
||||
association.getDataValues((FcModelNode) node);
|
||||
}
|
||||
if (data != null) {
|
||||
data.reset();
|
||||
} else {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (getChildAt(i) instanceof DataObjectTreeNode) {
|
||||
DataTreeNode child = (DataTreeNode) getChildAt(i);
|
||||
child.reset(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeValues(ClientAssociation association) throws ServiceError, IOException {
|
||||
if (data != null) {
|
||||
data.write();
|
||||
} else {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (getChildAt(i) instanceof DataObjectTreeNode) {
|
||||
DataTreeNode child = (DataTreeNode) getChildAt(i);
|
||||
child.writeValues(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (association != null) {
|
||||
association.setDataValues((FcModelNode) node);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writable() {
|
||||
if (node instanceof FcModelNode) {
|
||||
FcModelNode modelNode = (FcModelNode) node;
|
||||
Fc constraint = modelNode.getFc();
|
||||
return constraint != Fc.ST && constraint != Fc.MX;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readable() {
|
||||
return node instanceof FcModelNode;
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui;
|
||||
|
||||
import com.beanit.iec61850bean.ClientAssociation;
|
||||
import com.beanit.iec61850bean.DataSet;
|
||||
import com.beanit.iec61850bean.ServiceError;
|
||||
import java.io.IOException;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
|
||||
public class DataSetTreeNode extends DefaultMutableTreeNode implements DataTreeNode {
|
||||
|
||||
private static final long serialVersionUID = 7919716359809465616L;
|
||||
|
||||
private final DataSet node;
|
||||
|
||||
public DataSetTreeNode(String name, DataSet node) {
|
||||
super(name);
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public DataSet getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(ClientAssociation association) throws ServiceError, IOException {
|
||||
if (association != null) {
|
||||
association.getDataSetValues(node);
|
||||
}
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (getChildAt(i) instanceof DataObjectTreeNode) {
|
||||
DataTreeNode child = (DataTreeNode) getChildAt(i);
|
||||
child.reset(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeValues(ClientAssociation association) throws ServiceError, IOException {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
if (getChildAt(i) instanceof DataObjectTreeNode) {
|
||||
DataTreeNode child = (DataTreeNode) getChildAt(i);
|
||||
child.writeValues(null);
|
||||
}
|
||||
}
|
||||
if (association != null) {
|
||||
association.setDataSetValues(node);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicDataBind<?> getData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readable() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui;
|
||||
|
||||
import com.beanit.iec61850bean.ClientAssociation;
|
||||
import com.beanit.iec61850bean.ServiceError;
|
||||
import java.io.IOException;
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
public interface DataTreeNode {
|
||||
|
||||
BasicDataBind<?> getData();
|
||||
|
||||
void reset(ClientAssociation association) throws ServiceError, IOException;
|
||||
|
||||
void writeValues(ClientAssociation association) throws ServiceError, IOException;
|
||||
|
||||
int getChildCount();
|
||||
|
||||
TreeNode getChildAt(int index);
|
||||
|
||||
boolean writable();
|
||||
|
||||
boolean readable();
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui;
|
||||
|
||||
import com.beanit.iec61850bean.DataSet;
|
||||
import com.beanit.iec61850bean.Fc;
|
||||
import com.beanit.iec61850bean.FcModelNode;
|
||||
import com.beanit.iec61850bean.LogicalDevice;
|
||||
import com.beanit.iec61850bean.LogicalNode;
|
||||
import com.beanit.iec61850bean.ModelNode;
|
||||
import com.beanit.iec61850bean.ServerModel;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
public class ServerModelParser {
|
||||
|
||||
private final ServerModel model;
|
||||
private DataObjectTreeNode modelTree;
|
||||
|
||||
public ServerModelParser(ServerModel model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
public TreeNode getModelTree() {
|
||||
if (modelTree == null) {
|
||||
createModelTree();
|
||||
}
|
||||
return modelTree;
|
||||
}
|
||||
|
||||
private synchronized void createModelTree() {
|
||||
if (modelTree == null) {
|
||||
modelTree = new DataObjectTreeNode("server", null);
|
||||
for (ModelNode node : model.getChildren()) {
|
||||
if (node instanceof LogicalDevice == false) {
|
||||
System.out.println(
|
||||
"Node " + node.getName() + " is " + node.getClass() + " (should be LogicalDevice)");
|
||||
continue;
|
||||
}
|
||||
addLogicalDevice(modelTree, (LogicalDevice) node);
|
||||
}
|
||||
for (DataSet dataSet : model.getDataSets()) {
|
||||
addDataSet(modelTree, dataSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addLogicalDevice(DataObjectTreeNode root, LogicalDevice node) {
|
||||
DataObjectTreeNode treeLD = new DataObjectTreeNode(node.getName(), node);
|
||||
root.add(treeLD);
|
||||
for (ModelNode subNode : node.getChildren()) {
|
||||
if (subNode instanceof LogicalNode == false) {
|
||||
System.out.println(
|
||||
"Node " + subNode.getName() + " is " + subNode.getClass() + " (should be LogicalNode)");
|
||||
continue;
|
||||
}
|
||||
addLogicalNode(treeLD, (LogicalNode) subNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void addLogicalNode(DataObjectTreeNode parent, LogicalNode node) {
|
||||
DataObjectTreeNode treeLN = new DataObjectTreeNode(node.getName(), node);
|
||||
parent.add(treeLN);
|
||||
Collection<ModelNode> children = node.getChildren();
|
||||
Map<String, Set<Fc>> childMap = new HashMap<>();
|
||||
for (ModelNode child : children) {
|
||||
if (!childMap.containsKey(child.getName())) {
|
||||
childMap.put(child.getName(), new HashSet<Fc>());
|
||||
}
|
||||
childMap.get(child.getName()).add(((FcModelNode) child).getFc());
|
||||
}
|
||||
for (Map.Entry<String, Set<Fc>> childEntry : childMap.entrySet()) {
|
||||
addFunctionalConstraintObject(treeLN, node, childEntry.getKey(), childEntry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void addDataSet(DataObjectTreeNode parent, DataSet node) {
|
||||
DataSetTreeNode treeDS = new DataSetTreeNode(node.getReferenceStr(), node);
|
||||
parent.add(treeDS);
|
||||
Collection<FcModelNode> children = node.getMembers();
|
||||
for (ModelNode child : children) {
|
||||
addFunctionalConstraintObject(treeDS, child);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFunctionalConstraintObject(
|
||||
DataObjectTreeNode parent, LogicalNode parentNode, String childName, Set<Fc> childFcs) {
|
||||
DataObjectTreeNode treeFCDO = new DataObjectTreeNode(childName, null);
|
||||
parent.add(treeFCDO);
|
||||
|
||||
for (Fc constraint : childFcs) {
|
||||
ModelNode subNode = parentNode.getChild(childName, constraint);
|
||||
addDataObject(treeFCDO, "[" + constraint + "]", subNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void addFunctionalConstraintObject(DataSetTreeNode parent, ModelNode node) {
|
||||
DataObjectTreeNode treeFCDO = new DataObjectTreeNode(node.getReference().toString(), node);
|
||||
parent.add(treeFCDO);
|
||||
if (node.getChildren() != null) {
|
||||
for (ModelNode subNode : node.getChildren()) {
|
||||
addDataObject(treeFCDO, subNode.getName(), subNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addDataObject(DataObjectTreeNode parent, String name, ModelNode node) {
|
||||
DataObjectTreeNode treeDO = new DataObjectTreeNode(name, node);
|
||||
parent.add(treeDO);
|
||||
if (node.getChildren() != null) {
|
||||
for (ModelNode subNode : node.getChildren()) {
|
||||
addDataObject(treeDO, subNode.getName(), subNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class SettingsFrame extends JDialog implements ActionListener {
|
||||
|
||||
private static final long serialVersionUID = -411845634137160667L;
|
||||
|
||||
private int tselLocal1 = 0;
|
||||
private final JTextField tselLocalField1 = new JTextField(Integer.toString(tselLocal1));
|
||||
private int tselLocal2 = 0;
|
||||
private final JTextField tselLocalField2 = new JTextField(Integer.toString(tselLocal2));
|
||||
private int tselRemote1 = 0;
|
||||
private final JTextField tselRemoteField1 = new JTextField(Integer.toString(tselRemote1));
|
||||
private int tselRemote2 = 1;
|
||||
private final JTextField tselRemoteField2 = new JTextField(Integer.toString(tselRemote2));
|
||||
|
||||
public SettingsFrame() {
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
|
||||
final GridBagLayout layout = new GridBagLayout();
|
||||
setLayout(layout);
|
||||
|
||||
this.setSize(200, 120);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
JLabel label = new JLabel("TSelLocal: ");
|
||||
GridBagConstraints constraint = new GridBagConstraints();
|
||||
constraint.gridwidth = 1;
|
||||
constraint.gridheight = 1;
|
||||
constraint.gridx = 0;
|
||||
constraint.gridy = 0;
|
||||
constraint.insets = new Insets(5, 5, 5, 5);
|
||||
constraint.anchor = GridBagConstraints.WEST;
|
||||
layout.setConstraints(label, constraint);
|
||||
add(label);
|
||||
|
||||
constraint = new GridBagConstraints();
|
||||
constraint.fill = GridBagConstraints.HORIZONTAL;
|
||||
constraint.gridwidth = 1;
|
||||
constraint.gridheight = 1;
|
||||
constraint.gridx = 1;
|
||||
constraint.gridy = 0;
|
||||
constraint.weightx = 1;
|
||||
constraint.insets = new Insets(5, 5, 5, 5);
|
||||
constraint.anchor = GridBagConstraints.WEST;
|
||||
layout.setConstraints(tselLocalField1, constraint);
|
||||
add(tselLocalField1);
|
||||
|
||||
constraint = new GridBagConstraints();
|
||||
constraint.fill = GridBagConstraints.HORIZONTAL;
|
||||
constraint.gridwidth = 1;
|
||||
constraint.gridheight = 1;
|
||||
constraint.gridx = 2;
|
||||
constraint.gridy = 0;
|
||||
constraint.weightx = 1;
|
||||
constraint.insets = new Insets(5, 5, 5, 5);
|
||||
constraint.anchor = GridBagConstraints.WEST;
|
||||
layout.setConstraints(tselLocalField2, constraint);
|
||||
add(tselLocalField2);
|
||||
|
||||
label = new JLabel("TSelRemote: ");
|
||||
constraint = new GridBagConstraints();
|
||||
constraint.gridwidth = 1;
|
||||
constraint.gridheight = 1;
|
||||
constraint.gridx = 0;
|
||||
constraint.gridy = 1;
|
||||
constraint.insets = new Insets(5, 5, 5, 5);
|
||||
constraint.anchor = GridBagConstraints.WEST;
|
||||
layout.setConstraints(label, constraint);
|
||||
add(label);
|
||||
|
||||
constraint = new GridBagConstraints();
|
||||
constraint.fill = GridBagConstraints.HORIZONTAL;
|
||||
constraint.gridwidth = 1;
|
||||
constraint.gridheight = 1;
|
||||
constraint.gridx = 1;
|
||||
constraint.gridy = 1;
|
||||
constraint.weightx = 1;
|
||||
constraint.insets = new Insets(5, 5, 5, 5);
|
||||
constraint.anchor = GridBagConstraints.WEST;
|
||||
layout.setConstraints(tselRemoteField1, constraint);
|
||||
add(tselRemoteField1);
|
||||
|
||||
constraint = new GridBagConstraints();
|
||||
constraint.fill = GridBagConstraints.HORIZONTAL;
|
||||
constraint.gridwidth = 1;
|
||||
constraint.gridheight = 1;
|
||||
constraint.gridx = 2;
|
||||
constraint.gridy = 1;
|
||||
constraint.weightx = 1;
|
||||
constraint.insets = new Insets(5, 5, 5, 5);
|
||||
constraint.anchor = GridBagConstraints.WEST;
|
||||
layout.setConstraints(tselRemoteField2, constraint);
|
||||
add(tselRemoteField2);
|
||||
|
||||
JButton button = new JButton("Cancel");
|
||||
button.setActionCommand("Cancel");
|
||||
button.addActionListener(this);
|
||||
constraint.gridwidth = 1;
|
||||
constraint.gridheight = 1;
|
||||
constraint.gridx = 0;
|
||||
constraint.gridy = 2;
|
||||
constraint.insets = new Insets(5, 5, 5, 5);
|
||||
constraint.anchor = GridBagConstraints.SOUTHWEST;
|
||||
layout.setConstraints(button, constraint);
|
||||
add(button);
|
||||
|
||||
button = new JButton("OK");
|
||||
button.setActionCommand("Okay");
|
||||
button.addActionListener(this);
|
||||
constraint.gridwidth = 2;
|
||||
constraint.gridheight = 1;
|
||||
constraint.gridx = 1;
|
||||
constraint.gridy = 2;
|
||||
constraint.insets = new Insets(5, 5, 5, 5);
|
||||
constraint.anchor = GridBagConstraints.SOUTHWEST;
|
||||
layout.setConstraints(button, constraint);
|
||||
add(button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if ("cancel".equalsIgnoreCase(e.getActionCommand())) {
|
||||
tselLocalField1.setText(Integer.toString(tselLocal1 & 0xFF));
|
||||
tselLocalField2.setText(Integer.toString(tselLocal2 & 0xFF));
|
||||
tselRemoteField1.setText(Integer.toString(tselRemote1 & 0xFF));
|
||||
tselRemoteField2.setText(Integer.toString(tselRemote2 & 0xFF));
|
||||
setVisible(false);
|
||||
} else if ("okay".equalsIgnoreCase(e.getActionCommand())) {
|
||||
tselLocal1 = parseTextField(tselLocalField1, tselLocal1);
|
||||
tselLocal2 = parseTextField(tselLocalField2, tselLocal2);
|
||||
tselRemote1 = parseTextField(tselRemoteField1, tselRemote1);
|
||||
tselRemote2 = parseTextField(tselRemoteField2, tselRemote2);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getTselLocal() {
|
||||
return new byte[] {(byte) tselLocal1, (byte) tselLocal2};
|
||||
}
|
||||
|
||||
public void setTselLocal(byte[] tsel) {
|
||||
if (tsel.length != 2) {
|
||||
throw new IllegalArgumentException("TSel must consist of 2 bytes");
|
||||
}
|
||||
tselLocal1 = tsel[0];
|
||||
tselLocal2 = tsel[1];
|
||||
|
||||
tselLocalField1.setText(Integer.toString(tselLocal1 & 0xFF));
|
||||
tselLocalField2.setText(Integer.toString(tselLocal2 & 0xFF));
|
||||
}
|
||||
|
||||
public byte[] getTselRemote() {
|
||||
return new byte[] {(byte) tselRemote1, (byte) tselRemote2};
|
||||
}
|
||||
|
||||
public void setTselRemote(byte[] tsel) {
|
||||
if (tsel.length != 2) {
|
||||
throw new IllegalArgumentException("TSel must consist of 2 bytes");
|
||||
}
|
||||
tselRemote1 = tsel[0];
|
||||
tselRemote2 = tsel[1];
|
||||
|
||||
tselRemoteField1.setText(Integer.toString(tselRemote1 & 0xFF));
|
||||
tselRemoteField2.setText(Integer.toString(tselRemote2 & 0xFF));
|
||||
}
|
||||
|
||||
private int parseTextField(JTextField field, int oldValue) {
|
||||
int value = oldValue;
|
||||
try {
|
||||
int newValue = Integer.parseInt(field.getText());
|
||||
if (newValue >= 0 && newValue <= 255) {
|
||||
value = newValue;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return oldValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaBoolean;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
public class BooleanDataBind extends BasicDataBind<BdaBoolean> {
|
||||
|
||||
private JCheckBox checkbox;
|
||||
|
||||
public BooleanDataBind(BdaBoolean data) {
|
||||
super(data, BdaType.BOOLEAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
checkbox = new JCheckBox();
|
||||
checkbox.setBorder(null);
|
||||
checkbox.setSelected(data.getValue());
|
||||
return checkbox;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
checkbox.setSelected(data.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(checkbox.isSelected());
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaCheck;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import java.awt.Component;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class CheckDataBind extends BasicDataBind<BdaCheck> {
|
||||
|
||||
private final JCheckBox interlock = new JCheckBox("Interlock");
|
||||
private final JCheckBox synchron = new JCheckBox("Synchron");
|
||||
|
||||
public CheckDataBind(BdaCheck data) {
|
||||
super(data, BdaType.CHECK);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
interlock.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
JPanel valuePanel = new JPanel();
|
||||
valuePanel.setLayout(new BoxLayout(valuePanel, BoxLayout.PAGE_AXIS));
|
||||
valuePanel.add(interlock);
|
||||
valuePanel.add(synchron);
|
||||
return valuePanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
interlock.setSelected(data.getInterlockCheck());
|
||||
synchron.setSelected(data.getSynchrocheck());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setInterlockCheck(interlock.isSelected());
|
||||
data.setSynchrocheck(synchron.isSelected());
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaDoubleBitPos;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
public class DoubleBitPosDataBind extends BasicDataBind<BdaDoubleBitPos> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final JComboBox valueField = new JComboBox(BdaDoubleBitPos.DoubleBitPos.values());
|
||||
|
||||
public DoubleBitPosDataBind(BdaDoubleBitPos data) {
|
||||
super(data, BdaType.DOUBLE_BIT_POS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
return valueField;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
valueField.setSelectedItem(data.getDoubleBitPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
// TODO uncomment once data.setTapCommand() is implemented
|
||||
// data.setTapCommand(valueField.getSelectedItem());
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaEntryTime;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
public class EntryTimeDataBind extends BasicDataBind<BdaEntryTime> {
|
||||
|
||||
public EntryTimeDataBind(BdaEntryTime data) {
|
||||
super(data, BdaType.ENTRY_TIME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
byte[] value = data.getValue();
|
||||
StringBuilder sb;
|
||||
|
||||
sb = new StringBuilder("EntryTime [");
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
sb.append(Integer.toHexString(value[i] & 0xff));
|
||||
if (i != value.length - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append("]");
|
||||
return new JLabel(sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
// ignore for now
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
// ignore for now
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaFloat32;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Float32DataBind extends TextFieldDataBind<BdaFloat32> {
|
||||
|
||||
private static final FloatFilter FILTER = new FloatFilter();
|
||||
|
||||
public Float32DataBind(BdaFloat32 data) {
|
||||
super(data, BdaType.FLOAT32, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(data.getFloat().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
float newFloat = Float.parseFloat(inputField.getText());
|
||||
data.setFloat(newFloat);
|
||||
}
|
||||
|
||||
private static class FloatFilter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
Float.parseFloat(text);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaFloat64;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Float64DataBind extends TextFieldDataBind<BdaFloat64> {
|
||||
|
||||
private static final DoubleFilter FILTER = new DoubleFilter();
|
||||
|
||||
public Float64DataBind(BdaFloat64 data) {
|
||||
super(data, BdaType.FLOAT64, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(data.getDouble().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
double newDouble = Double.parseDouble(inputField.getText());
|
||||
data.setDouble(newDouble);
|
||||
}
|
||||
|
||||
private static class DoubleFilter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
Double.parseDouble(text);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaInt16;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Int16DataBind extends TextFieldDataBind<BdaInt16> {
|
||||
|
||||
private static final Int16Filter FILTER = new Int16Filter();
|
||||
|
||||
public Int16DataBind(BdaInt16 data) {
|
||||
super(data, BdaType.INT16, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(Short.toString(data.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(Short.parseShort(inputField.getText()));
|
||||
}
|
||||
|
||||
private static class Int16Filter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
Short.parseShort(text);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaInt16U;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Int16UDataBind extends TextFieldDataBind<BdaInt16U> {
|
||||
|
||||
private static final UInt16Filter FILTER = new UInt16Filter();
|
||||
|
||||
public Int16UDataBind(BdaInt16U data) {
|
||||
super(data, BdaType.INT16U, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(Integer.toString(data.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(Integer.parseInt(inputField.getText()));
|
||||
}
|
||||
|
||||
private static class UInt16Filter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
int value = Integer.parseInt(text);
|
||||
return value >= 0 && value <= 0xFFFF;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaInt32;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Int32DataBind extends TextFieldDataBind<BdaInt32> {
|
||||
|
||||
private static final Int32Filter FILTER = new Int32Filter();
|
||||
|
||||
public Int32DataBind(BdaInt32 data) {
|
||||
super(data, BdaType.INT32, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(Integer.toString(data.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(Integer.parseInt(inputField.getText()));
|
||||
}
|
||||
|
||||
private static class Int32Filter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
Integer.parseInt(text);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaInt32U;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Int32UDataBind extends TextFieldDataBind<BdaInt32U> {
|
||||
|
||||
private static final UInt32Filter FILTER = new UInt32Filter();
|
||||
|
||||
public Int32UDataBind(BdaInt32U data) {
|
||||
super(data, BdaType.INT32U, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(Long.toString(data.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(Long.parseLong(inputField.getText()));
|
||||
}
|
||||
|
||||
private static class UInt32Filter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
long value = Long.parseLong(text);
|
||||
return value >= 0 && value <= 0xFFFFFFFFL;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaInt64;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Int64DataBind extends TextFieldDataBind<BdaInt64> {
|
||||
|
||||
private static final Int64Filter FILTER = new Int64Filter();
|
||||
|
||||
public Int64DataBind(BdaInt64 data) {
|
||||
super(data, BdaType.INT64, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(Long.toString(data.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(Long.parseLong(inputField.getText()));
|
||||
}
|
||||
|
||||
private static class Int64Filter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
Long.parseLong(text);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaInt8;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Int8DataBind extends TextFieldDataBind<BdaInt8> {
|
||||
|
||||
private static final Int8Filter FILTER = new Int8Filter();
|
||||
|
||||
public Int8DataBind(BdaInt8 data) {
|
||||
super(data, BdaType.INT8, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(Byte.toString(data.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(Byte.parseByte(inputField.getText()));
|
||||
}
|
||||
|
||||
private static class Int8Filter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
Byte.parseByte(text);
|
||||
return true;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaInt8U;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
|
||||
public class Int8UDataBind extends TextFieldDataBind<BdaInt8U> {
|
||||
|
||||
private static final UInt8Filter FILTER = new UInt8Filter();
|
||||
|
||||
public Int8UDataBind(BdaInt8U data) {
|
||||
super(data, BdaType.INT8U, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(Short.toString(data.getValue()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(Short.parseShort(inputField.getText()));
|
||||
}
|
||||
|
||||
private static class UInt8Filter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
short value = Short.parseShort(text);
|
||||
return value >= 0 && value <= 0xFF;
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaOctetString;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
public class OctetStringDataBind extends BasicDataBind<BdaOctetString> {
|
||||
|
||||
public OctetStringDataBind(BdaOctetString data) {
|
||||
super(data, BdaType.OCTET_STRING);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
byte[] value = data.getValue();
|
||||
StringBuilder sb;
|
||||
|
||||
sb = new StringBuilder("OctetString [");
|
||||
for (int i = 0; i < value.length; i++) {
|
||||
sb.append(Integer.toHexString(value[i] & 0xff));
|
||||
if (i != value.length - 1) {
|
||||
sb.append(", ");
|
||||
}
|
||||
}
|
||||
sb.append("]");
|
||||
return new JLabel(sb.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
// ignore for now
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
// ignore for now
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaOptFlds;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import java.awt.Component;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class OptfldsDataBind extends BasicDataBind<BdaOptFlds> {
|
||||
|
||||
private final JCheckBox bufferOverflow = new JCheckBox("BufferOverflow");
|
||||
private final JCheckBox configRevision = new JCheckBox("ConfigRevision");
|
||||
private final JCheckBox dataReference = new JCheckBox("DataReference");
|
||||
private final JCheckBox dataSetName = new JCheckBox("DataSetName");
|
||||
private final JCheckBox entryId = new JCheckBox("EntryId");
|
||||
private final JCheckBox reasonForInclusion = new JCheckBox("ReasonForInclusion");
|
||||
private final JCheckBox reportTimestamp = new JCheckBox("ReportTimestamp");
|
||||
private final JCheckBox segmentation = new JCheckBox("Segmentation");
|
||||
private final JCheckBox sequenceNumber = new JCheckBox("SequenceNumber");
|
||||
|
||||
public OptfldsDataBind(BdaOptFlds data) {
|
||||
super(data, BdaType.OPTFLDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
bufferOverflow.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
JPanel valuePanel = new JPanel();
|
||||
valuePanel.setLayout(new BoxLayout(valuePanel, BoxLayout.PAGE_AXIS));
|
||||
valuePanel.add(bufferOverflow);
|
||||
valuePanel.add(configRevision);
|
||||
valuePanel.add(dataReference);
|
||||
valuePanel.add(dataSetName);
|
||||
valuePanel.add(entryId);
|
||||
valuePanel.add(reasonForInclusion);
|
||||
valuePanel.add(reportTimestamp);
|
||||
valuePanel.add(segmentation);
|
||||
valuePanel.add(sequenceNumber);
|
||||
return valuePanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
bufferOverflow.setSelected(data.isBufferOverflow());
|
||||
configRevision.setSelected(data.isConfigRevision());
|
||||
dataReference.setSelected(data.isDataReference());
|
||||
dataSetName.setSelected(data.isDataSetName());
|
||||
entryId.setSelected(data.isEntryId());
|
||||
reasonForInclusion.setSelected(data.isReasonForInclusion());
|
||||
reportTimestamp.setSelected(data.isReportTimestamp());
|
||||
segmentation.setSelected(data.isSegmentation());
|
||||
sequenceNumber.setSelected(data.isSequenceNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setBufferOverflow(bufferOverflow.isSelected());
|
||||
data.setConfigRevision(configRevision.isSelected());
|
||||
data.setDataReference(dataReference.isSelected());
|
||||
data.setDataSetName(dataSetName.isSelected());
|
||||
data.setEntryId(entryId.isSelected());
|
||||
data.setReasonForInclusion(reasonForInclusion.isSelected());
|
||||
data.setReportTimestamp(reportTimestamp.isSelected());
|
||||
data.setSegmentation(segmentation.isSelected());
|
||||
data.setSequenceNumber(sequenceNumber.isSelected());
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaQuality;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import java.awt.Component;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class QualityDataBind extends BasicDataBind<BdaQuality> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final JComboBox validity = new JComboBox(BdaQuality.Validity.values());
|
||||
|
||||
private final JCheckBox badReference = new JCheckBox("BadReference");
|
||||
private final JCheckBox failure = new JCheckBox("Failure");
|
||||
private final JCheckBox inaccurate = new JCheckBox("Inaccurate");
|
||||
private final JCheckBox inconsistent = new JCheckBox("Inconsistent");
|
||||
private final JCheckBox oldData = new JCheckBox("OldData");
|
||||
private final JCheckBox operatorBlocked = new JCheckBox("OperatorBlocked");
|
||||
private final JCheckBox oscillatory = new JCheckBox("Oscillatory");
|
||||
private final JCheckBox outOfRange = new JCheckBox("OutOfRange");
|
||||
private final JCheckBox overflow = new JCheckBox("Overflow");
|
||||
private final JCheckBox substituded = new JCheckBox("Substituded");
|
||||
private final JCheckBox test = new JCheckBox("Test");
|
||||
|
||||
public QualityDataBind(BdaQuality data) {
|
||||
super(data, BdaType.QUALITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
validity.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
JPanel valuePanel = new JPanel();
|
||||
valuePanel.setLayout(new BoxLayout(valuePanel, BoxLayout.PAGE_AXIS));
|
||||
valuePanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
valuePanel.add(validity);
|
||||
valuePanel.add(badReference);
|
||||
valuePanel.add(failure);
|
||||
valuePanel.add(inaccurate);
|
||||
valuePanel.add(inconsistent);
|
||||
valuePanel.add(oldData);
|
||||
valuePanel.add(operatorBlocked);
|
||||
valuePanel.add(oscillatory);
|
||||
valuePanel.add(outOfRange);
|
||||
valuePanel.add(overflow);
|
||||
valuePanel.add(substituded);
|
||||
valuePanel.add(test);
|
||||
return valuePanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
validity.setSelectedItem(data.getValidity());
|
||||
badReference.setSelected(data.isBadReference());
|
||||
failure.setSelected(data.isFailure());
|
||||
inaccurate.setSelected(data.isInaccurate());
|
||||
inconsistent.setSelected(data.isInconsistent());
|
||||
oldData.setSelected(data.isOldData());
|
||||
operatorBlocked.setSelected(data.isOperatorBlocked());
|
||||
oscillatory.setSelected(data.isOscillatory());
|
||||
outOfRange.setSelected(data.isOutOfRange());
|
||||
overflow.setSelected(data.isOverflow());
|
||||
substituded.setSelected(data.isSubstituted());
|
||||
test.setSelected(data.isTest());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
// TODO uncomment once mutators are implemented
|
||||
// data.setValidity(validity.getSelectedItem());
|
||||
// data.setBadReference(badReference.isSelected());
|
||||
// data.setFailure(failure.isSelected());
|
||||
// data.setInaccurate(inaccurate.isSelected());
|
||||
// data.setInconsistent(inconsistent.isSelected());
|
||||
// data.setOldData(oldData.isSelected());
|
||||
// data.setOperatorBlocked(operatorBlocked.isSelected());
|
||||
// data.setOlscillatory(oscillatory.isSelected());
|
||||
// data.setOutOfRange(outOfRange.isSelected());
|
||||
// data.setOverflow(overflow.isSelected());
|
||||
// data.setSubstituded(substituded.isSelected());
|
||||
// data.setTest(test.isSelected());
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaReasonForInclusion;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import java.awt.Component;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class ReasonForInclusionDataBind extends BasicDataBind<BdaReasonForInclusion> {
|
||||
|
||||
private final JCheckBox applicationTrigger = new JCheckBox("ApplicationTrigger");
|
||||
private final JCheckBox dataChange = new JCheckBox("DataChange");
|
||||
private final JCheckBox dataUpdate = new JCheckBox("DataUpdate");
|
||||
private final JCheckBox generalInterrogation = new JCheckBox("GeneralInterrogation");
|
||||
private final JCheckBox integrity = new JCheckBox("Integrity");
|
||||
private final JCheckBox qualitychanged = new JCheckBox("QualityChanged");
|
||||
|
||||
public ReasonForInclusionDataBind(BdaReasonForInclusion data) {
|
||||
super(data, BdaType.REASON_FOR_INCLUSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
applicationTrigger.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
JPanel valuePanel = new JPanel();
|
||||
valuePanel.setLayout(new BoxLayout(valuePanel, BoxLayout.PAGE_AXIS));
|
||||
valuePanel.add(applicationTrigger);
|
||||
valuePanel.add(dataChange);
|
||||
valuePanel.add(dataUpdate);
|
||||
valuePanel.add(generalInterrogation);
|
||||
valuePanel.add(integrity);
|
||||
valuePanel.add(qualitychanged);
|
||||
return valuePanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
applicationTrigger.setSelected(data.isApplicationTrigger());
|
||||
dataChange.setSelected(data.isDataChange());
|
||||
dataUpdate.setSelected(data.isDataUpdate());
|
||||
generalInterrogation.setSelected(data.isGeneralInterrogation());
|
||||
integrity.setSelected(data.isIntegrity());
|
||||
qualitychanged.setSelected(data.isQualityChange());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setApplicationTrigger(applicationTrigger.isSelected());
|
||||
data.setDataChange(dataChange.isSelected());
|
||||
data.setDataUpdate(dataUpdate.isSelected());
|
||||
data.setGeneralInterrogation(generalInterrogation.isSelected());
|
||||
data.setIntegrity(integrity.isSelected());
|
||||
data.setQualityChange(qualitychanged.isSelected());
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaTapCommand;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
public class TapCommandDataBind extends BasicDataBind<BdaTapCommand> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final JComboBox tapCommand = new JComboBox(BdaTapCommand.TapCommand.values());
|
||||
|
||||
public TapCommandDataBind(BdaTapCommand data) {
|
||||
super(data, BdaType.TAP_COMMAND);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
return tapCommand;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
tapCommand.setSelectedItem(data.getTapCommand());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
// TODO uncomment once data.setTapCommand is implemented
|
||||
// data.setTapCommand(tapCommand.getSelectedItem());
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BasicDataAttribute;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Document;
|
||||
import javax.swing.text.DocumentFilter;
|
||||
import javax.swing.text.PlainDocument;
|
||||
|
||||
public abstract class TextFieldDataBind<E extends BasicDataAttribute> extends BasicDataBind<E> {
|
||||
|
||||
private final DocumentFilter filter;
|
||||
protected JTextField inputField;
|
||||
|
||||
TextFieldDataBind(E data, BdaType type, AbstractFilter filter) {
|
||||
super(data, type);
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
inputField = new JTextField();
|
||||
PlainDocument doc = (PlainDocument) inputField.getDocument();
|
||||
doc.setDocumentFilter(filter);
|
||||
resetImpl();
|
||||
return inputField;
|
||||
}
|
||||
|
||||
protected abstract static class AbstractFilter extends DocumentFilter {
|
||||
@Override
|
||||
public final void insertString(FilterBypass fb, int offset, String string, AttributeSet attr)
|
||||
throws BadLocationException {
|
||||
|
||||
Document doc = fb.getDocument();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(doc.getText(0, doc.getLength()));
|
||||
sb.insert(offset, string);
|
||||
|
||||
if (test(sb.toString())) {
|
||||
super.insertString(fb, offset, string, attr);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void replace(
|
||||
FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
|
||||
throws BadLocationException {
|
||||
|
||||
Document doc = fb.getDocument();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(doc.getText(0, doc.getLength()));
|
||||
sb.replace(offset, offset + length, text);
|
||||
|
||||
if (test(sb.toString())) {
|
||||
super.replace(fb, offset, length, text, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
|
||||
Document doc = fb.getDocument();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(doc.getText(0, doc.getLength()));
|
||||
sb.delete(offset, offset + length);
|
||||
|
||||
if (test(sb.toString())) {
|
||||
super.remove(fb, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean test(String text);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaTimestamp;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeParseException;
|
||||
|
||||
public class TimeStampDataBind extends TextFieldDataBind<BdaTimestamp> {
|
||||
|
||||
private static final TimestampFilter FILTER = new TimestampFilter();
|
||||
|
||||
public TimeStampDataBind(BdaTimestamp data) {
|
||||
super(data, BdaType.TIMESTAMP, FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(data.getInstant().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setInstant(Instant.parse(inputField.getText()));
|
||||
}
|
||||
|
||||
private static class TimestampFilter extends AbstractFilter {
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
Instant.parse(text);
|
||||
return true;
|
||||
} catch (DateTimeParseException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaTriggerConditions;
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.clientgui.BasicDataBind;
|
||||
import java.awt.Component;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
public class TriggerConditionDataBind extends BasicDataBind<BdaTriggerConditions> {
|
||||
|
||||
private final JCheckBox dataChange = new JCheckBox("DataChange");
|
||||
private final JCheckBox dataUpdate = new JCheckBox("DataUpdate");
|
||||
private final JCheckBox generalInterrogation = new JCheckBox("GeneralInterrogation");
|
||||
private final JCheckBox integrity = new JCheckBox("Integrity");
|
||||
private final JCheckBox qualityChange = new JCheckBox("QualityChange");
|
||||
|
||||
public TriggerConditionDataBind(BdaTriggerConditions data) {
|
||||
super(data, BdaType.TRIGGER_CONDITIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent init() {
|
||||
dataChange.setAlignmentX(Component.LEFT_ALIGNMENT);
|
||||
JPanel valuePanel = new JPanel();
|
||||
valuePanel.setLayout(new BoxLayout(valuePanel, BoxLayout.PAGE_AXIS));
|
||||
valuePanel.add(dataChange);
|
||||
valuePanel.add(dataUpdate);
|
||||
valuePanel.add(generalInterrogation);
|
||||
valuePanel.add(integrity);
|
||||
valuePanel.add(qualityChange);
|
||||
return valuePanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
dataChange.setSelected(data.isDataChange());
|
||||
dataUpdate.setSelected(data.isDataUpdate());
|
||||
generalInterrogation.setSelected(data.isGeneralInterrogation());
|
||||
integrity.setSelected(data.isIntegrity());
|
||||
qualityChange.setSelected(data.isQualityChange());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setDataChange(dataChange.isSelected());
|
||||
data.setDataUpdate(dataUpdate.isSelected());
|
||||
data.setGeneralInterrogation(generalInterrogation.isSelected());
|
||||
data.setIntegrity(integrity.isSelected());
|
||||
data.setQualityChange(qualityChange.isSelected());
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.BdaUnicodeString;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class UnicodeStringDataBind extends TextFieldDataBind<BdaUnicodeString> {
|
||||
|
||||
private static final Charset UTF8 = StandardCharsets.UTF_8;
|
||||
|
||||
public UnicodeStringDataBind(BdaUnicodeString data) {
|
||||
super(data, BdaType.UNICODE_STRING, new Utf8Filter(data.getMaxLength()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(new String(data.getValue(), UTF8));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(UTF8.encode(inputField.getText()).array());
|
||||
}
|
||||
|
||||
private static class Utf8Filter extends AbstractFilter {
|
||||
private final CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder();
|
||||
private final int maxBytes;
|
||||
|
||||
public Utf8Filter(int maxBytes) {
|
||||
this.maxBytes = maxBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
byte[] codedString = encoder.encode(CharBuffer.wrap(text)).array();
|
||||
return codedString.length <= maxBytes;
|
||||
} catch (CharacterCodingException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.databind;
|
||||
|
||||
import com.beanit.iec61850bean.BdaType;
|
||||
import com.beanit.iec61850bean.BdaVisibleString;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class VisibleStringDataBind extends TextFieldDataBind<BdaVisibleString> {
|
||||
|
||||
private static final Charset ASCII = StandardCharsets.US_ASCII;
|
||||
|
||||
public VisibleStringDataBind(BdaVisibleString data) {
|
||||
super(data, BdaType.VISIBLE_STRING, new AsciiFilter(data.getMaxLength()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetImpl() {
|
||||
inputField.setText(new String(data.getValue(), ASCII));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeImpl() {
|
||||
data.setValue(ASCII.encode(inputField.getText()).array());
|
||||
}
|
||||
|
||||
private static class AsciiFilter extends TextFieldDataBind.AbstractFilter {
|
||||
private final CharsetEncoder encoder = StandardCharsets.US_ASCII.newEncoder();
|
||||
private final int maxBytes;
|
||||
|
||||
public AsciiFilter(int maxBytes) {
|
||||
this.maxBytes = maxBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean test(String text) {
|
||||
try {
|
||||
byte[] codedString = encoder.encode(CharBuffer.wrap(text)).array();
|
||||
return codedString.length <= maxBytes;
|
||||
} catch (CharacterCodingException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2011 The IEC61850bean Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.clientgui.util;
|
||||
|
||||
public class Counter {
|
||||
private int value;
|
||||
|
||||
public Counter(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Counter() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public void increment() {
|
||||
value++;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2012 The jASN1 Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal;
|
||||
|
||||
import com.beanit.asn1bean.ber.BerLength;
|
||||
import com.beanit.asn1bean.ber.BerTag;
|
||||
import com.beanit.asn1bean.ber.ReverseByteArrayOutputStream;
|
||||
import com.beanit.asn1bean.ber.types.BerType;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class BerBoolean implements Serializable, BerType {
|
||||
|
||||
public static final BerTag tag =
|
||||
new BerTag(BerTag.UNIVERSAL_CLASS, BerTag.PRIMITIVE, BerTag.BOOLEAN_TAG);
|
||||
private static final long serialVersionUID = 1L;
|
||||
public boolean value;
|
||||
private byte[] code = null;
|
||||
|
||||
public BerBoolean() {}
|
||||
|
||||
public BerBoolean(byte[] code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public BerBoolean(boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int encode(OutputStream reverseOS) throws IOException {
|
||||
return encode(reverseOS, true);
|
||||
}
|
||||
|
||||
public int encode(OutputStream reverseOS, boolean withTag) throws IOException {
|
||||
|
||||
if (code != null) {
|
||||
reverseOS.write(code);
|
||||
if (withTag) {
|
||||
return tag.encode(reverseOS) + code.length;
|
||||
}
|
||||
return code.length;
|
||||
}
|
||||
|
||||
int codeLength = 1;
|
||||
|
||||
if (value) {
|
||||
reverseOS.write(0x01);
|
||||
} else {
|
||||
reverseOS.write(0);
|
||||
}
|
||||
|
||||
codeLength += BerLength.encodeLength(reverseOS, codeLength);
|
||||
|
||||
if (withTag) {
|
||||
codeLength += tag.encode(reverseOS);
|
||||
}
|
||||
|
||||
return codeLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int decode(InputStream is) throws IOException {
|
||||
return decode(is, true);
|
||||
}
|
||||
|
||||
public int decode(InputStream is, boolean withTag) throws IOException {
|
||||
|
||||
int codeLength = 0;
|
||||
|
||||
if (withTag) {
|
||||
codeLength += tag.decodeAndCheck(is);
|
||||
}
|
||||
|
||||
BerLength length = new BerLength();
|
||||
codeLength += length.decode(is);
|
||||
|
||||
if (length.val != 1) {
|
||||
throw new IOException("Decoded length of BerBoolean is not correct");
|
||||
}
|
||||
|
||||
int nextByte = is.read();
|
||||
if (nextByte == -1) {
|
||||
throw new EOFException("Unexpected end of input stream.");
|
||||
}
|
||||
|
||||
codeLength++;
|
||||
value = nextByte != 0;
|
||||
|
||||
return codeLength;
|
||||
}
|
||||
|
||||
public void encodeAndSave(int encodingSizeGuess) throws IOException {
|
||||
ReverseByteArrayOutputStream os = new ReverseByteArrayOutputStream(encodingSizeGuess);
|
||||
encode(os, false);
|
||||
code = os.getArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright 2019 beanit
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
|
||||
public class HexString {
|
||||
|
||||
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||
|
||||
/** Don't let anyone instantiate this class. */
|
||||
private HexString() {}
|
||||
|
||||
/**
|
||||
* Returns the byte as a hex string. If b is less than 16 the hex string returned contains a
|
||||
* leading zero.
|
||||
*
|
||||
* @param b the byte to be converted
|
||||
* @return the hex string.
|
||||
*/
|
||||
public static String fromByte(byte b) {
|
||||
return fromBytes(new byte[] {b});
|
||||
}
|
||||
|
||||
public static String fromByte(int b) {
|
||||
return fromBytes(new byte[] {(byte) b});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the integer value as hex string filled with leading zeros.
|
||||
*
|
||||
* @param i the integer value to be converted
|
||||
* @return the hex string
|
||||
*/
|
||||
public static String fromInt(int i) {
|
||||
byte[] bytes = new byte[] {(byte) (i >> 24), (byte) (i >> 16), (byte) (i >> 8), (byte) i};
|
||||
return fromBytes(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long value as hex string filled with leading zeros.
|
||||
*
|
||||
* @param l the long value to be converted
|
||||
* @return the hex string
|
||||
*/
|
||||
public static String fromLong(long l) {
|
||||
byte[] bytes =
|
||||
new byte[] {
|
||||
(byte) (l >> 56),
|
||||
(byte) (l >> 48),
|
||||
(byte) (l >> 40),
|
||||
(byte) (l >> 32),
|
||||
(byte) (l >> 24),
|
||||
(byte) (l >> 16),
|
||||
(byte) (l >> 8),
|
||||
(byte) l
|
||||
};
|
||||
return fromBytes(bytes);
|
||||
}
|
||||
|
||||
public static String fromBytes(byte[] bytes) {
|
||||
return fromBytes(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
public static String fromBytesFormatted(byte[] bytes) {
|
||||
return fromBytesFormatted(bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
public static String fromBytes(byte[] bytes, int offset, int length) {
|
||||
char[] hexChars = new char[length * 2];
|
||||
for (int j = 0; j < length; j++) {
|
||||
int v = bytes[j + offset] & 0xff;
|
||||
hexChars[j * 2] = hexArray[v >>> 4];
|
||||
hexChars[j * 2 + 1] = hexArray[v & 0x0f];
|
||||
}
|
||||
return new String(hexChars);
|
||||
}
|
||||
|
||||
public static String fromBytes(ByteBuffer buffer) {
|
||||
return fromBytes(buffer.array(), buffer.arrayOffset(), buffer.arrayOffset() + buffer.limit());
|
||||
}
|
||||
|
||||
public static String fromBytesFormatted(byte[] bytes, int offset, int length) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
int l = 1;
|
||||
for (int i = offset; i < (offset + length); i++) {
|
||||
if ((l != 1) && ((l - 1) % 8 == 0)) {
|
||||
builder.append(' ');
|
||||
}
|
||||
if ((l != 1) && ((l - 1) % 16 == 0)) {
|
||||
builder.append('\n');
|
||||
}
|
||||
l++;
|
||||
appendFromByte(bytes[i], builder);
|
||||
if (i != offset + length - 1) {
|
||||
builder.append(' ');
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given hex string to a byte array.
|
||||
*
|
||||
* @param hexString the hex string
|
||||
* @return the bytes
|
||||
* @throws NumberFormatException if the string is not a valid hex string
|
||||
*/
|
||||
public static byte[] toBytes(String hexString) {
|
||||
|
||||
Objects.requireNonNull(hexString);
|
||||
if ((hexString.length() == 0) || ((hexString.length() % 2) != 0)) {
|
||||
throw new NumberFormatException("argument is not a valid hex string");
|
||||
}
|
||||
|
||||
int length = hexString.length();
|
||||
|
||||
byte[] data = new byte[length / 2];
|
||||
for (int i = 0; i < length; i += 2) {
|
||||
int firstCharacter = Character.digit(hexString.charAt(i), 16);
|
||||
int secondCharacter = Character.digit(hexString.charAt(i + 1), 16);
|
||||
|
||||
if (firstCharacter == -1 || secondCharacter == -1) {
|
||||
throw new NumberFormatException("argument is not a valid hex string");
|
||||
}
|
||||
|
||||
data[i / 2] = (byte) ((firstCharacter << 4) + secondCharacter);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static void appendFromByte(byte b, StringBuilder builder) {
|
||||
builder.append(fromByte(b));
|
||||
}
|
||||
|
||||
public static void appendFromBytes(StringBuilder builder, byte[] bytes, int offset, int length) {
|
||||
builder.append(fromBytes(bytes, offset, length));
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2018 beanit
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal;
|
||||
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class NamedThreadFactory implements ThreadFactory {
|
||||
|
||||
private final AtomicInteger threadCounter = new AtomicInteger(1);
|
||||
private final String namePrefix;
|
||||
|
||||
/**
|
||||
* Creates a thread factory with the given pool name as a name prefix. Threads created will have
|
||||
* the name {@code <poolName>-thread-<thread-counter>}. A common pool name is of format {@code
|
||||
* <pool-name>-<pool-id>}.
|
||||
*
|
||||
* @param poolName the thread pool name
|
||||
*/
|
||||
public NamedThreadFactory(String poolName) {
|
||||
this.namePrefix = poolName + "-thread-";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r);
|
||||
thread.setName(namePrefix + threadCounter.getAndIncrement());
|
||||
return thread;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2018 beanit
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal.cli;
|
||||
|
||||
public class Action {
|
||||
|
||||
private final String key;
|
||||
private final String description;
|
||||
|
||||
public Action(String key, String description) {
|
||||
this.key = key;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2018 beanit
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal.cli;
|
||||
|
||||
public final class ActionException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 4806947065917148946L;
|
||||
|
||||
public ActionException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ActionException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
public ActionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public ActionException(String s, Throwable cause) {
|
||||
super(s, cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2018 beanit
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal.cli;
|
||||
|
||||
public interface ActionListener {
|
||||
|
||||
void actionCalled(String actionKey) throws ActionException;
|
||||
|
||||
void quit();
|
||||
}
|
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2018 beanit
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal.cli;
|
||||
|
||||
import static java.lang.System.exit;
|
||||
import static java.lang.System.out;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ActionProcessor {
|
||||
|
||||
private static final String SEPARATOR_LINE =
|
||||
"------------------------------------------------------";
|
||||
|
||||
private final BufferedReader reader;
|
||||
private final ActionListener actionListener;
|
||||
private final Map<String, Action> actionMap = new LinkedHashMap<>();
|
||||
private final Action helpAction = new Action("h", "print help message");
|
||||
private final Action quitAction = new Action("q", "quit the application");
|
||||
private volatile boolean closed = false;
|
||||
|
||||
public ActionProcessor(ActionListener actionListener) {
|
||||
reader = new BufferedReader(new InputStreamReader(System.in, UTF_8));
|
||||
this.actionListener = actionListener;
|
||||
}
|
||||
|
||||
public void addAction(Action action) {
|
||||
actionMap.put(action.getKey(), action);
|
||||
}
|
||||
|
||||
public BufferedReader getReader() {
|
||||
return reader;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
|
||||
actionMap.put(helpAction.getKey(), helpAction);
|
||||
actionMap.put(quitAction.getKey(), quitAction);
|
||||
|
||||
printHelp();
|
||||
|
||||
try {
|
||||
|
||||
String actionKey;
|
||||
while (true) {
|
||||
|
||||
if (closed) {
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("\n** Enter action key: ");
|
||||
|
||||
try {
|
||||
actionKey = reader.readLine();
|
||||
} catch (IOException e) {
|
||||
System.err.printf("%s. Application is being shut down.\n", e.getMessage());
|
||||
exit(2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (closed) {
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (actionMap.get(actionKey) == null) {
|
||||
System.err.println("Illegal action key.\n");
|
||||
printHelp();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (actionKey.equals(helpAction.getKey())) {
|
||||
printHelp();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (actionKey.equals(quitAction.getKey())) {
|
||||
actionListener.quit();
|
||||
return;
|
||||
}
|
||||
|
||||
actionListener.actionCalled(actionKey);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
actionListener.quit();
|
||||
} finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
private void printHelp() {
|
||||
final String message = " %s - %s\n";
|
||||
out.flush();
|
||||
out.println();
|
||||
out.println(SEPARATOR_LINE);
|
||||
|
||||
for (Action action : actionMap.values()) {
|
||||
out.printf(message, action.getKey(), action.getDescription());
|
||||
}
|
||||
|
||||
out.println(SEPARATOR_LINE);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
closed = true;
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException ignored) {
|
||||
// if closing fails there is nothing meaningful that can be done
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2018 beanit
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal.cli;
|
||||
|
||||
public abstract class CliParameter {
|
||||
|
||||
final String name;
|
||||
final String description;
|
||||
final boolean optional;
|
||||
boolean selected;
|
||||
|
||||
CliParameter(CliParameterBuilder builder) {
|
||||
name = builder.name;
|
||||
description = builder.description;
|
||||
optional = builder.optional;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public boolean isOptional() {
|
||||
return optional;
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
abstract int parse(String[] args, int i) throws CliParseException;
|
||||
|
||||
abstract int appendSynopsis(StringBuilder sb);
|
||||
|
||||
abstract void appendDescription(StringBuilder sb);
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2018 beanit
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License
|
||||
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
* or implied. See the License for the specific language governing permissions and limitations under
|
||||
* the License.
|
||||
*/
|
||||
package com.beanit.iec61850bean.internal.cli;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CliParameterBuilder {
|
||||
|
||||
final String name;
|
||||
String description;
|
||||
boolean optional = true;
|
||||
|
||||
public CliParameterBuilder(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public CliParameterBuilder setDescription(String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CliParameterBuilder setMandatory() {
|
||||
optional = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LongCliParameter buildLongParameter(String parameterName, long defaultValue) {
|
||||
return new LongCliParameter(this, parameterName, defaultValue);
|
||||
}
|
||||
|
||||
public LongCliParameter buildLongParameter(String parameterName) {
|
||||
return new LongCliParameter(this, parameterName);
|
||||
}
|
||||
|
||||
public IntCliParameter buildIntParameter(String parameterName, int defaultValue) {
|
||||
return new IntCliParameter(this, parameterName, defaultValue);
|
||||
}
|
||||
|
||||
public IntCliParameter buildIntParameter(String parameterName) {
|
||||
return new IntCliParameter(this, parameterName);
|
||||
}
|
||||
|
||||
public StringCliParameter buildStringParameter(String parameterName, String defaultValue) {
|
||||
return new StringCliParameter(this, parameterName, defaultValue);
|
||||
}
|
||||
|
||||
public StringCliParameter buildStringParameter(String parameterName) {
|
||||
return new StringCliParameter(this, parameterName);
|
||||
}
|
||||
|
||||
public StringListCliParameter buildStringListParameter(String parameterName) {
|
||||
return new StringListCliParameter(this, parameterName);
|
||||
}
|
||||
|
||||
public StringListCliParameter buildStringListParameter(
|
||||
String parameterName, List<String> defaultValue) {
|
||||
return new StringListCliParameter(this, parameterName, defaultValue);
|
||||
}
|
||||
|
||||
public FlagCliParameter buildFlagParameter() {
|
||||
return new FlagCliParameter(this);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue