X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.fmil.core%2Fnative%2FFMUSimulator%2Ffmi_util.c.txt;h=450910cad7820976fc8435cfeec039214e4fa252;hb=6e244a5207b971fd651e40182e41517f511e2c2b;hp=ab87846a02cf15539812502cfb41864ddbf4dc4b;hpb=411f77604de585b8b00e76ce39dab96e530193e5;p=simantics%2Ffmil.git diff --git a/org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt b/org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt index ab87846..450910c 100644 --- a/org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt +++ b/org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt @@ -1,489 +1,800 @@ -/* - Copyright (C) 2012 Modelon AB - - This program is free software: you can redistribute it and/or modify - it under the terms of the BSD style license. - - This program 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 - FMILIB_License.txt file for more details. - - You should have received a copy of the FMILIB_License.txt file - along with this program. If not, contact Modelon AB . -*/ - -#include -#include -#include -#include -#include - -char* fmi_construct_dll_dir_name(jm_callbacks* callbacks, const char* fmu_unzipped_path) { - char* dir_path; - size_t len; - - assert( fmu_unzipped_path && callbacks); - - len = - strlen(fmu_unzipped_path) + strlen(FMI_FILE_SEP) - + strlen(FMI_BINARIES) + strlen(FMI_FILE_SEP) - + strlen(FMI_PLATFORM) + strlen(FMI_FILE_SEP) + 1; - - dir_path = (char*)callbacks->malloc(len); - if (dir_path == NULL) { - jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory."); - return NULL; - } - - sprintf(dir_path, "%s%s%s%s%s%s", fmu_unzipped_path, FMI_FILE_SEP, FMI_BINARIES, FMI_FILE_SEP, FMI_PLATFORM, FMI_FILE_SEP);/*safe */ - - return dir_path; -} - -char* fmi_construct_dll_file_name(jm_callbacks* callbacks, const char* dll_dir_name, const char* model_identifier) { - char* fname; - size_t len; - assert(callbacks && model_identifier); - len = - strlen(dll_dir_name) + - strlen(model_identifier) - + strlen(FMI_DLL_EXT) + 1; - fname = (char*)callbacks->malloc(len); - if (fname == NULL) { - jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory."); - return NULL; - } - sprintf(fname, "%s%s%s", dll_dir_name, model_identifier, FMI_DLL_EXT);/*safe */ - - return fname; -} - - -//// - -#include -#include -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - char *name; - char *description; - char *declaredType; - long vr; - // 0 = real - // 1 = integer - // 2 = boolean - // 3 = string - // 4 = enumeration - int type; - // 0 = constant - // 1 = parameter - // 2 = discrete - // 3 = continuous - // 4 = unknown - int variability; - // 0 = input - // 1 = output - // 2 = internal - // 3 = none - // 4 = unknown - int causality; -} FMIL_Variable; - -typedef struct { - char *name; - char *description; - char *quantity; - char *unit; -} FMIL_DeclaredType; - -__declspec(dllexport) void* FMI1_CS_LOAD(const char *zipFilePath, const char *unzipFolder); -__declspec(dllexport) int FMI1_CS_UNLOAD(void* fmu); -__declspec(dllexport) FMIL_Variable *FMI1_CS_GET_VARIABLES(void* fmu, int *count); -__declspec(dllexport) FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void* fmu, int *count); -__declspec(dllexport) int FMI1_CS_INSTANTIATE(void* fmu); -__declspec(dllexport) int FMI1_CS_INITIALIZE(void* fmu); -__declspec(dllexport) int FMI1_CS_STEP(void* fmu, double masterTime, double stepSize); -__declspec(dllexport) int FMI1_CS_SET_REAL(void* fmu, int vr, double value); -__declspec(dllexport) double FMI1_CS_GET_REAL(void* fmu, int vr); -__declspec(dllexport) int FMI1_CS_GET_REALS(void* fmu, int *vrs, double *values, int count); - -#ifdef __cplusplus -} -#endif - -#define BUFFER 4096 - -/* Logger function used by the C-API */ -void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message) -{ - printf("module = %s, log level = %d: %s\n", module, log_level, message); -} - -/* Logger function used by the FMU internally */ -void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...) -{ - char msg[BUFFER]; - int len; - va_list argp; - va_start(argp, message); - /*len=jm_vsnprintf(msg, BUFFER, message, argp); - printf("fmiStatus = %d; %s (%s): %s\n", status, instanceName, category, msg); - if(len > BUFFER) { - printf("Warning: message was trancated"); - }*/ -} - -void *FMI1_CS_LOAD(char *zipFilePath, char *unzipFolder) { - - fmi1_callback_functions_t callBackFunctions; - fmi_import_context_t* context; - fmi1_fmu_kind_enu_t standard = fmi1_fmu_kind_enu_cs_standalone; - fmi_version_enu_t version; - jm_status_enu_t status; - fmi1_import_t *fmu; - jm_callbacks* callbacks; - - callbacks = (jm_callbacks *)calloc(1, sizeof(jm_callbacks)); - - callbacks->malloc = malloc; - callbacks->calloc = calloc; - callbacks->realloc = realloc; - callbacks->free = free; - callbacks->logger = importlogger; - callbacks->log_level = jm_log_level_debug; - callbacks->context = 0; - - callBackFunctions.logger = fmilogger; - callBackFunctions.allocateMemory = calloc; - callBackFunctions.freeMemory = free; - - context = fmi_import_allocate_context(callbacks); - - version = fmi_import_get_fmi_version(context, zipFilePath, unzipFolder); - - fmu = fmi1_import_parse_xml(context, unzipFolder); - - status = fmi1_import_create_dllfmu(fmu, callBackFunctions, 0); - - fmi_import_free_context(context); - - return fmu; - -} - -int FMI1_CS_UNLOAD(void *fmu_) { - - fmi1_import_t *fmu = (fmi1_import_t *)fmu_; - - fmi1_import_destroy_dllfmu(fmu); - - fmi1_import_free(fmu); - - return 1; - -} - -/* - if(!vt) { - printf("No type definition\n"); - return; - } - - quan = fmi1_import_get_type_quantity(vt); - - printf("Type %s\n description: %s\n", fmi1_import_get_type_name(vt), fmi1_import_get_type_description(vt)); - - printf("Base type: %s\n", fmi1_base_type_to_string(fmi1_import_get_base_type(vt))); - - if(quan) { - printf("Quantity: %s\n", quan); - } - switch(fmi1_import_get_base_type(vt)) { - case fmi1_base_type_real: { - fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(vt); - fmi1_real_t min = fmi1_import_get_real_type_min(rt); - fmi1_real_t max = fmi1_import_get_real_type_max(rt); - fmi1_real_t nom = fmi1_import_get_real_type_nominal(rt); - fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt); - fmi1_import_display_unit_t* du = fmi1_import_get_type_display_unit(rt); - - printf("Min %g, max %g, nominal %g\n", min, max, nom); - - if(u) { - printf("Unit: %s\n", fmi1_import_get_unit_name(u)); - } - if(du) { - printf("Display unit: %s, gain: %g, offset: %g, is relative: %s", - fmi1_import_get_display_unit_name(du), - fmi1_import_get_display_unit_gain(du), - fmi1_import_get_display_unit_offset(du), - fmi1_import_get_real_type_is_relative_quantity(rt)?"yes":"no" - ); - } - - break; - } - case fmi1_base_type_int:{ - fmi1_import_integer_typedef_t* it = fmi1_import_get_type_as_int(vt); - int min = fmi1_import_get_integer_type_min(it); - int max = fmi1_import_get_integer_type_max(it); - printf("Min %d, max %d\n", min, max); - break; - } - case fmi1_base_type_bool:{ - break; - } - case fmi1_base_type_str:{ - break; - } - case fmi1_base_type_enum:{ - fmi1_import_enumeration_typedef_t* et = fmi1_import_get_type_as_enum(vt); - int min = fmi1_import_get_enum_type_min(et); - int max = fmi1_import_get_enum_type_max(et); - printf("Min %d, max %d\n", min, max); - { - size_t ni; - unsigned i; - ni = fmi1_import_get_enum_type_size(et); - i = (unsigned)(ni); - assert( i == ni); - printf("There are %u items \n",(unsigned)ni); - for(i = 0; i < ni; i++) { - printf("[%u] %s (%s) \n", (unsigned)i+1, fmi1_import_get_enum_type_item_name(et, i), fmi1_import_get_enum_type_item_description(et, i)); - } - } - break; - } - default: - printf("Error in fmiGetBaseType()\n"); - } -*/ - - -FMIL_Variable *FMI1_CS_GET_VARIABLES(void *fmu, int *count) { - - int i; - FMIL_Variable *result; - fmi1_import_variable_list_t* vl = fmi1_import_get_variable_list((fmi1_import_t *)fmu); - fmi1_import_variable_typedef_t* type; - - count[0] = fmi1_import_get_variable_list_size(vl); - - result = (FMIL_Variable *)malloc(count[0]*sizeof(FMIL_Variable)); - - for(i = 0; i < count[0]; i++) { - - fmi1_import_variable_t* var = fmi1_import_get_variable(vl, i); - if(!var) { - - printf("Something wrong with variable %d \n",i); - return 0; - - } else { - - result[i].name = fmi1_import_get_variable_name(var); - result[i].description = fmi1_import_get_variable_description(var); - - switch (fmi1_import_get_variability(var)) { - case fmi1_variability_enu_constant: - result[i].variability = 0; - break; - case fmi1_variability_enu_parameter: - result[i].variability = 1; - break; - case fmi1_variability_enu_discrete: - result[i].variability = 2; - break; - case fmi1_variability_enu_continuous: - result[i].variability = 3; - break; - case fmi1_variability_enu_unknown: - result[i].variability = 4; - break; - } - - switch (fmi1_import_get_causality(var)) { - case fmi1_causality_enu_input: - result[i].causality = 0; - break; - case fmi1_causality_enu_output: - result[i].causality = 1; - break; - case fmi1_causality_enu_internal: - result[i].causality = 2; - break; - case fmi1_causality_enu_none: - result[i].causality = 3; - break; - case fmi1_causality_enu_unknown: - result[i].causality = 4; - break; - } - - switch (fmi1_import_get_variable_base_type(var)) { - case fmi1_base_type_real: - result[i].type = 0; - break; - case fmi1_base_type_int: - result[i].type = 1; - break; - case fmi1_base_type_bool: - result[i].type = 2; - break; - case fmi1_base_type_str: - result[i].type = 3; - break; - case fmi1_base_type_enum: - result[i].type = 4; - break; - } - - result[i].vr = fmi1_import_get_variable_vr(var); - - type = fmi1_import_get_variable_declared_type(var); - if(type) { - result[i].declaredType = fmi1_import_get_type_name(type); - } else { - result[i].declaredType = 0; - } - - } - - } - - fmi1_import_free_variable_list(vl); - - return result; - -} - -FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void *fmu, int *count) { - - FMIL_DeclaredType *result; - fmi1_import_type_definitions_t* td = fmi1_import_get_type_definitions((fmi1_import_t *)fmu); - fmi1_import_variable_typedef_t* type; - unsigned i, ntd = (unsigned)fmi1_import_get_type_definition_number(td); - - count[0] = ntd; - - result = (FMIL_DeclaredType *)malloc(count[0]*sizeof(FMIL_DeclaredType)); - - for(i = 0; i < ntd; i++) { - type = fmi1_import_get_typedef(td, i); - result[i].name = fmi1_import_get_type_name(type); - result[i].description = fmi1_import_get_type_description(type); - result[i].quantity = fmi1_import_get_type_quantity(type); - result[i].unit = 0; - - switch(fmi1_import_get_base_type(type)) { - case fmi1_base_type_real: { - fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(type); - fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt); - if(u) result[i].unit = fmi1_import_get_unit_name(u); - } - } - - } - - return result; - -} - -#define INSTANCE_NAME "kekkeli" - -int FMI1_CS_INSTANTIATE(void *fmu) { - - fmi1_string_t fmuLocation; - fmi1_string_t mimeType; - fmi1_real_t timeout; - fmi1_boolean_t visible; - fmi1_boolean_t interactive; - fmi1_boolean_t loggingOn; - - fmuLocation = ""; - mimeType = ""; - timeout = 0; - visible = fmi1_false; - interactive = fmi1_false; - loggingOn = fmi1_true; - - if (fmi1_import_instantiate_slave(fmu, INSTANCE_NAME, NULL, NULL, timeout, fmi1_false, fmi1_false) == NULL) { - printf("fmi1_capi_instantiate_slave: Failed\n"); - return 0; - } else { - printf("fmi1_capi_instantiate_slave: Success\n"); - } - return 0; - -} - -int FMI1_CS_INITIALIZE(void *fmu) { - - fmi1_status_t status; - fmi1_real_t tStart; - fmi1_real_t tStop; - fmi1_boolean_t StopTimeDefined; - - tStart = 0; - tStop = 10; - StopTimeDefined = fmi1_false; - - status = fmi1_import_initialize_slave((fmi1_import_t *)fmu, tStart, StopTimeDefined, tStop); - if (status == fmi1_status_error || status == fmi1_status_fatal) { - printf("fmi1_capi_initialize_slave: Failed\n"); - return 0; - } else { - printf("fmi1_capi_initialize_slave: Success\n"); - } - return 0; - -} - -int FMI1_CS_STEP(void *fmu, double masterTime, double stepSize) { - - fmi1_status_t status; - - status = fmi1_import_do_step((fmi1_import_t *)fmu, (fmi1_real_t)masterTime, (fmi1_real_t)stepSize, fmi1_true); - if (status == fmi1_status_error || status == fmi1_status_fatal) { - return 1; - } else { - return 0; - } -} - -int FMI1_CS_SET_REAL(void *fmu, long valueId, double value) { - - fmi1_value_reference_t vr = valueId; - fmi1_import_set_real((fmi1_import_t *)fmu, &vr, 1, &value); - - return 0; - -} - -double FMI1_CS_GET_REAL(void *fmu, int valueReference) { - - fmi1_value_reference_t vr = valueReference; - fmi1_real_t value; - fmi1_import_get_real((fmi1_import_t *)fmu, &vr, 1, &value); - return value; - -} - -int FMI1_CS_GET_REALS(void *fmu, int *valueReferences, double *result, int count) { - - fmi1_value_reference_t *vrs = valueReferences; - fmi1_real_t value; - fmi1_import_get_real((fmi1_import_t *)fmu, vrs, count, result); - return 1; - -} +/* + Copyright (C) 2012 Modelon AB + + This program is free software: you can redistribute it and/or modify + it under the terms of the BSD style license. + + This program 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 + FMILIB_License.txt file for more details. + + You should have received a copy of the FMILIB_License.txt file + along with this program. If not, contact Modelon AB . +*/ + +#include +#include +#include +#include +#include + + +char* fmi_construct_dll_dir_name(jm_callbacks* callbacks, const char* fmu_unzipped_path) { + char* dir_path; + size_t len; + + assert( fmu_unzipped_path && callbacks); + + len = + strlen(fmu_unzipped_path) + strlen(FMI_FILE_SEP) + + strlen(FMI_BINARIES) + strlen(FMI_FILE_SEP) + + strlen(FMI_PLATFORM) + strlen(FMI_FILE_SEP) + 1; + + dir_path = (char*)callbacks->malloc(len); + if (dir_path == NULL) { + jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory."); + return NULL; + } + + sprintf(dir_path, "%s%s%s%s%s%s", fmu_unzipped_path, FMI_FILE_SEP, FMI_BINARIES, FMI_FILE_SEP, FMI_PLATFORM, FMI_FILE_SEP);/*safe */ + + return dir_path; +} + +char* fmi_construct_dll_file_name(jm_callbacks* callbacks, const char* dll_dir_name, const char* model_identifier) { + char* fname; + size_t len; + assert(callbacks && model_identifier); + len = + strlen(dll_dir_name) + + strlen(model_identifier) + + strlen(FMI_DLL_EXT) + 1; + fname = (char*)callbacks->malloc(len); + if (fname == NULL) { + jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory."); + return NULL; + } + sprintf(fname, "%s%s%s", dll_dir_name, model_identifier, FMI_DLL_EXT);/*safe */ + + return fname; +} + +#include +#include +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char *name; + char *description; + char *declaredType; + long vr; + /* 0 = real + // 1 = integer + // 2 = boolean + // 3 = string + // 4 = enumeration */ + int type; + /* 0 = constant + // 1 = parameter + // 2 = discrete + // 3 = continuous + // 4 = unknown */ + int variability; + /* 0 = input + // 1 = output + // 2 = internal + // 3 = none + // 4 = unknown */ + int causality; +} FMIL_Variable; + +typedef struct { + char *name; + char *description; + char *quantity; + char *unit; +} FMIL_DeclaredType; + +#ifdef _MSC_VER +#define DLLEXPORT __declspec(dllexport) +#elif __GNUC__ +#define DLLEXPORT __attribute__((visibility("default"))) +#pragma warning Using GNUC default visibility +#else +#define DLLEXPORT +#pragma warning Empty dynamic link EXPORT defined +#endif + +DLLEXPORT int FMI_CS_LOAD(const char *zipFilePath, const char *unzipFolder, void **fmuPointer, int *fmuVersion, const char **error); + +DLLEXPORT int FMI1_CS_UNLOAD(void* fmu, const char **error); +DLLEXPORT FMIL_Variable *FMI1_CS_GET_VARIABLES(void* fmu, int *count, const char **error); +DLLEXPORT FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void* fmu, int *count, const char **error); +DLLEXPORT int FMI1_CS_INSTANTIATE(void* fmu, const char *instanceName, const char **error); +DLLEXPORT int FMI1_CS_INITIALIZE(void* fmu, const char **error); +DLLEXPORT int FMI1_CS_STEP(void* fmu, double masterTime, double stepSize, const char **error); +DLLEXPORT int FMI1_CS_SET_REAL(void* fmu, int vr, double value, const char **error); +DLLEXPORT double FMI1_CS_GET_REAL(void* fmu, int vr, const char **error); +DLLEXPORT int FMI1_CS_GET_REALS(void* fmu, int *vrs, double *values, int count, const char **error); + +DLLEXPORT int FMI2_CS_UNLOAD(void* fmu, const char **error); +DLLEXPORT FMIL_Variable *FMI2_CS_GET_VARIABLES(void* fmu, int *count, const char **error); +DLLEXPORT FMIL_DeclaredType *FMI2_CS_GET_DECLARED_TYPES(void* fmu, int *count, const char **error); +DLLEXPORT int FMI2_CS_INSTANTIATE(void* fmu, const char *instanceName, const char **error); +DLLEXPORT int FMI2_CS_INITIALIZE(void* fmu, const char **error); +DLLEXPORT int FMI2_CS_STEP(void* fmu, double masterTime, double stepSize, const char **error); +DLLEXPORT int FMI2_CS_SET_REAL(void* fmu, int vr, double value, const char **error); +DLLEXPORT double FMI2_CS_GET_REAL(void* fmu, int vr, const char **error); +DLLEXPORT int FMI2_CS_GET_REALS(void* fmu, int *vrs, double *values, int count, const char **error); + +#ifdef __cplusplus +} +#endif + +#define BUFFER 4096 + +/* Logger function used by the C-API */ +void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message) +{ + printf("module = %s, log level = %d: %s\n", module, log_level, message); +} + +/* Logger function used by the FMU internally */ +void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...) +{ + char msg[BUFFER]; + int len; + va_list argp; + va_start(argp, message); + /*len=jm_vsnprintf(msg, BUFFER, message, argp); + printf("fmiStatus = %d; %s (%s): %s\n", status, instanceName, category, msg); + if(len > BUFFER) { + printf("Warning: message was trancated"); + }*/ +} + +int FMI_CS_LOAD(const char *zipFilePath, const char *unzipFolder, void **fmuPointer, int *fmuVersion, const char **error) { + + fmi1_callback_functions_t callBackFunctions; + fmi2_callback_functions_t callBackFunctions2; + fmi_import_context_t* context; + fmi_version_enu_t version; + jm_status_enu_t status; + fmi1_import_t *fmu; + fmi2_import_t *fmu2; + jm_callbacks* callbacks; + + callbacks = (jm_callbacks *)calloc(1, sizeof(jm_callbacks)); + + callbacks->malloc = malloc; + callbacks->calloc = calloc; + callbacks->realloc = realloc; + callbacks->free = free; + callbacks->logger = importlogger; +#ifdef _DEBUG + callbacks->log_level = jm_log_level_debug; +#else + callbacks->log_level = jm_log_level_warning; +#endif + callbacks->context = 0; + + context = fmi_import_allocate_context(callbacks); + + version = fmi_import_get_fmi_version(context, zipFilePath, unzipFolder); + + if (version == fmi_version_1_enu ) { + fmu = fmi1_import_parse_xml(context, unzipFolder); + if (fmi1_import_get_fmu_kind(fmu) != fmi1_fmu_kind_enu_cs_standalone && fmi1_import_get_fmu_kind(fmu) != fmi1_fmu_kind_enu_cs_tool) { + *error = "Provided FMU is version 1 but wrong type me (Model Exchange) when it should be cs (Co-Simulation)"; + return 2; /* wrong type, should be co-simulation */ + } + + callBackFunctions.logger = fmilogger; + callBackFunctions.allocateMemory = calloc; + callBackFunctions.freeMemory = free; + + status = fmi1_import_create_dllfmu(fmu, callBackFunctions, 0); + if (status == jm_status_error) { + *error = fmi1_import_get_last_error(fmu); + return 3; + } + + *fmuPointer = fmu; + *fmuVersion = 1; + } else if (version == fmi_version_2_0_enu) { + fmu2 = fmi2_import_parse_xml(context, unzipFolder, 0); + + if (fmi2_import_get_fmu_kind(fmu2) != fmi1_fmu_kind_enu_cs_standalone && fmi2_import_get_fmu_kind(fmu2) != fmi1_fmu_kind_enu_cs_tool) { + *error = "Provided FMU is version 2.0 but wrong type me (Model Exchange) when it should be cs (Co-Simulation)"; + return 2; /* wrong type, should be co-simulation */ + } + + callBackFunctions2.logger = fmi2_log_forwarding; + callBackFunctions2.allocateMemory = calloc; + callBackFunctions2.freeMemory = free; + callBackFunctions2.componentEnvironment = fmu2; + + status = fmi2_import_create_dllfmu(fmu2, fmi2_fmu_kind_cs, &callBackFunctions2); + if (status == jm_status_error) { + *error = fmi2_import_get_last_error(fmu2); + return 3; + } + + *fmuPointer = fmu2; + *fmuVersion = 2; + } + + fmi_import_free_context(context); + + return 0; /* success */ +} + +int FMI1_CS_UNLOAD(void *fmu_, const char **error) { + fmi1_import_t *fmu = (fmi1_import_t *)fmu_; + fmi1_import_destroy_dllfmu(fmu); + fmi1_import_free(fmu); + return 0; +} + +int FMI2_CS_UNLOAD(void *fmu_, const char **error) { + fmi2_import_t *fmu = (fmi2_import_t *)fmu_; + fmi2_import_destroy_dllfmu(fmu); + fmi2_import_free(fmu); + return 0; +} + +/* + if(!vt) { + printf("No type definition\n"); + return; + } + + quan = fmi1_import_get_type_quantity(vt); + + printf("Type %s\n description: %s\n", fmi1_import_get_type_name(vt), fmi1_import_get_type_description(vt)); + + printf("Base type: %s\n", fmi1_base_type_to_string(fmi1_import_get_base_type(vt))); + + if(quan) { + printf("Quantity: %s\n", quan); + } + switch(fmi1_import_get_base_type(vt)) { + case fmi1_base_type_real: { + fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(vt); + fmi1_real_t min = fmi1_import_get_real_type_min(rt); + fmi1_real_t max = fmi1_import_get_real_type_max(rt); + fmi1_real_t nom = fmi1_import_get_real_type_nominal(rt); + fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt); + fmi1_import_display_unit_t* du = fmi1_import_get_type_display_unit(rt); + + printf("Min %g, max %g, nominal %g\n", min, max, nom); + + if(u) { + printf("Unit: %s\n", fmi1_import_get_unit_name(u)); + } + if(du) { + printf("Display unit: %s, gain: %g, offset: %g, is relative: %s", + fmi1_import_get_display_unit_name(du), + fmi1_import_get_display_unit_gain(du), + fmi1_import_get_display_unit_offset(du), + fmi1_import_get_real_type_is_relative_quantity(rt)?"yes":"no" + ); + } + + break; + } + case fmi1_base_type_int:{ + fmi1_import_integer_typedef_t* it = fmi1_import_get_type_as_int(vt); + int min = fmi1_import_get_integer_type_min(it); + int max = fmi1_import_get_integer_type_max(it); + printf("Min %d, max %d\n", min, max); + break; + } + case fmi1_base_type_bool:{ + break; + } + case fmi1_base_type_str:{ + break; + } + case fmi1_base_type_enum:{ + fmi1_import_enumeration_typedef_t* et = fmi1_import_get_type_as_enum(vt); + int min = fmi1_import_get_enum_type_min(et); + int max = fmi1_import_get_enum_type_max(et); + printf("Min %d, max %d\n", min, max); + { + size_t ni; + unsigned i; + ni = fmi1_import_get_enum_type_size(et); + i = (unsigned)(ni); + assert( i == ni); + printf("There are %u items \n",(unsigned)ni); + for(i = 0; i < ni; i++) { + printf("[%u] %s (%s) \n", (unsigned)i+1, fmi1_import_get_enum_type_item_name(et, i), fmi1_import_get_enum_type_item_description(et, i)); + } + } + break; + } + default: + printf("Error in fmiGetBaseType()\n"); + } +*/ + + +FMIL_Variable *FMI1_CS_GET_VARIABLES(void *fmu, int *count, const char **error) { + + int i; + FMIL_Variable *result; + fmi1_import_variable_list_t* vl = fmi1_import_get_variable_list((fmi1_import_t *)fmu); + fmi1_import_variable_typedef_t* type; + + count[0] = fmi1_import_get_variable_list_size(vl); + + result = (FMIL_Variable *)malloc(count[0]*sizeof(FMIL_Variable)); + + for(i = 0; i < count[0]; i++) { + + fmi1_import_variable_t* var = fmi1_import_get_variable(vl, i); + if(!var) { + + printf("Something wrong with variable %d \n",i); + return 0; + + } else { + + result[i].name = fmi1_import_get_variable_name(var); + result[i].description = fmi1_import_get_variable_description(var); + + switch (fmi1_import_get_variability(var)) { + case fmi1_variability_enu_constant: + result[i].variability = 0; + break; + case fmi1_variability_enu_parameter: + result[i].variability = 1; + break; + case fmi1_variability_enu_discrete: + result[i].variability = 2; + break; + case fmi1_variability_enu_continuous: + result[i].variability = 3; + break; + case fmi1_variability_enu_unknown: + result[i].variability = 4; + break; + } + + switch (fmi1_import_get_causality(var)) { + case fmi1_causality_enu_input: + result[i].causality = 0; + break; + case fmi1_causality_enu_output: + result[i].causality = 1; + break; + case fmi1_causality_enu_internal: + result[i].causality = 2; + break; + case fmi1_causality_enu_none: + result[i].causality = 3; + break; + case fmi1_causality_enu_unknown: + result[i].causality = 4; + break; + } + + switch (fmi1_import_get_variable_base_type(var)) { + case fmi1_base_type_real: + result[i].type = 0; + break; + case fmi1_base_type_int: + result[i].type = 1; + break; + case fmi1_base_type_bool: + result[i].type = 2; + break; + case fmi1_base_type_str: + result[i].type = 3; + break; + case fmi1_base_type_enum: + result[i].type = 4; + break; + } + + result[i].vr = fmi1_import_get_variable_vr(var); + + type = fmi1_import_get_variable_declared_type(var); + if(type) { + result[i].declaredType = fmi1_import_get_type_name(type); + } else { + result[i].declaredType = 0; + } + + } + + } + + fmi1_import_free_variable_list(vl); + + return result; + +} + +FMIL_Variable *FMI2_CS_GET_VARIABLES(void *fmu, int *count, const char **error) { + + int i; + FMIL_Variable *result; + fmi2_import_variable_list_t* vl = fmi2_import_get_variable_list((fmi2_import_t *)fmu, 0); + fmi2_import_variable_typedef_t* type; + + count[0] = fmi2_import_get_variable_list_size(vl); + + result = (FMIL_Variable *)malloc(count[0]*sizeof(FMIL_Variable)); + + for(i = 0; i < count[0]; i++) { + + fmi2_import_variable_t* var = fmi2_import_get_variable(vl, i); + if(!var) { + + printf("Something wrong with variable %d \n",i); + return 0; + + } else { + + result[i].name = fmi2_import_get_variable_name(var); + result[i].description = fmi2_import_get_variable_description(var); + + switch (fmi2_import_get_variability(var)) { + case fmi2_variability_enu_constant: + result[i].variability = 0; + break; + case fmi2_variability_enu_fixed: + case fmi2_variability_enu_tunable: + result[i].variability = 1; + break; + case fmi2_variability_enu_discrete: + result[i].variability = 2; + break; + case fmi2_variability_enu_continuous: + result[i].variability = 3; + break; + case fmi2_variability_enu_unknown: + result[i].variability = 4; + break; + } + + switch (fmi2_import_get_causality(var)) { + case fmi2_causality_enu_input: + result[i].causality = 0; + break; + case fmi2_causality_enu_output: + result[i].causality = 1; + break; + case fmi2_causality_enu_local: + result[i].causality = 2; + break; + case fmi2_causality_enu_independent: + result[i].causality = 3; + break; + case fmi2_causality_enu_unknown: + result[i].causality = 4; + break; + } + + switch (fmi2_import_get_variable_base_type(var)) { + case fmi2_base_type_real: + result[i].type = 0; + break; + case fmi2_base_type_int: + result[i].type = 1; + break; + case fmi2_base_type_bool: + result[i].type = 2; + break; + case fmi2_base_type_str: + result[i].type = 3; + break; + case fmi2_base_type_enum: + result[i].type = 4; + break; + } + + result[i].vr = fmi2_import_get_variable_vr(var); + + type = fmi2_import_get_variable_declared_type(var); + if(type) { + result[i].declaredType = fmi2_import_get_type_name(type); + } else { + result[i].declaredType = 0; + } + + } + + } + + fmi2_import_free_variable_list(vl); + + return result; + +} + +FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void *fmu, int *count, const char **error) { + + FMIL_DeclaredType *result; + fmi1_import_type_definitions_t* td = fmi1_import_get_type_definitions((fmi1_import_t *)fmu); + fmi1_import_variable_typedef_t* type; + unsigned i, ntd = (unsigned)fmi1_import_get_type_definition_number(td); + + count[0] = ntd; + + result = (FMIL_DeclaredType *)malloc(count[0]*sizeof(FMIL_DeclaredType)); + + for(i = 0; i < ntd; i++) { + type = fmi1_import_get_typedef(td, i); + result[i].name = fmi1_import_get_type_name(type); + result[i].description = fmi1_import_get_type_description(type); + result[i].quantity = fmi1_import_get_type_quantity(type); + result[i].unit = 0; + + switch(fmi1_import_get_base_type(type)) { + case fmi1_base_type_real: { + fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(type); + fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt); + if(u) result[i].unit = fmi1_import_get_unit_name(u); + } + } + + } + + return result; + +} + +FMIL_DeclaredType *FMI2_CS_GET_DECLARED_TYPES(void *fmu, int *count, const char **error) { + + FMIL_DeclaredType *result; + fmi2_import_type_definitions_t* td = fmi2_import_get_type_definitions((fmi2_import_t *)fmu); + fmi2_import_variable_typedef_t* type; + unsigned i, ntd = (unsigned)fmi2_import_get_type_definition_number(td); + + count[0] = ntd; + + result = (FMIL_DeclaredType *)malloc(count[0]*sizeof(FMIL_DeclaredType)); + + for(i = 0; i < ntd; i++) { + type = fmi2_import_get_typedef(td, i); + result[i].name = fmi2_import_get_type_name(type); + result[i].description = fmi2_import_get_type_description(type); + result[i].quantity = fmi2_import_get_type_quantity(type); + result[i].unit = 0; + + switch(fmi2_import_get_base_type(type)) { + case fmi2_base_type_real: { + fmi2_import_real_typedef_t* rt = fmi2_import_get_type_as_real(type); + fmi2_import_unit_t* u = fmi2_import_get_real_type_unit(rt); + if(u) result[i].unit = fmi2_import_get_unit_name(u); + } + } + + } + + return result; + +} + +int FMI1_CS_INSTANTIATE(void *fmu, const char *instanceName, const char **error) { + + fmi1_string_t fmuLocation; + fmi1_string_t mimeType; + fmi1_real_t timeout; + fmi1_boolean_t visible; + fmi1_boolean_t interactive; + fmi1_boolean_t loggingOn; + + jm_status_enu_t jmstatus; + + fmuLocation = ""; + mimeType = ""; + timeout = 0; + visible = fmi1_false; + interactive = fmi1_false; + loggingOn = fmi1_true; + + jmstatus = fmi1_import_instantiate_slave((fmi1_import_t*)fmu, instanceName, NULL, NULL, timeout, fmi1_false, fmi1_false); + if (jmstatus == jm_status_error) { + *error = fmi1_import_get_last_error((fmi1_import_t*)fmu); + return 1; + } + return 0; +} + +int FMI2_CS_INSTANTIATE(void *fmu, const char *instanceName, const char **error) { + + fmi2_string_t fmuLocation; + fmi2_string_t mimeType; + fmi2_real_t timeout; + fmi2_boolean_t visible; + fmi2_boolean_t interactive; + fmi2_boolean_t loggingOn; + jm_status_enu_t jmstatus; + + fmuLocation = ""; + mimeType = ""; + timeout = 0; + visible = fmi2_false; + jmstatus = fmi2_import_instantiate((fmi2_import_t*)fmu, instanceName, fmi2_cosimulation, NULL, visible); + if (jmstatus == jm_status_error) { + *error = fmi2_import_get_last_error((fmi2_import_t*)fmu); + return 1; + } + return 0; +} + +int FMI1_CS_INITIALIZE(void *fmu, const char **error) { + + fmi1_status_t status; + fmi1_real_t tStart; + fmi1_real_t tStop; + fmi1_boolean_t StopTimeDefined; + + tStart = 0; + tStop = 10; + StopTimeDefined = fmi1_false; + + status = fmi1_import_initialize_slave((fmi1_import_t *)fmu, tStart, StopTimeDefined, tStop); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + printf("fmi1_capi_initialize_slave: Failed\n"); + return 0; + } else { + printf("fmi1_capi_initialize_slave: Success\n"); + } + return 0; + +} + +int FMI2_CS_INITIALIZE(void *fmu, const char **error) { + + fmi2_real_t tStart; + fmi2_real_t tStop; + fmi2_boolean_t StopTimeDefined; + fmi2_real_t relativeTol = 1e-4; + + fmi2_status_t fmistatus; + + tStart = 0; + tStop = 10; + StopTimeDefined = fmi1_false; + + fmistatus = fmi2_import_setup_experiment((fmi2_import_t*)fmu, fmi2_true, relativeTol, tStart, StopTimeDefined, tStop); + if(fmistatus != fmi2_status_ok) { + *error = ("fmi2_import_setup_experiment failed\n"); + return 1; + } + + fmistatus = fmi2_import_enter_initialization_mode((fmi2_import_t*)fmu); + if(fmistatus != fmi2_status_ok) { + *error = ("fmi2_import_enter_initialization_mode failed\n"); + return 1; + } + + fmistatus = fmi2_import_exit_initialization_mode((fmi2_import_t*)fmu); + if(fmistatus != fmi2_status_ok) { + *error = ("fmi2_import_exit_initialization_mode failed\n"); + return 1; + } + + return 0; +} + +int FMI1_CS_STEP(void *fmu, double masterTime, double stepSize, const char **error) { + + fmi1_status_t status; + + status = fmi1_import_do_step((fmi1_import_t *)fmu, (fmi1_real_t)masterTime, (fmi1_real_t)stepSize, fmi1_true); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + *error = "Error happened during stepping!"; + return 1; + } + return 0; +} + +int FMI2_CS_STEP(void *fmu, double masterTime, double stepSize, const char **error) { + + fmi2_status_t status; + + status = fmi2_import_do_step((fmi2_import_t *)fmu, (fmi2_real_t)masterTime, (fmi2_real_t)stepSize, fmi2_true); + if (status == fmi2_status_error || status == fmi2_status_fatal) { + *error = "Error happened during stepping!"; + return 1; + } + return 0; +} + +int FMI1_CS_SET_REAL(void *fmu, int valueId, double value, const char **error) { + + fmi1_status_t status; + + fmi1_value_reference_t vr = valueId; + status = fmi1_import_set_real((fmi1_import_t *)fmu, &vr, 1, &value); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + *error = "Error happened during setting real value!"; + return 1; + } + return 0; +} + +int FMI2_CS_SET_REAL(void *fmu, int valueId, double value, const char **error) { + + fmi2_status_t status; + + fmi2_value_reference_t vr = valueId; + status = fmi2_import_set_real((fmi2_import_t *)fmu, &vr, 1, &value); + if (status == fmi2_status_error || status == fmi2_status_fatal) { + *error = "Error happened during setting real value!"; + return 1; + } + return 0; +} + +double FMI1_CS_GET_REAL(void *fmu, int valueReference, const char **error) { + + fmi1_value_reference_t vr = valueReference; + fmi1_real_t value; + + fmi1_status_t status; + + status = fmi1_import_get_real((fmi1_import_t *)fmu, &vr, 1, &value); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + *error = "Error happened during getting real value!"; + } + return value; +} + +double FMI2_CS_GET_REAL(void *fmu, int valueReference, const char **error) { + + fmi2_value_reference_t vr = valueReference; + fmi2_real_t value; + + fmi2_status_t status; + + status = fmi2_import_get_real((fmi2_import_t *)fmu, &vr, 1, &value); + if (status == fmi2_status_error || status == fmi2_status_fatal) { + *error = "Error happened during setting real value!"; + } + return value; +} + +int FMI1_CS_GET_REALS(void *fmu, int *valueReferences, double *result, int count, const char **error) { + + fmi1_value_reference_t *vrs = (fmi1_value_reference_t*) valueReferences; + fmi1_real_t value; + + fmi1_status_t status; + + status = fmi1_import_get_real((fmi1_import_t *)fmu, vrs, count, result); + if (status == fmi1_status_error || status == fmi1_status_fatal) { + *error = "Error happened during getting reals value!"; + } + return 0; +} + +int FMI2_CS_GET_REALS(void *fmu, int *valueReferences, double *result, int count, const char **error) { + + fmi2_value_reference_t *vrs = (fmi2_value_reference_t*) valueReferences; + fmi2_real_t value; + + fmi2_status_t status; + + status = fmi2_import_get_real((fmi2_import_t *)fmu, vrs, count, result); + if (status == fmi2_status_error || status == fmi2_status_fatal) { + *error = "Error happened during getting reals value!"; + } + return 0; + +}