/* 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; }