org.javafmi.proxy.v1.FmuProxy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fmu-wrapper Show documentation
Show all versions of fmu-wrapper Show documentation
javaFMI is a Java Library for the functional mock-up interface (or FMI). FMI defines a standardized interface to be used in computer simulations. The FMI Standard has beed developed by a large number of software companies and research centers that have worked in a cooperation project under the name of MODELISAR. This library addresses the connection of a java application with a FMU (functional mock-up unit).
/*
* Copyright 2013-2016 SIANI - ULPGC
*
* This File is part of JavaFMI Project
*
* JavaFMI Project is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* JavaFMI Project is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JavaFMI. If not, see .
*/
package org.javafmi.proxy.v1;
import com.sun.jna.Function;
import com.sun.jna.Library;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
import org.javafmi.kernel.OS;
import org.javafmi.modeldescription.FmiVersion;
import org.javafmi.modeldescription.ScalarVariable;
import org.javafmi.modeldescription.v1.EnumerationType;
import org.javafmi.modeldescription.v1.ModelDescription;
import org.javafmi.proxy.*;
import java.io.File;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.IntBuffer;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.javafmi.proxy.Status.*;
public class FmuProxy implements FmiProxy {
private static final String MIME_TYPE = "application/x-fmu-sharedlibrary";
private static final long DEFAULT_TIMEOUT = 2000;
private static final boolean DEFAULT_DOING_LOGGING = false;
private static final boolean DEFAULT_VISIBLE = false;
private static final boolean DEFAULT_INTERACTIVE = false;
private static final boolean STOP_DEFINED = true;
private static final String SET_DEBUG = "_fmiSetDebugLogging";
private static final String GET_REAL = "_fmiGetReal";
private static final String GET_INTEGER = "_fmiGetInteger";
private static final String GET_BOOLEAN = "_fmiGetBoolean";
private static final String GET_STRING = "_fmiGetString";
private static final String SET_REAL = "_fmiSetReal";
private static final String SET_INTEGER = "_fmiSetInteger";
private static final String SET_BOOLEAN = "_fmiSetBoolean";
private static final String SET_STRING = "_fmiSetString";
private static final String INSTANTIATE = "_fmiInstantiateSlave";
private static final String INITIALIZE = "_fmiInitializeSlave";
private static final String TERMINATE = "_fmiTerminateSlave";
private static final String FREE = "_fmiFreeSlaveInstance";
private static final String RESET = "_fmiResetSlave";
private static final String DO_STEP = "_fmiDoStep";
private static final String CANCEL_STEP = "_fmiCancelStep";
private final String libraryPath;
private ModelDescription modelDescription;
private NativeLibrary libraryInstance;
private double startTime;
private double stopTime;
private Pointer component;
private Map functions;
private FmuProxyState fmuProxyState;
private CallbackFunctions.ByValue callbacks;
private Buffers buffers;
public FmuProxy(String libraryPath, ModelDescription modelDescription) {
this.libraryPath = libraryPath;
this.modelDescription = modelDescription.build();
this.callbacks = new CallbackFunctions.ByValue();
this.libraryInstance = getInstance(libraryPath);
this.functions = getFunctions();
this.buffers = new Buffers();
}
private NativeLibrary getInstance(String libraryPath) {
int RTLD_NOW = 0x00002, RTLD_DEEPBIND = 0x00008;
Map options = new HashMap<>();
if(OS.isLinux32() || OS.isLinux64()) options.put(Library.OPTION_OPEN_FLAGS, RTLD_NOW | RTLD_DEEPBIND);
return NativeLibrary.getInstance(libraryPath, options);
}
static String[] functionsSuffix() {
return new String[]{SET_DEBUG, GET_REAL, GET_INTEGER, GET_BOOLEAN, GET_STRING, SET_REAL, SET_INTEGER, SET_BOOLEAN, SET_STRING, INSTANTIATE, INITIALIZE, TERMINATE, FREE, RESET, DO_STEP, CANCEL_STEP};
}
@Override
public void instantiate(String resourcesPath) {
component = (Pointer) functions.get(INSTANTIATE).invoke(Pointer.class, getParametersForInstantiate(libraryPath));
if (component == Pointer.NULL)
throw new MethodExecutionException("Instantiate: " + modelDescription.getModelIdentifier());
fmuProxyState = FmuProxyState.INSTANTIATED;
}
public Map getFunctions() {
LinkedHashMap functions = new LinkedHashMap<>();
for (String suffix : functionsSuffix())
functions.put(suffix, getFunction(suffix));
return functions;
}
@Override
public Status initialize(double startTime, double stopTime) {
if (fmuProxyState.equals(FmuProxyState.INITED)) return WARNING;
this.startTime = startTime;
this.stopTime = Double.isNaN(stopTime) ? Double.MAX_VALUE : stopTime;
if (translateStatus(functions.get(INITIALIZE).invokeInt(getParametersForInitialize())) != Status.OK)
throw new RuntimeException("impossible to initialize");
fmuProxyState = FmuProxyState.INITED;
return OK;
}
@Override
public Status terminate() {
Status terminateStatus = translateStatus((Integer) functions.get(TERMINATE).invoke(Integer.class, new Object[]{component}));
if (terminateStatus.equals(OK)) fmuProxyState = FmuProxyState.TERMINATED;
else fmuProxyState = FmuProxyState.INITED;
return terminateStatus;
}
@Override
public Status reset() {
Status resetStatus = translateStatus((Integer) functions.get(RESET).invoke(Integer.class, new Object[]{component}));
if (resetStatus.equals(Status.OK)) {
fmuProxyState = FmuProxyState.INSTANTIATED;
}
return resetStatus;
}
@Override
public void freeInstance() {
functions.get(FREE).invoke(new Object[]{component});
libraryInstance.dispose();
}
@Override
public Status doStep(double communicationPoint, double stepSize) {
return translateStatus(functions.get(DO_STEP).invokeInt(getParametersForDoStep(stepSize, communicationPoint)));
}
@Override
public Status cancelStep() {
return translateStatus((Integer) functions.get(CANCEL_STEP).invoke(Integer.class, new Object[]{component}));
}
@Override
public Object getEnumeration(ScalarVariable modelVariable) {
EnumerationType enumeration = (EnumerationType) modelVariable.getType();
Integer enumerationIndex;
EnumerationType enumerationType = (EnumerationType) modelDescription.getTypeFromTypeDefinition(enumeration.getDeclaredType());
if (modelVariable.getVariability().equalsIgnoreCase("constant")) {
enumerationIndex = enumeration.getStart();
return enumerationType.getItems().get(enumerationIndex - 1).getName();
}
enumerationIndex = getInteger(modelVariable.getValueReference())[0];
return enumerationType.getItems().get(enumerationIndex - 1).getName();
}
@Override
public double[] getReal(int... valueReferences) {
DoubleBuffer buffer = buffers.forDouble(valueReferences.length);
functions.get(GET_REAL).invokeInt(new Object[]{component, valueReferences, valueReferences.length, buffer});
return buffer.array();
}
@Override
public int[] getInteger(int... valueReference) {
IntBuffer buffer = buffers.forInteger(valueReference.length);
functions.get(GET_INTEGER).invoke(getParametersForFmuGetterSetter(valueReference, buffer));
return buffer.array();
}
@Override
public boolean[] getBoolean(int... valueReference) {
ByteBuffer buffer = buffers.forBytes(valueReference.length);
functions.get(GET_BOOLEAN).invoke(getParametersForFmuGetterSetter(valueReference, buffer));
byte[] resultAsArray = buffer.array();
boolean[] resultAsBoolean = new boolean[resultAsArray.length];
for (int i = 0; i < resultAsArray.length; i++) {
resultAsBoolean[i] = NativeBoolean.getBooleanFor(resultAsArray[i]);
}
return resultAsBoolean;
}
@Override
public String[] getString(int... valueReference) {
String[] buffer = new String[valueReference.length];
functions.get(GET_STRING).invoke(getParametersForFmuGetterSetter(valueReference, buffer));
return buffer;
}
@Override
public Status setReal(int[] valueReferences, double[] values) {
return translateStatus(functions.get(SET_REAL).invokeInt(new Object[]{component, valueReferences, valueReferences.length, values}));
}
@Override
public Status setInteger(int[] valueReferences, int[] values) {
return translateStatus(functions.get(SET_INTEGER).invokeInt(getParametersForFmuGetterSetter(valueReferences, values)));
}
@Override
public Status setBoolean(int[] valueReference, boolean[] values) {
return translateStatus(functions.get(SET_BOOLEAN).invokeInt(getParametersForFmuGetterSetter(valueReference, values)));
}
@Override
public Status setString(int[] valueReference, String[] newValue) {
return translateStatus(functions.get(SET_STRING).invokeInt(getParametersForFmuGetterSetter(valueReference, newValue)));
}
@SuppressWarnings("UnusedParameters")
public Status setIsDoingLogging(boolean isDoingLogging) {
return translateStatus(functions.get(SET_DEBUG).invokeInt(getParametersForSetDebugLogging()));
}
@Override
public boolean isTerminated() {
return fmuProxyState.equals(FmuProxyState.TERMINATED);
}
private Function getFunction(String suffix) {
return libraryInstance.getFunction(modelDescription.getModelIdentifier() + suffix);
}
private Object[] getParametersForInstantiate(String libraryPath) {
return new Object[]{modelDescription.getModelIdentifier(), modelDescription.getGuid(), rootFolderOf(libraryPath), MIME_TYPE, DEFAULT_TIMEOUT, NativeBoolean.getValueFor(DEFAULT_VISIBLE), NativeBoolean.getValueFor(DEFAULT_INTERACTIVE), callbacks, NativeBoolean.getValueFor(DEFAULT_DOING_LOGGING)};
}
private Object[] getParametersForInitialize() {
return new Object[]{component, startTime, NativeBoolean.getValueFor(STOP_DEFINED), stopTime};
}
private Object[] getParametersForDoStep(double stepSize, double communicationPoint) {
return new Object[]{component, communicationPoint, stepSize, (byte) 1};
}
private Object[] getParametersForSetDebugLogging() {
return new Object[]{component, NativeBoolean.getValueFor(DEFAULT_DOING_LOGGING)};
}
public Object[] getParametersForFmuGetterSetter(int[] valueReference, Object buffer) {
return new Object[]{component, valueReference, valueReference.length, buffer};
}
private String rootFolderOf(String libraryPath) {
return new File(libraryPath).getParentFile().getParentFile().getParentFile().getAbsolutePath();
}
@Override
public String getVersion() {
return FmiVersion.One;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy