diff --git a/fmi2/src/main/java/org/intocps/fmi/IFmiComponent.java b/fmi2/src/main/java/org/intocps/fmi/IFmiComponent.java index b6c180e..402a881 100644 --- a/fmi2/src/main/java/org/intocps/fmi/IFmiComponent.java +++ b/fmi2/src/main/java/org/intocps/fmi/IFmiComponent.java @@ -140,7 +140,7 @@ public abstract Fmi2Status setStrings(long[] scalarValueIndices, FmuResult getSerializedFMUstateSize(IFmiComponentState state) throws FmuInvocationException; FmuResult serializeFMUstate(IFmiComponentState state, long size) throws FmuInvocationException; - FmuResult serializeFMUstate(IFmiComponentState state, byte[] bytes, long size) throws FmuInvocationException; + FmuResult deSerializeFMUstate( byte[] bytes, long size) throws FmuInvocationException; public abstract boolean isValid(); diff --git a/jnifmuapi/src/main/java/org/intocps/fmi/jnifmuapi/FmuComponent.java b/jnifmuapi/src/main/java/org/intocps/fmi/jnifmuapi/FmuComponent.java index 06030f2..5ebd9c2 100644 --- a/jnifmuapi/src/main/java/org/intocps/fmi/jnifmuapi/FmuComponent.java +++ b/jnifmuapi/src/main/java/org/intocps/fmi/jnifmuapi/FmuComponent.java @@ -584,7 +584,7 @@ public FmuResult serializeFMUstate(IFmiComponentState state, long byteSi throw new FmuInvocationException("Invalid state"); } - public FmuResult serializeFMUstate(IFmiComponentState state, byte[] bytes, long size) throws FmuInvocationException{ + public FmuResult deSerializeFMUstate( byte[] bytes, long size) throws FmuInvocationException{ long statePtr[] = new long[1]; Fmi2Status res = Fmi2Status.valueOf(nDeSerializeFMUstate(fmuPtr, componentPtr, bytes,size,statePtr)); diff --git a/jnifmuapi/src/main/native/src/comp_api.c b/jnifmuapi/src/main/native/src/comp_api.c index a971953..6f2b39b 100644 --- a/jnifmuapi/src/main/native/src/comp_api.c +++ b/jnifmuapi/src/main/native/src/comp_api.c @@ -643,9 +643,10 @@ JNIEXPORT jbyte JNICALL Java_org_intocps_fmi_jnifmuapi_NativeFmuComponent_nDeSer fmi2FMUstate state; state = NULL; fmi2Status status = getFmuPtr(fmuPtr)->deSerializeFMUstate(c, bytes, len,&state); - if(state==fmi2OK) + if(status==fmi2OK) { jlong *vbody = (*env)->GetLongArrayElements(env, statePtrArr, 0); + vbody[0] = (jlong) (state); (*env)->ReleaseLongArrayElements(env, statePtrArr, vbody, 0); diff --git a/jnifmuapi/src/test/java/org/intocps/fmi/jnifmuapi/FmuComponentTest.java b/jnifmuapi/src/test/java/org/intocps/fmi/jnifmuapi/FmuComponentTest.java index c05224a..e81da69 100644 --- a/jnifmuapi/src/test/java/org/intocps/fmi/jnifmuapi/FmuComponentTest.java +++ b/jnifmuapi/src/test/java/org/intocps/fmi/jnifmuapi/FmuComponentTest.java @@ -1,36 +1,36 @@ /* -* This file is part of the INTO-CPS toolchain. -* -* Copyright (c) 2017-CurrentYear, INTO-CPS Association, -* c/o Professor Peter Gorm Larsen, Department of Engineering -* Finlandsgade 22, 8200 Aarhus N. -* -* All rights reserved. -* -* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR -* THIS INTO-CPS ASSOCIATION PUBLIC LICENSE VERSION 1.0. -* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES -* RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL -* VERSION 3, ACCORDING TO RECIPIENTS CHOICE. -* -* The INTO-CPS toolchain and the INTO-CPS Association Public License -* are obtained from the INTO-CPS Association, either from the above address, -* from the URLs: http://www.into-cps.org, and in the INTO-CPS toolchain distribution. -* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. -* -* This program is distributed WITHOUT ANY WARRANTY; without -* even the implied warranty of MERCHANTABILITY or FITNESS FOR -* A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH IN THE -* BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF -* THE INTO-CPS ASSOCIATION. -* -* See the full INTO-CPS Association Public License conditions for more details. -*/ + * This file is part of the INTO-CPS toolchain. + * + * Copyright (c) 2017-CurrentYear, INTO-CPS Association, + * c/o Professor Peter Gorm Larsen, Department of Engineering + * Finlandsgade 22, 8200 Aarhus N. + * + * All rights reserved. + * + * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR + * THIS INTO-CPS ASSOCIATION PUBLIC LICENSE VERSION 1.0. + * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES + * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL + * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. + * + * The INTO-CPS toolchain and the INTO-CPS Association Public License + * are obtained from the INTO-CPS Association, either from the above address, + * from the URLs: http://www.into-cps.org, and in the INTO-CPS toolchain distribution. + * GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html. + * + * This program is distributed WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH IN THE + * BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF + * THE INTO-CPS ASSOCIATION. + * + * See the full INTO-CPS Association Public License conditions for more details. + */ /* -* Author: -* Kenneth Lausdahl -*/ + * Author: + * Kenneth Lausdahl + */ package org.intocps.fmi.jnifmuapi; @@ -43,184 +43,221 @@ import org.junit.Test; // Before running these tests extract the latest fmi.native lib and place the lib folder in resources. See https://github.com/INTO-CPS-Association/org.intocps.maestro.fmi -public class FmuComponentTest extends BaseFmuComponent -{ - @Test - public void setDebugLogging() throws FmuInvocationException - { - comp.setDebugLogging(true, new String[] { "loglevel1", "loglevel2" }); - } - - @Test - public void setReset() throws FmuInvocationException - { - comp.reset(); - } - - @Test - public void initModesTest() throws FmuInvocationException - { - comp.enterInitializationMode(); - comp.exitInitializationMode(); - } - - @Test - public void setupExperimentTest() throws FmuInvocationException - { - boolean toleranceDefined = true; - double tolerance = 0.1; - double startTime = 0; - boolean stopTimeDefined = true; - double stopTime = 10; - comp.setupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); - } - - @Test - public void testDoStep() throws FmuInvocationException - { - initModesTest(); - double currentCommunicationPoint = 0; - double communicationStepSize = 0.1; - boolean noSetFMUStatePriorToCurrentPoint = true; - Assert.assertEquals(Fmi2Status.OK, comp.doStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint)); - } - - @Test - public void testGetOutputDerivatives() throws FmuInvocationException - { - // initModesTest(); - testSetRealInputDerivatives(); - // - double currentCommunicationPoint = 0; - double communicationStepSize = 0.1; - boolean noSetFMUStatePriorToCurrentPoint = true; - ; - Assert.assertEquals(Fmi2Status.OK, comp.doStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint)); - // - long[] scalarValueIndices = new long[] { TestUtils.REAL_ID }; - FmuResult res = comp.getRealOutputDerivatives(scalarValueIndices, new int[]{1}); - // System.out.println(res.result); - Assert.assertEquals(Fmi2Status.OK, res.status); - Assert.assertEquals(1, res.result.length); - Assert.assertTrue(Math.abs(99.12 - res.result[0]) <= 10); - } - - @Test - public void testSetRealInputDerivatives() throws FmuInvocationException - { - initModesTest(); - long[] scalarValueIndices = new long[] { TestUtils.REAL_ID }; - double[] derivatives = new double[] { 99.12 }; - Fmi2Status res = comp.setRealInputDerivatives(scalarValueIndices, new int[]{1}, derivatives); - // System.out.println(res); - Assert.assertEquals(Fmi2Status.OK, res); - } - - @Test - public void testGetDirectionalDerivative() throws FmuInvocationException - { - comp.enterInitializationMode(); - long[] vUnknownRef = new long[] { TestUtils.REAL_ID }; - long[] vKnownRef = new long[] { TestUtils.REAL_ID }; - double[] dvKnown = new double[] { 2 }; - FmuResult res = comp.getDirectionalDerivative(vUnknownRef, vKnownRef, dvKnown); - // System.out.println(res); - Assert.assertEquals(Fmi2Status.OK, res.status); - Assert.assertTrue(Math.abs(2 - res.result[0]) <= 10); - } - - @Test - public void testTerminate() throws FmuInvocationException - { - testDoStep(); - Assert.assertEquals(Fmi2Status.OK, comp.terminate()); - } - - @Test - public void setGetReal() throws InvalidParameterException, - FmuInvocationException - { - double value = 99.99; - long[] scalarValueIndices = new long[] { TestUtils.REAL_ID }; - Assert.assertEquals(Fmi2Status.OK, comp.setReals(scalarValueIndices, new double[] { value })); - - Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); - - FmuResult ret = comp.getReal(scalarValueIndices); - Assert.assertEquals(Fmi2Status.OK, ret.status); - Assert.assertEquals(value, ret.result[0], 0.1 / 10E307); - } - - @Test - public void setGetInteger() throws InvalidParameterException, - FmuInvocationException - { - int value = 99; - long[] scalarValueIndices = new long[] { TestUtils.INTEGER_ID }; - Assert.assertEquals(Fmi2Status.OK, comp.setIntegers(scalarValueIndices, new int[] { value })); - - Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); - - FmuResult ret = comp.getInteger(scalarValueIndices); - Assert.assertEquals(Fmi2Status.OK, ret.status); - Assert.assertEquals(value, ret.result[0]); - } - - @Test - public void setGetBoolean() throws InvalidParameterException, - FmuInvocationException - { - boolean value = true; - long[] scalarValueIndices = new long[] { TestUtils.BOOLEAN_ID }; - Assert.assertEquals(Fmi2Status.OK, comp.setBooleans(scalarValueIndices, new boolean[] { value })); - - Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); - - FmuResult ret = comp.getBooleans(scalarValueIndices); - Assert.assertEquals(Fmi2Status.OK, ret.status); - Assert.assertEquals(value, ret.result[0]); - } - - @Test - public void getState() throws FmuInvocationException, - InvalidParameterException - { - FmuResult res = comp.getState(); - System.out.println(res.result); - Assert.assertEquals(Fmi2Status.OK, res.status); - - // change the state and update reaal 0 = 99.99 - long[] scalarValueIndices = new long[] { 0 }; - - double[] values = new double[] { 99.99 }; - comp.setReals(scalarValueIndices, values); - - // enable get - Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); - FmuResult real = comp.getReal(scalarValueIndices); - - Assert.assertEquals(values[0], real.result[0], 0.001); - // 0 = 99.99 confirmed - - FmuResult res2 = comp.getState(); - System.out.println(res2.result); - Assert.assertEquals(Fmi2Status.OK, res2.status); - - // set state 0 = 0 - comp.setState(res.result); - - real = comp.getReal(scalarValueIndices); - Assert.assertEquals(0, real.result[0], 0.001); - - // set state 0 = 99.99 - comp.setState(res2.result); - - real = comp.getReal(scalarValueIndices); - Assert.assertEquals(values[0], real.result[0], 0.001); - - - res.result.freeState(); - res2.result.freeState(); - - } +public class FmuComponentTest extends BaseFmuComponent { + @Test + public void setDebugLogging() throws FmuInvocationException { + comp.setDebugLogging(true, new String[]{"loglevel1", "loglevel2"}); + } + + @Test + public void setReset() throws FmuInvocationException { + comp.reset(); + } + + @Test + public void initModesTest() throws FmuInvocationException { + comp.enterInitializationMode(); + comp.exitInitializationMode(); + } + + @Test + public void setupExperimentTest() throws FmuInvocationException { + boolean toleranceDefined = true; + double tolerance = 0.1; + double startTime = 0; + boolean stopTimeDefined = true; + double stopTime = 10; + comp.setupExperiment(toleranceDefined, tolerance, startTime, stopTimeDefined, stopTime); + } + + @Test + public void testDoStep() throws FmuInvocationException { + initModesTest(); + double currentCommunicationPoint = 0; + double communicationStepSize = 0.1; + boolean noSetFMUStatePriorToCurrentPoint = true; + Assert.assertEquals(Fmi2Status.OK, comp.doStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint)); + } + + @Test + public void testGetOutputDerivatives() throws FmuInvocationException { + // initModesTest(); + testSetRealInputDerivatives(); + // + double currentCommunicationPoint = 0; + double communicationStepSize = 0.1; + boolean noSetFMUStatePriorToCurrentPoint = true; + ; + Assert.assertEquals(Fmi2Status.OK, comp.doStep(currentCommunicationPoint, communicationStepSize, noSetFMUStatePriorToCurrentPoint)); + // + long[] scalarValueIndices = new long[]{TestUtils.REAL_ID}; + FmuResult res = comp.getRealOutputDerivatives(scalarValueIndices, new int[]{1}); + // System.out.println(res.result); + Assert.assertEquals(Fmi2Status.OK, res.status); + Assert.assertEquals(1, res.result.length); + Assert.assertTrue(Math.abs(99.12 - res.result[0]) <= 10); + } + + @Test + public void testSetRealInputDerivatives() throws FmuInvocationException { + initModesTest(); + long[] scalarValueIndices = new long[]{TestUtils.REAL_ID}; + double[] derivatives = new double[]{99.12}; + Fmi2Status res = comp.setRealInputDerivatives(scalarValueIndices, new int[]{1}, derivatives); + // System.out.println(res); + Assert.assertEquals(Fmi2Status.OK, res); + } + + @Test + public void testGetDirectionalDerivative() throws FmuInvocationException { + comp.enterInitializationMode(); + long[] vUnknownRef = new long[]{TestUtils.REAL_ID}; + long[] vKnownRef = new long[]{TestUtils.REAL_ID}; + double[] dvKnown = new double[]{2}; + FmuResult res = comp.getDirectionalDerivative(vUnknownRef, vKnownRef, dvKnown); + // System.out.println(res); + Assert.assertEquals(Fmi2Status.OK, res.status); + Assert.assertTrue(Math.abs(2 - res.result[0]) <= 10); + } + + @Test + public void testTerminate() throws FmuInvocationException { + testDoStep(); + Assert.assertEquals(Fmi2Status.OK, comp.terminate()); + } + + @Test + public void setGetReal() throws InvalidParameterException, FmuInvocationException { + double value = 99.99; + long[] scalarValueIndices = new long[]{TestUtils.REAL_ID}; + Assert.assertEquals(Fmi2Status.OK, comp.setReals(scalarValueIndices, new double[]{value})); + + Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); + + FmuResult ret = comp.getReal(scalarValueIndices); + Assert.assertEquals(Fmi2Status.OK, ret.status); + Assert.assertEquals(value, ret.result[0], 0.1 / 10E307); + } + + @Test + public void setGetInteger() throws InvalidParameterException, FmuInvocationException { + int value = 99; + long[] scalarValueIndices = new long[]{TestUtils.INTEGER_ID}; + Assert.assertEquals(Fmi2Status.OK, comp.setIntegers(scalarValueIndices, new int[]{value})); + + Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); + + FmuResult ret = comp.getInteger(scalarValueIndices); + Assert.assertEquals(Fmi2Status.OK, ret.status); + Assert.assertEquals(value, ret.result[0]); + } + + @Test + public void setGetBoolean() throws InvalidParameterException, FmuInvocationException { + boolean value = true; + long[] scalarValueIndices = new long[]{TestUtils.BOOLEAN_ID}; + Assert.assertEquals(Fmi2Status.OK, comp.setBooleans(scalarValueIndices, new boolean[]{value})); + + Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); + + FmuResult ret = comp.getBooleans(scalarValueIndices); + Assert.assertEquals(Fmi2Status.OK, ret.status); + Assert.assertEquals(value, ret.result[0]); + } + + @Test + public void getState() throws FmuInvocationException, InvalidParameterException { + FmuResult res = comp.getState(); + System.out.println(res.result); + Assert.assertEquals(Fmi2Status.OK, res.status); + + // change the state and update reaal 0 = 99.99 + long[] scalarValueIndices = new long[]{0}; + + double[] values = new double[]{99.99}; + comp.setReals(scalarValueIndices, values); + + // enable get + Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); + FmuResult real = comp.getReal(scalarValueIndices); + + Assert.assertEquals(values[0], real.result[0], 0.001); + // 0 = 99.99 confirmed + + FmuResult res2 = comp.getState(); + System.out.println(res2.result); + Assert.assertEquals(Fmi2Status.OK, res2.status); + + // set state 0 = 0 + comp.setState(res.result); + + real = comp.getReal(scalarValueIndices); + Assert.assertEquals(0, real.result[0], 0.001); + + // set state 0 = 99.99 + comp.setState(res2.result); + + real = comp.getReal(scalarValueIndices); + Assert.assertEquals(values[0], real.result[0], 0.001); + + + res.result.freeState(); + res2.result.freeState(); + + } + + @Test + public void getStateSerialize() throws FmuInvocationException, InvalidParameterException { + FmuResult res = comp.getState(); + System.out.println(res.result); + Assert.assertEquals(Fmi2Status.OK, res.status); + + // change the state and update reaal 0 = 99.99 + long[] scalarValueIndices = new long[]{0}; + + double[] values = new double[]{99.99}; + comp.setReals(scalarValueIndices, values); + + // enable get + Assert.assertEquals(Fmi2Status.OK, comp.enterInitializationMode()); + FmuResult real = comp.getReal(scalarValueIndices); + + Assert.assertEquals(values[0], real.result[0], 0.001); + // 0 = 99.99 confirmed + + FmuResult stateSizeResult = comp.getSerializedFMUstateSize(res.result); + Assert.assertEquals(Fmi2Status.OK, stateSizeResult.status); + Assert.assertTrue("We dont know what the size should be but must be more than nothing", stateSizeResult.result > 0); + + FmuResult serializedStateResult = comp.serializeFMUstate(res.result, stateSizeResult.result); + Assert.assertEquals(Fmi2Status.OK, serializedStateResult.status); + + //so lets alter the current state + values[0] = 11.11; + comp.setReals(scalarValueIndices, values); + + // enable get + real = comp.getReal(scalarValueIndices); + + Assert.assertEquals(values[0], real.result[0], 0.001); + // 0 = 11.11 confirmed + + // ok lets destroy the original state + res.result.freeState(); + + //lets make a new state from the bytes of the original state just freed + + FmuResult deserializedResult = comp.deSerializeFMUstate(serializedStateResult.result, stateSizeResult.result); + Assert.assertEquals(Fmi2Status.OK, deserializedResult.status); + + Assert.assertEquals("Setting the deserialized state failed", Fmi2Status.OK, comp.setState(deserializedResult.result)); + + real = comp.getReal(scalarValueIndices); + + Assert.assertEquals(99.99, real.result[0], 0.001); + // 0 = 99.99 confirmed + + deserializedResult.result.freeState(); + + } } diff --git a/jnifmuapi/src/test/resources/fmus/fmi2/fmi2functiontest/sources/fmuTemplate.c b/jnifmuapi/src/test/resources/fmus/fmi2/fmi2functiontest/sources/fmuTemplate.c index 88c85b0..4e9875c 100644 --- a/jnifmuapi/src/test/resources/fmus/fmi2/fmi2functiontest/sources/fmuTemplate.c +++ b/jnifmuapi/src/test/resources/fmus/fmi2/fmi2functiontest/sources/fmuTemplate.c @@ -673,6 +673,13 @@ fmi2Status fmi2GetFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) fmi2Status fmi2SetFMUstate(fmi2Component c, fmi2FMUstate FMUstate) {int i = 0; ModelInstance *comp = c; + + if (FMUstate==NULL) + { + FILTERED_LOG(comp, fmi2Error, LOG_FMI_CALL, "fmi2SetFMUstate -- State pointer invalid"); + return fmi2Error; + } + fmi2Real *r =(fmi2Real *)(FMUstate); @@ -714,16 +721,33 @@ fmi2Status fmi2FreeFMUstate(fmi2Component c, fmi2FMUstate* FMUstate) } fmi2Status fmi2SerializedFMUstateSize(fmi2Component c, fmi2FMUstate FMUstate, size_t *size) { - return unsupportedFunction(c, "fmi2SerializedFMUstateSize", MASK_fmi2SerializedFMUstateSize); + *size = NUMBER_OF_REALS * sizeof(fmi2Real); + return fmi2OK; } fmi2Status fmi2SerializeFMUstate(fmi2Component c, fmi2FMUstate FMUstate, fmi2Byte serializedState[], size_t size) { - return unsupportedFunction(c, "fmi2SerializeFMUstate", MASK_fmi2SerializeFMUstate); + ModelInstance *comp = c; + size_t stateSize = NUMBER_OF_REALS * sizeof(fmi2Real); + if(size!=stateSize) + return fmi2Error; + + + memcpy(serializedState, comp->r, stateSize); + return fmi2OK; } fmi2Status fmi2DeSerializeFMUstate(fmi2Component c, const fmi2Byte serializedState[], size_t size, fmi2FMUstate* FMUstate) { - return unsupportedFunction(c, "fmi2DeSerializeFMUstate", MASK_fmi2DeSerializeFMUstate); + ModelInstance *comp = c; + size_t stateSize = NUMBER_OF_REALS * sizeof(fmi2Real); + if(size!=stateSize) + return fmi2Error; + + fmi2Real *r = (fmi2Real *) comp->functions->allocateMemory(NUMBER_OF_REALS, sizeof(fmi2Real)); + + memcpy(r,serializedState, stateSize); + *FMUstate = r; + return fmi2OK; } fmi2Status fmi2GetDirectionalDerivative(fmi2Component c, const fmi2ValueReference vUnknown_ref[], size_t nUnknown,