]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/native/FMUSimulator/fmi_util.c.txt
Renamed org.simantics.fmil to org.simantics.fmil.core to prevent having bundles and...
[simantics/fmil.git] / org.simantics.fmil.core / native / FMUSimulator / fmi_util.c.txt
1 /*\r
2     Copyright (C) 2012 Modelon AB\r
3 \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
6 \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
11 \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
14 */\r
15 \r
16 #include <assert.h>\r
17 #include <string.h>\r
18 #include <stdio.h>\r
19 #include <FMI/fmi_util.h>\r
20 #include <FMI/fmi_zip_unzip.h>\r
21 \r
22 char* fmi_construct_dll_dir_name(jm_callbacks* callbacks, const char* fmu_unzipped_path) {\r
23         char* dir_path;\r
24         size_t len;\r
25 \r
26         assert( fmu_unzipped_path && callbacks);\r
27 \r
28         len = \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
32 \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
36                 return NULL;\r
37         }\r
38 \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
40 \r
41         return dir_path;\r
42 }\r
43 \r
44 char* fmi_construct_dll_file_name(jm_callbacks* callbacks, const char* dll_dir_name, const char* model_identifier) {\r
45         char* fname;\r
46         size_t len;\r
47         assert(callbacks && model_identifier);\r
48         len = \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
55                 return NULL;\r
56         }\r
57         sprintf(fname, "%s%s%s", dll_dir_name, model_identifier, FMI_DLL_EXT);/*safe */\r
58 \r
59         return fname;\r
60 }\r
61 \r
62 \r
63 ////\r
64 \r
65 #include <stdio.h>\r
66 #include <stdlib.h>\r
67 #include <stdarg.h>\r
68 #include <string.h>\r
69 #include <errno.h>\r
70 \r
71 #include <fmilib.h>\r
72 \r
73 #ifdef __cplusplus\r
74 extern "C" {\r
75 #endif\r
76 \r
77 typedef struct {\r
78         char *name;\r
79         char *description;\r
80         char *declaredType;\r
81         long vr;\r
82         // 0 = real\r
83         // 1 = integer\r
84         // 2 = boolean\r
85         // 3 = string\r
86         // 4 = enumeration\r
87         int type;\r
88         // 0 = constant\r
89         // 1 = parameter\r
90         // 2 = discrete\r
91         // 3 = continuous\r
92         // 4 = unknown\r
93         int variability;\r
94         // 0 = input\r
95         // 1 = output\r
96         // 2 = internal\r
97         // 3 = none\r
98         // 4 = unknown\r
99         int causality;\r
100 } FMIL_Variable;\r
101 \r
102 typedef struct {\r
103         char *name;\r
104         char *description;\r
105         char *quantity;\r
106         char *unit;\r
107 } FMIL_DeclaredType;\r
108 \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
119 \r
120 #ifdef __cplusplus\r
121 }\r
122 #endif\r
123 \r
124 #define BUFFER 4096\r
125 \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
128 {\r
129         printf("module = %s, log level = %d: %s\n", module, log_level, message);\r
130 }\r
131 \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
134 {\r
135         char msg[BUFFER];\r
136     int len;\r
137         va_list argp;   \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
141     if(len > BUFFER) {\r
142         printf("Warning: message was trancated");\r
143     }*/\r
144 }\r
145 \r
146 void *FMI1_CS_LOAD(char *zipFilePath, char *unzipFolder) {\r
147 \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
155 \r
156         callbacks = (jm_callbacks *)calloc(1, sizeof(jm_callbacks));\r
157 \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
165 \r
166         callBackFunctions.logger = fmilogger;\r
167         callBackFunctions.allocateMemory = calloc;\r
168         callBackFunctions.freeMemory = free;\r
169 \r
170         context = fmi_import_allocate_context(callbacks);\r
171 \r
172         version = fmi_import_get_fmi_version(context, zipFilePath, unzipFolder);\r
173 \r
174         fmu = fmi1_import_parse_xml(context, unzipFolder);\r
175 \r
176         status = fmi1_import_create_dllfmu(fmu, callBackFunctions, 0);\r
177 \r
178         fmi_import_free_context(context);\r
179 \r
180         return fmu;\r
181 \r
182 }\r
183 \r
184 int FMI1_CS_UNLOAD(void *fmu_) {\r
185 \r
186         fmi1_import_t *fmu = (fmi1_import_t *)fmu_;\r
187 \r
188         fmi1_import_destroy_dllfmu(fmu);\r
189 \r
190         fmi1_import_free(fmu);\r
191 \r
192         return 1;\r
193 \r
194 }\r
195 \r
196 /*\r
197  if(!vt) {\r
198         printf("No type definition\n");\r
199         return;\r
200     }\r
201 \r
202     quan = fmi1_import_get_type_quantity(vt);\r
203 \r
204     printf("Type %s\n description: %s\n",  fmi1_import_get_type_name(vt), fmi1_import_get_type_description(vt));\r
205 \r
206     printf("Base type: %s\n", fmi1_base_type_to_string(fmi1_import_get_base_type(vt)));\r
207 \r
208     if(quan) {\r
209         printf("Quantity: %s\n", quan);\r
210     }\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
219 \r
220         printf("Min %g, max %g, nominal %g\n", min, max, nom);\r
221 \r
222         if(u) {\r
223             printf("Unit: %s\n", fmi1_import_get_unit_name(u));\r
224         }\r
225         if(du) {\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
231                    );\r
232         }\r
233 \r
234         break;\r
235     }\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
241         break;\r
242     }\r
243     case fmi1_base_type_bool:{\r
244         break;\r
245     }\r
246     case fmi1_base_type_str:{\r
247         break;\r
248     }\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
254         {\r
255             size_t ni;\r
256                         unsigned i;\r
257             ni = fmi1_import_get_enum_type_size(et);\r
258                         i = (unsigned)(ni);\r
259                         assert( i == 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
263             }\r
264         }\r
265         break;\r
266     }\r
267     default:\r
268         printf("Error in fmiGetBaseType()\n");\r
269     }\r
270 */\r
271 \r
272 \r
273 FMIL_Variable *FMI1_CS_GET_VARIABLES(void *fmu, int *count) {\r
274 \r
275     int i;\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
279 \r
280     count[0] = fmi1_import_get_variable_list_size(vl);\r
281 \r
282         result = (FMIL_Variable *)malloc(count[0]*sizeof(FMIL_Variable));\r
283 \r
284     for(i = 0; i < count[0]; i++) {\r
285 \r
286         fmi1_import_variable_t* var = fmi1_import_get_variable(vl, i);\r
287         if(!var) {\r
288 \r
289                         printf("Something wrong with variable %d \n",i);\r
290                         return 0;\r
291 \r
292                 } else {\r
293 \r
294                         result[i].name = fmi1_import_get_variable_name(var);\r
295                         result[i].description = fmi1_import_get_variable_description(var);\r
296 \r
297                         switch  (fmi1_import_get_variability(var)) {\r
298                         case fmi1_variability_enu_constant:\r
299                                 result[i].variability = 0;\r
300                                 break;\r
301                         case fmi1_variability_enu_parameter:\r
302                                 result[i].variability = 1;\r
303                                 break;\r
304                         case fmi1_variability_enu_discrete:\r
305                                 result[i].variability = 2;\r
306                                 break;\r
307                         case fmi1_variability_enu_continuous:\r
308                                 result[i].variability = 3;\r
309                                 break;\r
310                         case fmi1_variability_enu_unknown:\r
311                                 result[i].variability = 4;\r
312                                 break;\r
313                         }\r
314 \r
315                         switch  (fmi1_import_get_causality(var)) {\r
316                         case fmi1_causality_enu_input:\r
317                                 result[i].causality = 0;\r
318                                 break;\r
319                         case fmi1_causality_enu_output:\r
320                                 result[i].causality = 1;\r
321                                 break;\r
322                         case fmi1_causality_enu_internal:\r
323                                 result[i].causality = 2;\r
324                                 break;\r
325                         case fmi1_causality_enu_none:\r
326                                 result[i].causality = 3;\r
327                                 break;\r
328                         case fmi1_causality_enu_unknown:\r
329                                 result[i].causality = 4;\r
330                                 break;\r
331                         }\r
332 \r
333                         switch  (fmi1_import_get_variable_base_type(var)) {\r
334                         case fmi1_base_type_real:\r
335                                 result[i].type = 0;\r
336                                 break;\r
337                         case fmi1_base_type_int:\r
338                                 result[i].type = 1;\r
339                                 break;\r
340                         case fmi1_base_type_bool:\r
341                                 result[i].type = 2;\r
342                                 break;\r
343                         case fmi1_base_type_str:\r
344                                 result[i].type = 3;\r
345                                 break;\r
346                         case fmi1_base_type_enum:\r
347                                 result[i].type = 4;\r
348                                 break;\r
349                         }\r
350                         \r
351                         result[i].vr = fmi1_import_get_variable_vr(var);\r
352 \r
353                         type = fmi1_import_get_variable_declared_type(var);\r
354                         if(type) {\r
355                                 result[i].declaredType = fmi1_import_get_type_name(type);\r
356                         } else {\r
357                                 result[i].declaredType = 0;\r
358                         }\r
359 \r
360                 }\r
361 \r
362     }\r
363 \r
364     fmi1_import_free_variable_list(vl);\r
365 \r
366         return result;\r
367 \r
368 }\r
369 \r
370 FMIL_DeclaredType *FMI1_CS_GET_DECLARED_TYPES(void *fmu, int *count) {\r
371 \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
376 \r
377     count[0] = ntd;\r
378 \r
379         result = (FMIL_DeclaredType *)malloc(count[0]*sizeof(FMIL_DeclaredType));\r
380 \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
387 \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
393                    }\r
394           }\r
395 \r
396     }\r
397 \r
398         return result;\r
399 \r
400 }\r
401 \r
402 #define INSTANCE_NAME           "kekkeli"\r
403 \r
404 int FMI1_CS_INSTANTIATE(void *fmu) {\r
405 \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
412 \r
413         fmuLocation = "";\r
414         mimeType = "";\r
415         timeout = 0;\r
416         visible = fmi1_false;\r
417         interactive = fmi1_false;\r
418         loggingOn = fmi1_true;\r
419 \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
422                 return 0;\r
423         } else {\r
424                 printf("fmi1_capi_instantiate_slave:             Success\n");\r
425         }\r
426         return 0;\r
427 \r
428 }\r
429 \r
430 int FMI1_CS_INITIALIZE(void *fmu) {\r
431 \r
432         fmi1_status_t status;\r
433         fmi1_real_t tStart;\r
434         fmi1_real_t tStop;\r
435         fmi1_boolean_t StopTimeDefined;\r
436 \r
437         tStart = 0;\r
438         tStop = 10;\r
439         StopTimeDefined = fmi1_false;\r
440 \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
444                 return 0;\r
445         } else {\r
446                 printf("fmi1_capi_initialize_slave:              Success\n");\r
447         }\r
448         return 0;\r
449 \r
450 }\r
451 \r
452 int FMI1_CS_STEP(void *fmu, double masterTime, double stepSize) {\r
453 \r
454     fmi1_status_t status;\r
455 \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
458                 return 1;\r
459         } else {\r
460                 return 0;\r
461         }\r
462 }\r
463 \r
464 int FMI1_CS_SET_REAL(void *fmu, long valueId, double value) {\r
465 \r
466         fmi1_value_reference_t vr = valueId;\r
467         fmi1_import_set_real((fmi1_import_t *)fmu, &vr, 1, &value);\r
468 \r
469         return 0;\r
470 \r
471 }\r
472 \r
473 double FMI1_CS_GET_REAL(void *fmu, int valueReference) {\r
474 \r
475         fmi1_value_reference_t vr = valueReference;\r
476         fmi1_real_t value;\r
477         fmi1_import_get_real((fmi1_import_t *)fmu, &vr, 1, &value);\r
478         return value;\r
479 \r
480 }\r
481 \r
482 int FMI1_CS_GET_REALS(void *fmu, int *valueReferences, double *result, int count) {\r
483 \r
484         fmi1_value_reference_t *vrs = valueReferences;\r
485         fmi1_real_t value;\r
486         fmi1_import_get_real((fmi1_import_t *)fmu, vrs, count, result);\r
487         return 1;\r
488 \r
489 }\r