2 Copyright (C) 2012 Modelon AB
\r
4 This program is free software: you can redistribute it and/or modify
\r
5 it under the terms of the BSD style license.
\r
7 This program is distributed in the hope that it will be useful,
\r
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
10 FMILIB_License.txt file for more details.
\r
12 You should have received a copy of the FMILIB_License.txt file
\r
13 along with this program. If not, contact Modelon AB <http://www.modelon.com>.
\r
19 #include <FMI/fmi_util.h>
\r
20 #include <FMI/fmi_zip_unzip.h>
\r
22 char* fmi_construct_dll_dir_name(jm_callbacks* callbacks, const char* fmu_unzipped_path) {
\r
26 assert( fmu_unzipped_path && callbacks);
\r
29 strlen(fmu_unzipped_path) + strlen(FMI_FILE_SEP)
\r
30 + strlen(FMI_BINARIES) + strlen(FMI_FILE_SEP)
\r
31 + strlen(FMI_PLATFORM) + strlen(FMI_FILE_SEP) + 1;
\r
33 dir_path = (char*)callbacks->malloc(len);
\r
34 if (dir_path == NULL) {
\r
35 jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory.");
\r
39 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 */
\r
44 char* fmi_construct_dll_file_name(jm_callbacks* callbacks, const char* dll_dir_name, const char* model_identifier) {
\r
47 assert(callbacks && model_identifier);
\r
49 strlen(dll_dir_name) +
\r
50 strlen(model_identifier)
\r
51 + strlen(FMI_DLL_EXT) + 1;
\r
52 fname = (char*)callbacks->malloc(len);
\r
53 if (fname == NULL) {
\r
54 jm_log_fatal(callbacks, "FMIUT", "Failed to allocate memory.");
\r
57 sprintf(fname, "%s%s%s", dll_dir_name, model_identifier, FMI_DLL_EXT);/*safe */
\r
107 } FMIL_DeclaredType;
\r
109 __declspec(dllexport) void* FMI1_CS_LOAD(const char *zipFilePath, const char *unzipFolder);
\r
110 __declspec(dllexport) int FMI1_CS_UNLOAD(void* fmu);
\r
111 __declspec(dllexport) FMIL_Variable *FMI1_CS_GET_VARIABLES(void* fmu, int *count);
\r
112 __declspec(dllexport) FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void* fmu, int *count);
\r
113 __declspec(dllexport) int FMI1_CS_INSTANTIATE(void* fmu);
\r
114 __declspec(dllexport) int FMI1_CS_INITIALIZE(void* fmu);
\r
115 __declspec(dllexport) int FMI1_CS_STEP(void* fmu, double masterTime, double stepSize);
\r
116 __declspec(dllexport) int FMI1_CS_SET_REAL(void* fmu, int vr, double value);
\r
117 __declspec(dllexport) double FMI1_CS_GET_REAL(void* fmu, int vr);
\r
118 __declspec(dllexport) int FMI1_CS_GET_REALS(void* fmu, int *vrs, double *values, int count);
\r
124 #define BUFFER 4096
\r
126 /* Logger function used by the C-API */
\r
127 void importlogger(jm_callbacks* c, jm_string module, jm_log_level_enu_t log_level, jm_string message)
\r
129 printf("module = %s, log level = %d: %s\n", module, log_level, message);
\r
132 /* Logger function used by the FMU internally */
\r
133 void fmilogger(fmi1_component_t c, fmi1_string_t instanceName, fmi1_status_t status, fmi1_string_t category, fmi1_string_t message, ...)
\r
138 va_start(argp, message);
\r
139 /*len=jm_vsnprintf(msg, BUFFER, message, argp);
\r
140 printf("fmiStatus = %d; %s (%s): %s\n", status, instanceName, category, msg);
\r
142 printf("Warning: message was trancated");
\r
146 void *FMI1_CS_LOAD(char *zipFilePath, char *unzipFolder) {
\r
148 fmi1_callback_functions_t callBackFunctions;
\r
149 fmi_import_context_t* context;
\r
150 fmi1_fmu_kind_enu_t standard = fmi1_fmu_kind_enu_cs_standalone;
\r
151 fmi_version_enu_t version;
\r
152 jm_status_enu_t status;
\r
153 fmi1_import_t *fmu;
\r
154 jm_callbacks* callbacks;
\r
156 callbacks = (jm_callbacks *)calloc(1, sizeof(jm_callbacks));
\r
158 callbacks->malloc = malloc;
\r
159 callbacks->calloc = calloc;
\r
160 callbacks->realloc = realloc;
\r
161 callbacks->free = free;
\r
162 callbacks->logger = importlogger;
\r
163 callbacks->log_level = jm_log_level_debug;
\r
164 callbacks->context = 0;
\r
166 callBackFunctions.logger = fmilogger;
\r
167 callBackFunctions.allocateMemory = calloc;
\r
168 callBackFunctions.freeMemory = free;
\r
170 context = fmi_import_allocate_context(callbacks);
\r
172 version = fmi_import_get_fmi_version(context, zipFilePath, unzipFolder);
\r
174 fmu = fmi1_import_parse_xml(context, unzipFolder);
\r
176 status = fmi1_import_create_dllfmu(fmu, callBackFunctions, 0);
\r
178 fmi_import_free_context(context);
\r
184 int FMI1_CS_UNLOAD(void *fmu_) {
\r
186 fmi1_import_t *fmu = (fmi1_import_t *)fmu_;
\r
188 fmi1_import_destroy_dllfmu(fmu);
\r
190 fmi1_import_free(fmu);
\r
198 printf("No type definition\n");
\r
202 quan = fmi1_import_get_type_quantity(vt);
\r
204 printf("Type %s\n description: %s\n", fmi1_import_get_type_name(vt), fmi1_import_get_type_description(vt));
\r
206 printf("Base type: %s\n", fmi1_base_type_to_string(fmi1_import_get_base_type(vt)));
\r
209 printf("Quantity: %s\n", quan);
\r
211 switch(fmi1_import_get_base_type(vt)) {
\r
212 case fmi1_base_type_real: {
\r
213 fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(vt);
\r
214 fmi1_real_t min = fmi1_import_get_real_type_min(rt);
\r
215 fmi1_real_t max = fmi1_import_get_real_type_max(rt);
\r
216 fmi1_real_t nom = fmi1_import_get_real_type_nominal(rt);
\r
217 fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt);
\r
218 fmi1_import_display_unit_t* du = fmi1_import_get_type_display_unit(rt);
\r
220 printf("Min %g, max %g, nominal %g\n", min, max, nom);
\r
223 printf("Unit: %s\n", fmi1_import_get_unit_name(u));
\r
226 printf("Display unit: %s, gain: %g, offset: %g, is relative: %s",
\r
227 fmi1_import_get_display_unit_name(du),
\r
228 fmi1_import_get_display_unit_gain(du),
\r
229 fmi1_import_get_display_unit_offset(du),
\r
230 fmi1_import_get_real_type_is_relative_quantity(rt)?"yes":"no"
\r
236 case fmi1_base_type_int:{
\r
237 fmi1_import_integer_typedef_t* it = fmi1_import_get_type_as_int(vt);
\r
238 int min = fmi1_import_get_integer_type_min(it);
\r
239 int max = fmi1_import_get_integer_type_max(it);
\r
240 printf("Min %d, max %d\n", min, max);
\r
243 case fmi1_base_type_bool:{
\r
246 case fmi1_base_type_str:{
\r
249 case fmi1_base_type_enum:{
\r
250 fmi1_import_enumeration_typedef_t* et = fmi1_import_get_type_as_enum(vt);
\r
251 int min = fmi1_import_get_enum_type_min(et);
\r
252 int max = fmi1_import_get_enum_type_max(et);
\r
253 printf("Min %d, max %d\n", min, max);
\r
257 ni = fmi1_import_get_enum_type_size(et);
\r
258 i = (unsigned)(ni);
\r
260 printf("There are %u items \n",(unsigned)ni);
\r
261 for(i = 0; i < ni; i++) {
\r
262 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));
\r
268 printf("Error in fmiGetBaseType()\n");
\r
273 FMIL_Variable *FMI1_CS_GET_VARIABLES(void *fmu, int *count) {
\r
276 FMIL_Variable *result;
\r
277 fmi1_import_variable_list_t* vl = fmi1_import_get_variable_list((fmi1_import_t *)fmu);
\r
278 fmi1_import_variable_typedef_t* type;
\r
280 count[0] = fmi1_import_get_variable_list_size(vl);
\r
282 result = (FMIL_Variable *)malloc(count[0]*sizeof(FMIL_Variable));
\r
284 for(i = 0; i < count[0]; i++) {
\r
286 fmi1_import_variable_t* var = fmi1_import_get_variable(vl, i);
\r
289 printf("Something wrong with variable %d \n",i);
\r
294 result[i].name = fmi1_import_get_variable_name(var);
\r
295 result[i].description = fmi1_import_get_variable_description(var);
\r
297 switch (fmi1_import_get_variability(var)) {
\r
298 case fmi1_variability_enu_constant:
\r
299 result[i].variability = 0;
\r
301 case fmi1_variability_enu_parameter:
\r
302 result[i].variability = 1;
\r
304 case fmi1_variability_enu_discrete:
\r
305 result[i].variability = 2;
\r
307 case fmi1_variability_enu_continuous:
\r
308 result[i].variability = 3;
\r
310 case fmi1_variability_enu_unknown:
\r
311 result[i].variability = 4;
\r
315 switch (fmi1_import_get_causality(var)) {
\r
316 case fmi1_causality_enu_input:
\r
317 result[i].causality = 0;
\r
319 case fmi1_causality_enu_output:
\r
320 result[i].causality = 1;
\r
322 case fmi1_causality_enu_internal:
\r
323 result[i].causality = 2;
\r
325 case fmi1_causality_enu_none:
\r
326 result[i].causality = 3;
\r
328 case fmi1_causality_enu_unknown:
\r
329 result[i].causality = 4;
\r
333 switch (fmi1_import_get_variable_base_type(var)) {
\r
334 case fmi1_base_type_real:
\r
335 result[i].type = 0;
\r
337 case fmi1_base_type_int:
\r
338 result[i].type = 1;
\r
340 case fmi1_base_type_bool:
\r
341 result[i].type = 2;
\r
343 case fmi1_base_type_str:
\r
344 result[i].type = 3;
\r
346 case fmi1_base_type_enum:
\r
347 result[i].type = 4;
\r
351 result[i].vr = fmi1_import_get_variable_vr(var);
\r
353 type = fmi1_import_get_variable_declared_type(var);
\r
355 result[i].declaredType = fmi1_import_get_type_name(type);
\r
357 result[i].declaredType = 0;
\r
364 fmi1_import_free_variable_list(vl);
\r
370 FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void *fmu, int *count) {
\r
372 FMIL_DeclaredType *result;
\r
373 fmi1_import_type_definitions_t* td = fmi1_import_get_type_definitions((fmi1_import_t *)fmu);
\r
374 fmi1_import_variable_typedef_t* type;
\r
375 unsigned i, ntd = (unsigned)fmi1_import_get_type_definition_number(td);
\r
379 result = (FMIL_DeclaredType *)malloc(count[0]*sizeof(FMIL_DeclaredType));
\r
381 for(i = 0; i < ntd; i++) {
\r
382 type = fmi1_import_get_typedef(td, i);
\r
383 result[i].name = fmi1_import_get_type_name(type);
\r
384 result[i].description = fmi1_import_get_type_description(type);
\r
385 result[i].quantity = fmi1_import_get_type_quantity(type);
\r
386 result[i].unit = 0;
\r
388 switch(fmi1_import_get_base_type(type)) {
\r
389 case fmi1_base_type_real: {
\r
390 fmi1_import_real_typedef_t* rt = fmi1_import_get_type_as_real(type);
\r
391 fmi1_import_unit_t* u = fmi1_import_get_real_type_unit(rt);
\r
392 if(u) result[i].unit = fmi1_import_get_unit_name(u);
\r
402 #define INSTANCE_NAME "kekkeli"
\r
404 int FMI1_CS_INSTANTIATE(void *fmu) {
\r
406 fmi1_string_t fmuLocation;
\r
407 fmi1_string_t mimeType;
\r
408 fmi1_real_t timeout;
\r
409 fmi1_boolean_t visible;
\r
410 fmi1_boolean_t interactive;
\r
411 fmi1_boolean_t loggingOn;
\r
416 visible = fmi1_false;
\r
417 interactive = fmi1_false;
\r
418 loggingOn = fmi1_true;
\r
420 if (fmi1_import_instantiate_slave(fmu, INSTANCE_NAME, NULL, NULL, timeout, fmi1_false, fmi1_false) == NULL) {
\r
421 printf("fmi1_capi_instantiate_slave: Failed\n");
\r
424 printf("fmi1_capi_instantiate_slave: Success\n");
\r
430 int FMI1_CS_INITIALIZE(void *fmu) {
\r
432 fmi1_status_t status;
\r
433 fmi1_real_t tStart;
\r
435 fmi1_boolean_t StopTimeDefined;
\r
439 StopTimeDefined = fmi1_false;
\r
441 status = fmi1_import_initialize_slave((fmi1_import_t *)fmu, tStart, StopTimeDefined, tStop);
\r
442 if (status == fmi1_status_error || status == fmi1_status_fatal) {
\r
443 printf("fmi1_capi_initialize_slave: Failed\n");
\r
446 printf("fmi1_capi_initialize_slave: Success\n");
\r
452 int FMI1_CS_STEP(void *fmu, double masterTime, double stepSize) {
\r
454 fmi1_status_t status;
\r
456 status = fmi1_import_do_step((fmi1_import_t *)fmu, (fmi1_real_t)masterTime, (fmi1_real_t)stepSize, fmi1_true);
\r
457 if (status == fmi1_status_error || status == fmi1_status_fatal) {
\r
464 int FMI1_CS_SET_REAL(void *fmu, long valueId, double value) {
\r
466 fmi1_value_reference_t vr = valueId;
\r
467 fmi1_import_set_real((fmi1_import_t *)fmu, &vr, 1, &value);
\r
473 double FMI1_CS_GET_REAL(void *fmu, int valueReference) {
\r
475 fmi1_value_reference_t vr = valueReference;
\r
477 fmi1_import_get_real((fmi1_import_t *)fmu, &vr, 1, &value);
\r
482 int FMI1_CS_GET_REALS(void *fmu, int *valueReferences, double *result, int count) {
\r
484 fmi1_value_reference_t *vrs = valueReferences;
\r
486 fmi1_import_get_real((fmi1_import_t *)fmu, vrs, count, result);
\r