package org.openmuc.openiec61850.app;
|
|
import java.io.IOException;
|
import java.net.InetAddress;
|
import java.net.UnknownHostException;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
import javax.swing.JCheckBox;
|
import javax.swing.JTextField;
|
|
import org.openmuc.openiec61850.BdaFloat32;
|
import org.openmuc.openiec61850.BdaBoolean;
|
import org.openmuc.openiec61850.BdaTriggerConditions;
|
import org.openmuc.openiec61850.Brcb;
|
import org.openmuc.openiec61850.ClientAssociation;
|
import org.openmuc.openiec61850.ClientEventListener;
|
import org.openmuc.openiec61850.ClientSap;
|
import org.openmuc.openiec61850.DataSet;
|
import org.openmuc.openiec61850.Fc;
|
import org.openmuc.openiec61850.FcModelNode;
|
import org.openmuc.openiec61850.ModelNode;
|
import org.openmuc.openiec61850.Report;
|
import org.openmuc.openiec61850.SclParseException;
|
import org.openmuc.openiec61850.ServerModel;
|
import org.openmuc.openiec61850.ServerSap;
|
import org.openmuc.openiec61850.ServiceError;
|
import org.openmuc.openiec61850.Urcb;
|
import org.openmuc.openiec61850.clientgui.BasicDataBind;
|
import org.openmuc.openiec61850.internal.cli.Action;
|
import org.openmuc.openiec61850.internal.cli.ActionException;
|
import org.openmuc.openiec61850.internal.cli.ActionListener;
|
import org.openmuc.openiec61850.internal.cli.ActionProcessor;
|
import org.openmuc.openiec61850.internal.cli.CliParameter;
|
import org.openmuc.openiec61850.internal.cli.CliParameterBuilder;
|
import org.openmuc.openiec61850.internal.cli.CliParseException;
|
import org.openmuc.openiec61850.internal.cli.CliParser;
|
import org.openmuc.openiec61850.internal.cli.FatalActionException;
|
import org.openmuc.openiec61850.internal.cli.IntCliParameter;
|
import org.openmuc.openiec61850.internal.cli.StringCliParameter;
|
import org.openmuc.openiec61850.clientgui.databind.BooleanDataBind;
|
import org.openmuc.openiec61850.clientgui.databind.Float32DataBind;
|
|
/**
|
*
|
* @author Stefan Feuerhahn
|
*
|
*/
|
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 volatile ClientAssociation association;
|
private static ServerModel serverModel;
|
private static final ActionProcessor actionProcessor = new ActionProcessor(new ActionExecutor());
|
|
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, FatalActionException {
|
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 SetDataValues request...");
|
|
try {
|
BasicDataBind<?> data = new Float32DataBind((BdaFloat32)fcModelNode);
|
JTextField tf_t = (JTextField)data.getValueField();
|
tf_t.setText("12.0");
|
data.write();
|
association.setDataValues(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 write data.");
|
|
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.");
|
BasicDataBind<?> data = new Float32DataBind((BdaFloat32)fcModelNode);
|
JTextField tf_t = (JTextField)data.getValueField();
|
System.out.println("The read data is:" + tf_t.getText());
|
//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(",");
|
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;
|
}
|
}
|
|
public static void writeNodeData(String reference, String fc_str) {
|
FcModelNode fcModelNode = (FcModelNode)serverModel.findModelNode(reference, Fc.fromString(fc_str));
|
if(null == fcModelNode) {
|
System.err.println("error, no modenode was found.....");
|
return;
|
}
|
|
System.out.println("Sending SetDataValues request...");
|
try {
|
/*
|
BasicDataBind<?> data = new Float32DataBind((BdaFloat32)fcModelNode);
|
JTextField tf_t = (JTextField)data.getValueField();
|
tf_t.setText("12.0");
|
*/
|
BasicDataBind<?> data = new BooleanDataBind((BdaBoolean)fcModelNode.getChild("ctlVal"));
|
JCheckBox ckb_t = (JCheckBox)data.getValueField();
|
ckb_t.setSelected(false);
|
data.write();
|
association.setDataValues(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 write data.");
|
}
|
|
public static void readNodeData(String reference, String fc_str) {
|
FcModelNode fcModelNode = (FcModelNode)serverModel.findModelNode(reference, Fc.fromString(fc_str));
|
if(null == fcModelNode) {
|
System.err.println("error, no modenode was found.....");
|
return;
|
}
|
|
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.");
|
/*
|
BasicDataBind<?> data = new Float32DataBind((BdaFloat32)fcModelNode);
|
JTextField tf_t = (JTextField)data.getValueField();
|
System.out.println("The modelnode is:" + fcModelNode.getReference() + ", the value is: " + tf_t.getText());
|
*/
|
BasicDataBind<?> data = new BooleanDataBind((BdaBoolean)fcModelNode.getChild("ctlVal"));
|
JCheckBox ckb_t = (JCheckBox)data.getValueField();
|
System.out.println("The modelnode is:" + fcModelNode.getChild("ctlVal").getReference() + ", the value is: " + ckb_t.isSelected());
|
}
|
|
public static void main(String[] args) {
|
|
List<CliParameter> cliParameters = new ArrayList<>();
|
cliParameters.add(hostParam);
|
cliParameters.add(portParam);
|
cliParameters.add(modelFileParam);
|
|
CliParser cliParser = new CliParser("openiec61850-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 {
|
List<ServerSap> serverSaps = ServerSap.getSapsFromSclFile("zjdy_bts_1_2G.icd");
|
if (serverSaps == null || serverSaps.size() == 0) {
|
throw new SclParseException("No AccessPoint found in SCL file.");
|
}
|
//serverModel = serverSaps.get(0).serverModel;
|
//serverModel = association.getModelFromSclFile("zjdy_bts_1_2G.icd");
|
//serverModel = association.getModelFromSclFile(modelFileParam.getValue());
|
} catch (SclParseException e1) {
|
System.out.println("Error parsing SCL file: " + e1.getMessage());
|
return;
|
}
|
|
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();
|
|
/*
|
writeNodeData("ZJDYBTSE/ncdGGIO1.Para6.setMag.f", "SP");
|
readNodeData("ZJDYBTSE/ncdGGIO1.Para6.setMag.f", "SP");
|
|
writeNodeData("ZJDYBTSE/ncdGGIO1.SPCSO1.Oper", "CO");
|
readNodeData("ZJDYBTSE/ncdGGIO1.SPCSO1.Oper", "CO");*/
|
}
|
}
|