package org.openmuc.openiec61850.app; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.openmuc.openiec61850.BasicDataAttribute; import org.openmuc.openiec61850.BdaFloat32; import org.openmuc.openiec61850.BdaFloat64; import org.openmuc.openiec61850.BdaInt16; import org.openmuc.openiec61850.BdaInt16U; import org.openmuc.openiec61850.BdaInt32; import org.openmuc.openiec61850.BdaInt32U; import org.openmuc.openiec61850.BdaInt64; import org.openmuc.openiec61850.BdaInt8; import org.openmuc.openiec61850.BdaInt8U; import org.openmuc.openiec61850.Fc; import org.openmuc.openiec61850.ModelNode; import org.openmuc.openiec61850.SclParseException; import org.openmuc.openiec61850.ServerEventListener; import org.openmuc.openiec61850.ServerModel; import org.openmuc.openiec61850.ServerSap; import org.openmuc.openiec61850.ServiceError; 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.IntCliParameter; import org.openmuc.openiec61850.internal.cli.StringCliParameter; /** * * @author Stefan Feuerhahn * */ 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 ServerModel serverModel; private static final ActionProcessor actionProcessor = new ActionProcessor(new ActionExecutor()); private static ServerSap serverSap = null; private static class EventListener implements ServerEventListener { @Override public void serverStoppedListening(ServerSap serverSap) { System.out.println("The SAP stopped listening"); } @Override public List write(List bdas) { for (BasicDataAttribute bda : bdas) { System.out.println("got a write request: " + bda); /* System.out.println("got a write request: " + bda.getReference().toString() + " value is: " + ((BdaFloat32) bda).getFloat()); BasicDataAttribute bdat = (BasicDataAttribute) serverModel.findModelNode(bda.getReference(), Fc.fromString("SP")); System.out.println("got a write rest: " + bdat.getReference().toString() + " value is: " + ((BdaFloat32) bdat).getFloat()); */ } 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("** Reading model from file."); System.out.println("Enter reference to read (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 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 { throw new IllegalArgumentException(); } } @Override public void quit() { System.out.println("** Stopping server."); serverSap.stop(); return; } } public static void main(String[] args) throws IOException { List cliParameters = new ArrayList<>(); cliParameters.add(modelFileParam); cliParameters.add(portParam); CliParser cliParser = new CliParser("openiec61850-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 serverSaps = null; try { serverSaps = ServerSap.getSapsFromSclFile(modelFileParam.getValue()); } catch (SclParseException e) { System.out.println("Error parsing SCL/ICD file: " + e.getMessage()); return; } serverSap = serverSaps.get(0); 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(); BasicDataAttribute bda = (BasicDataAttribute) serverModel.findModelNode("ZJDYBTSE/ncdGGIO1.Para2.setMag.f", Fc.fromString("SP")); ((BdaFloat32) bda).setFloat((float) 13.5); List bdas = new ArrayList<>(); bdas.add(bda); serverSap.setValues(bdas); 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(); } }