/* ------------------------------------------------------------------------- * sim_support.c * Functions used by both FMU simulators fmu20sim_me and fmu20sim_cs * to parse command-line arguments, to unzip and load an fmu, * to write CSV file, and more. * * Revision history * 07.03.2014 initial version released in FMU SDK 2.0.0 * 10.04.2014 use FMI 2.0 headers that prefix function and type names with 'fmi2'. * When 'fmi2' functions are not found in loaded DLL, look also for * FMI 2.0 RC1 function names. * * Author: Adrian Tirea * Copyright QTronic GmbH. All rights reserved. * -------------------------------------------------------------------------*/ #include #include #include #include #include #include #include "fmi2.h" #include "sim_support.h" #define FMI_COSIMULATION extern FMU fmu; //int unzip(const char *zipPath, const char *outPath) { // int code; // char cwd[BUFSIZE]; // char binPath[BUFSIZE]; // int n = strlen(UNZIP_CMD) + strlen(outPath) + 3 + strlen(zipPath) + 9; // char* cmd = (char*)calloc(sizeof(char), n); // // // remember current directory // if (!GetCurrentDirectory(BUFSIZE, cwd)) { // printf ("error: Could not get current directory\n"); // return 0; // error // } // // // change to %FMUSDK_HOME%\bin to find 7z.dll and 7z.exe // if (!GetEnvironmentVariable("FMUSDK_HOME", binPath, BUFSIZE)) { // if (GetLastError() == ERROR_ENVVAR_NOT_FOUND) { // printf ("error: Environment variable FMUSDK_HOME not defined\n"); // } // else { // printf ("error: Could not get value of FMUSDK_HOME\n"); // } // return 0; // error // } // strcat(binPath, "\\bin"); // if (!SetCurrentDirectory(binPath)) { // printf ("error: could not change to directory '%s'\n", binPath); // return 0; // error // } // // // run the unzip command // // remove "> NUL" to see the unzip protocol // sprintf(cmd, "%s\"%s\" \"%s\" > NUL", UNZIP_CMD, outPath, zipPath); // // printf("cmd='%s'\n", cmd); // code = system(cmd); // free(cmd); // if (code != SEVEN_ZIP_NO_ERROR) { // printf("7z: "); // switch (code) { // case SEVEN_ZIP_WARNING: printf("warning\n"); break; // case SEVEN_ZIP_ERROR: printf("error\n"); break; // case SEVEN_ZIP_COMMAND_LINE_ERROR: printf("command line error\n"); break; // case SEVEN_ZIP_OUT_OF_MEMORY: printf("out of memory\n"); break; // case SEVEN_ZIP_STOPPED_BY_USER: printf("stopped by user\n"); break; // default: printf("unknown problem\n"); // } // } // // // restore current directory // SetCurrentDirectory(cwd); // return (code == SEVEN_ZIP_NO_ERROR || code == SEVEN_ZIP_WARNING) ? 1 : 0; //} // //// fileName is an absolute path, e.g. C:\test\a.fmu //// or relative to the current dir, e.g. ..\test\a.fmu //// Does not check for existence of the file //static char* getFmuPath(const char* fileName){ // char pathName[MAX_PATH]; // int n = GetFullPathName(fileName, MAX_PATH, pathName, NULL); // return n ? strdup(pathName) : NULL; //} // //static char* getTmpPath() { // char tmpPath[BUFSIZE]; // if(! GetTempPath(BUFSIZE, tmpPath)) { // printf ("error: Could not find temporary disk space\n"); // return NULL; // } // strcat(tmpPath, "fmu\\"); // return strdup(tmpPath); //} // //char *getTempResourcesLocation() { // char *tempPath = getTmpPath(); // char *resourcesLocation = (char *)calloc(sizeof(char), 9 + strlen(RESOURCES_DIR) + strlen(tempPath)); // strcpy(resourcesLocation, "file:///"); // strcat(resourcesLocation, tempPath); // strcat(resourcesLocation, RESOURCES_DIR); // free(tempPath); // return resourcesLocation; //} static void *getAdr(int *success, void *dllHandle, const char *functionName, const char* preamble) { int length = strlen(preamble) + strlen(functionName) + 1; char* new_name = malloc(length); // allocate memory strcpy(new_name, preamble); // copy first string strcat(new_name, functionName); void* fp = dlsym(dllHandle, new_name); if (!fp) { printf("warning: Function %s not found in dll\n", new_name); *success = 0; } free(new_name); return fp; } // Load the given dll and set function pointers in fmu // Return 0 to indicate failure int loadDll(const char* dllPath, FMU *fmu, const char* preamble) { int x = 1, s = 1; //HMODULE h = LoadLibrary(dllPath); void *h = dlopen(dllPath, RTLD_LAZY); printf("%s", dlerror()); if (!h) { printf("error: Could not load %s\n", dllPath); return 0; // failure } fmu->dllHandle = h; fmu->getTypesPlatform = (fmi2GetTypesPlatformTYPE *) getAdr(&s, h, "fmi2GetTypesPlatform", preamble); fmu->getVersion = (fmi2GetVersionTYPE *) getAdr(&s, h, "fmi2GetVersion", preamble); fmu->setDebugLogging = (fmi2SetDebugLoggingTYPE *) getAdr(&s, h, "fmi2SetDebugLogging",preamble); fmu->instantiate = (fmi2InstantiateTYPE *) getAdr(&s, h, "fmi2Instantiate", preamble); fmu->freeInstance = (fmi2FreeInstanceTYPE *) getAdr(&s, h, "fmi2FreeInstance", preamble); fmu->setupExperiment = (fmi2SetupExperimentTYPE *) getAdr(&s, h, "fmi2SetupExperiment", preamble); fmu->enterInitializationMode = (fmi2EnterInitializationModeTYPE *) getAdr(&s, h, "fmi2EnterInitializationMode", preamble); fmu->exitInitializationMode = (fmi2ExitInitializationModeTYPE *) getAdr(&s, h, "fmi2ExitInitializationMode", preamble); fmu->terminate = (fmi2TerminateTYPE *) getAdr(&s, h, "fmi2Terminate", preamble); fmu->reset = (fmi2ResetTYPE *) getAdr(&s, h, "fmi2Reset", preamble); fmu->getReal = (fmi2GetRealTYPE *) getAdr(&s, h, "fmi2GetReal", preamble); fmu->getInteger = (fmi2GetIntegerTYPE *) getAdr(&s, h, "fmi2GetInteger", preamble); fmu->getBoolean = (fmi2GetBooleanTYPE *) getAdr(&s, h, "fmi2GetBoolean", preamble); fmu->getString = (fmi2GetStringTYPE *) getAdr(&s, h, "fmi2GetString", preamble); fmu->setReal = (fmi2SetRealTYPE *) getAdr(&s, h, "fmi2SetReal", preamble); fmu->setInteger = (fmi2SetIntegerTYPE *) getAdr(&s, h, "fmi2SetInteger", preamble); fmu->setBoolean = (fmi2SetBooleanTYPE *) getAdr(&s, h, "fmi2SetBoolean", preamble); fmu->setString = (fmi2SetStringTYPE *) getAdr(&s, h, "fmi2SetString", preamble); fmu->getFMUstate = (fmi2GetFMUstateTYPE *) getAdr(&s, h, "fmi2GetFMUstate", preamble); fmu->setFMUstate = (fmi2SetFMUstateTYPE *) getAdr(&s, h, "fmi2SetFMUstate", preamble); fmu->freeFMUstate = (fmi2FreeFMUstateTYPE *) getAdr(&s, h, "fmi2FreeFMUstate", preamble); fmu->serializedFMUstateSize = (fmi2SerializedFMUstateSizeTYPE *) getAdr(&s, h, "fmi2SerializedFMUstateSize", preamble); fmu->serializeFMUstate = (fmi2SerializeFMUstateTYPE *) getAdr(&s, h, "fmi2SerializeFMUstate", preamble); fmu->deSerializeFMUstate = (fmi2DeSerializeFMUstateTYPE *) getAdr(&s, h, "fmi2DeSerializeFMUstate", preamble); fmu->getDirectionalDerivative = (fmi2GetDirectionalDerivativeTYPE *) getAdr(&s, h, "fmi2GetDirectionalDerivative", preamble); #ifdef FMI_COSIMULATION fmu->setRealInputDerivatives = (fmi2SetRealInputDerivativesTYPE *) getAdr(&s, h, "fmi2SetRealInputDerivatives", preamble); fmu->getRealOutputDerivatives = (fmi2GetRealOutputDerivativesTYPE *) getAdr(&s, h, "fmi2GetRealOutputDerivatives", preamble); fmu->doStep = (fmi2DoStepTYPE *) getAdr(&s, h, "fmi2DoStep", preamble); fmu->cancelStep = (fmi2CancelStepTYPE *) getAdr(&s, h, "fmi2CancelStep", preamble); fmu->getStatus = (fmi2GetStatusTYPE *) getAdr(&s, h, "fmi2GetStatus", preamble); fmu->getRealStatus = (fmi2GetRealStatusTYPE *) getAdr(&s, h, "fmi2GetRealStatus", preamble); fmu->getIntegerStatus = (fmi2GetIntegerStatusTYPE *) getAdr(&s, h, "fmi2GetIntegerStatus", preamble); fmu->getBooleanStatus = (fmi2GetBooleanStatusTYPE *) getAdr(&s, h, "fmi2GetBooleanStatus", preamble); fmu->getStringStatus = (fmi2GetStringStatusTYPE *) getAdr(&s, h, "fmi2GetStringStatus", preamble); #else // FMI2 for Model Exchange fmu->enterEventMode = (fmi2EnterEventModeTYPE *) getAdr(&s, h, "fmi2EnterEventMode", preamble); fmu->newDiscreteStates = (fmi2NewDiscreteStatesTYPE *) getAdr(&s, h, "fmi2NewDiscreteStates", preamble); fmu->enterContinuousTimeMode = (fmi2EnterContinuousTimeModeTYPE *) getAdr(&s, h, "fmi2EnterContinuousTimeMode", preamble); fmu->completedIntegratorStep = (fmi2CompletedIntegratorStepTYPE *) getAdr(&s, h, "fmi2CompletedIntegratorStep", preamble); fmu->setTime = (fmi2SetTimeTYPE *) getAdr(&s, h, "fmi2SetTime", preamble); fmu->setContinuousStates = (fmi2SetContinuousStatesTYPE *) getAdr(&s, h, "fmi2SetContinuousStates", preamble); fmu->getDerivatives = (fmi2GetDerivativesTYPE *) getAdr(&s, h, "fmi2GetDerivatives", preamble); fmu->getEventIndicators = (fmi2GetEventIndicatorsTYPE *) getAdr(&s, h, "fmi2GetEventIndicators", preamble); fmu->getContinuousStates = (fmi2GetContinuousStatesTYPE *) getAdr(&s, h, "fmi2GetContinuousStates", preamble); fmu->getNominalsOfContinuousStates = (fmi2GetNominalsOfContinuousStatesTYPE *) getAdr(&s, h, "fmi2GetNominalsOfContinuousStates", preamble); #endif if (fmu->getVersion == NULL && fmu->instantiate == NULL) { printf("warning: Functions from FMI 2.0 could not be found in %s\n", dllPath); printf("warning: Simulator will look for FMI 2.0 RC1 functions names...\n"); fmu->getTypesPlatform = (fmi2GetTypesPlatformTYPE *) getAdr(&s, h, "fmiGetTypesPlatform", preamble); fmu->getVersion = (fmi2GetVersionTYPE *) getAdr(&s, h, "fmiGetVersion", preamble); fmu->setDebugLogging = (fmi2SetDebugLoggingTYPE *) getAdr(&s, h, "fmiSetDebugLogging", preamble); fmu->instantiate = (fmi2InstantiateTYPE *) getAdr(&s, h, "fmiInstantiate", preamble); fmu->freeInstance = (fmi2FreeInstanceTYPE *) getAdr(&s, h, "fmiFreeInstance", preamble); fmu->setupExperiment = (fmi2SetupExperimentTYPE *) getAdr(&s, h, "fmiSetupExperiment", preamble); fmu->enterInitializationMode = (fmi2EnterInitializationModeTYPE *) getAdr(&s, h, "fmiEnterInitializationMode", preamble); fmu->exitInitializationMode = (fmi2ExitInitializationModeTYPE *) getAdr(&s, h, "fmiExitInitializationMode", preamble); fmu->terminate = (fmi2TerminateTYPE *) getAdr(&s, h, "fmiTerminate", preamble); fmu->reset = (fmi2ResetTYPE *) getAdr(&s, h, "fmiReset", preamble); fmu->getReal = (fmi2GetRealTYPE *) getAdr(&s, h, "fmiGetReal", preamble); fmu->getInteger = (fmi2GetIntegerTYPE *) getAdr(&s, h, "fmiGetInteger", preamble); fmu->getBoolean = (fmi2GetBooleanTYPE *) getAdr(&s, h, "fmiGetBoolean", preamble); fmu->getString = (fmi2GetStringTYPE *) getAdr(&s, h, "fmiGetString", preamble); fmu->setReal = (fmi2SetRealTYPE *) getAdr(&s, h, "fmiSetReal", preamble); fmu->setInteger = (fmi2SetIntegerTYPE *) getAdr(&s, h, "fmiSetInteger", preamble); fmu->setBoolean = (fmi2SetBooleanTYPE *) getAdr(&s, h, "fmiSetBoolean", preamble); fmu->setString = (fmi2SetStringTYPE *) getAdr(&s, h, "fmiSetString", preamble); fmu->getFMUstate = (fmi2GetFMUstateTYPE *) getAdr(&s, h, "fmiGetFMUstate", preamble); fmu->setFMUstate = (fmi2SetFMUstateTYPE *) getAdr(&s, h, "fmiSetFMUstate", preamble); fmu->freeFMUstate = (fmi2FreeFMUstateTYPE *) getAdr(&s, h, "fmiFreeFMUstate", preamble); fmu->serializedFMUstateSize = (fmi2SerializedFMUstateSizeTYPE *) getAdr(&s, h, "fmiSerializedFMUstateSize", preamble); fmu->serializeFMUstate = (fmi2SerializeFMUstateTYPE *) getAdr(&s, h, "fmiSerializeFMUstate", preamble); fmu->deSerializeFMUstate = (fmi2DeSerializeFMUstateTYPE *) getAdr(&s, h, "fmiDeSerializeFMUstate", preamble); fmu->getDirectionalDerivative = (fmi2GetDirectionalDerivativeTYPE *) getAdr(&s, h, "fmiGetDirectionalDerivative", preamble); #ifdef FMI_COSIMULATION fmu->setRealInputDerivatives = (fmi2SetRealInputDerivativesTYPE *) getAdr(&s, h, "fmiSetRealInputDerivatives", preamble); fmu->getRealOutputDerivatives = (fmi2GetRealOutputDerivativesTYPE *) getAdr(&s, h, "fmiGetRealOutputDerivatives", preamble); fmu->doStep = (fmi2DoStepTYPE *) getAdr(&s, h, "fmiDoStep", preamble); fmu->cancelStep = (fmi2CancelStepTYPE *) getAdr(&s, h, "fmiCancelStep", preamble); fmu->getStatus = (fmi2GetStatusTYPE *) getAdr(&s, h, "fmiGetStatus", preamble); fmu->getRealStatus = (fmi2GetRealStatusTYPE *) getAdr(&s, h, "fmiGetRealStatus", preamble); fmu->getIntegerStatus = (fmi2GetIntegerStatusTYPE *) getAdr(&s, h, "fmiGetIntegerStatus", preamble); fmu->getBooleanStatus = (fmi2GetBooleanStatusTYPE *) getAdr(&s, h, "fmiGetBooleanStatus", preamble); fmu->getStringStatus = (fmi2GetStringStatusTYPE *) getAdr(&s, h, "fmiGetStringStatus", preamble); #else // FMI2 for Model Exchange fmu->enterEventMode = (fmi2EnterEventModeTYPE *) getAdr(&s, h, "fmiEnterEventMode", preamble); fmu->newDiscreteStates = (fmi2NewDiscreteStatesTYPE *) getAdr(&s, h, "fmiNewDiscreteStates", preamble); fmu->enterContinuousTimeMode = (fmi2EnterContinuousTimeModeTYPE *) getAdr(&s, h, "fmiEnterContinuousTimeMode", preamble); fmu->completedIntegratorStep = (fmi2CompletedIntegratorStepTYPE *) getAdr(&s, h, "fmiCompletedIntegratorStep", preamble); fmu->setTime = (fmi2SetTimeTYPE *) getAdr(&s, h, "fmiSetTime", preamble); fmu->setContinuousStates = (fmi2SetContinuousStatesTYPE *) getAdr(&s, h, "fmiSetContinuousStates", preamble); fmu->getDerivatives = (fmi2GetDerivativesTYPE *) getAdr(&s, h, "fmiGetDerivatives", preamble); fmu->getEventIndicators = (fmi2GetEventIndicatorsTYPE *) getAdr(&s, h, "fmiGetEventIndicators", preamble); fmu->getContinuousStates = (fmi2GetContinuousStatesTYPE *) getAdr(&s, h, "fmiGetContinuousStates", preamble); fmu->getNominalsOfContinuousStates = (fmi2GetNominalsOfContinuousStatesTYPE *) getAdr(&s, h, "fmiGetNominalsOfContinuousStates", preamble); #endif } return s; } //static void printModelDescription(ModelDescription* md){ // Element* e = (Element*)md; // int i; // int n; // number of attributes // const char **attributes = getAttributesAsArray(e, &n); // Component *component; // // if (!attributes) { // printf("ModelDescription printing aborted."); // return; // } // printf("%s\n", getElementTypeName(e)); // for (i = 0; i < n; i += 2) { // printf(" %s=%s\n", attributes[i], attributes[i+1]); // } // free((void *)attributes); // //#ifdef FMI_COSIMULATION // component = getCoSimulation(md); // if (!component) { // printf("error: No CoSimulation element found in model description. This FMU is not for Co-Simulation.\n"); // exit(EXIT_FAILURE); // } //#else // FMI_MODEL_EXCHANGE // component = getModelExchange(md); // if (!component) { // printf("error: No ModelExchange element found in model description. This FMU is not for Model Exchange.\n"); // exit(EXIT_FAILURE); // } //#endif // printf("%s\n", getElementTypeName((Element *)component)); // attributes = getAttributesAsArray((Element *)component, &n); // if (!attributes) { // printf("ModelDescription printing aborted."); // return; // } // for (i = 0; i < n; i += 2) { // printf(" %s=%s\n", attributes[i], attributes[i+1]); // } // // free((void *)attributes); //} // //void loadFMU(const char* fmuFileName) { // char* fmuPath; // char* tmpPath; // char* xmlPath; // char* dllPath; // const char *modelId; // // // get absolute path to FMU, NULL if not found // fmuPath = getFmuPath(fmuFileName); // if (!fmuPath) exit(EXIT_FAILURE); // // // unzip the FMU to the tmpPath directory // tmpPath = getTmpPath(); // if (!unzip(fmuPath, tmpPath)) exit(EXIT_FAILURE); // // // parse tmpPath\modelDescription.xml // xmlPath = calloc(sizeof(char), strlen(tmpPath) + strlen(XML_FILE) + 1); // sprintf(xmlPath, "%s%s", tmpPath, XML_FILE); // fmu.modelDescription = parse(xmlPath); // free(xmlPath); // if (!fmu.modelDescription) exit(EXIT_FAILURE); // printModelDescription(fmu.modelDescription); //#ifdef FMI_COSIMULATION // modelId = getAttributeValue((Element *)getCoSimulation(fmu.modelDescription), att_modelIdentifier); //#else // FMI_MODEL_EXCHANGE // modelId = getAttributeValue((Element *)getModelExchange(fmu.modelDescription), att_modelIdentifier); //#endif // // load the FMU dll // dllPath = calloc(sizeof(char), strlen(tmpPath) + strlen(DLL_DIR) // + strlen(modelId) + strlen(".dll") + 1); // sprintf(dllPath, "%s%s%s.dll", tmpPath, DLL_DIR, modelId); // if (!loadDll(dllPath, &fmu)) { // exit(EXIT_FAILURE); // } // free(dllPath); // free(fmuPath); // free(tmpPath); //} // //void deleteUnzippedFiles() { // const char *fmuTempPath = getTmpPath(); // char *cmd = (char *)calloc(15 + strlen(fmuTempPath), sizeof(char)); // sprintf(cmd, "rmdir /S /Q %s", fmuTempPath); // system(cmd); // free(cmd); //} // //static void doubleToCommaString(char* buffer, double r){ // char* comma; // sprintf(buffer, "%.16g", r); // comma = strchr(buffer, '.'); // if (comma) *comma = ','; //} // //// output time and all variables in CSV format //// if separator is ',', columns are separated by ',' and '.' is used for floating-point numbers. //// otherwise, the given separator (e.g. ';' or '\t') is to separate columns, and ',' is used //// as decimal dot in floating-point numbers. //void outputRow(FMU *fmu, fmi2Component c, double time, FILE* file, char separator, fmi2Boolean header) { // int k; // fmi2Real r; // fmi2Integer i; // fmi2Boolean b; // fmi2String s; // fmi2ValueReference vr; // int n = getScalarVariableSize(fmu->modelDescription); // char buffer[32]; // // // print first column // if (header) { // fprintf(file, "time"); // } else { // if (separator==',') // fprintf(file, "%.16g", time); // else { // // separator is e.g. ';' or '\t' // doubleToCommaString(buffer, time); // fprintf(file, "%s", buffer); // } // } // // // print all other columns // for (k = 0; k < n; k++) { // ScalarVariable *sv = getScalarVariable(fmu->modelDescription, k); // if (header) { // // output names only // if (separator == ',') { // // treat array element, e.g. print a[1, 2] as a[1.2] // const char *s = getAttributeValue((Element *)sv, att_name); // fprintf(file, "%c", separator); // while (*s) { // if (*s != ' ') { // fprintf(file, "%c", *s == ',' ? '.' : *s); // } // s++; // } // } else { // fprintf(file, "%c%s", separator, getAttributeValue((Element *)sv, att_name)); // } // } else { // // output values // vr = getValueReference(sv); // switch (getElementType(getTypeSpec(sv))) { // case elm_Real: // fmu->getReal(c, &vr, 1, &r); // if (separator == ',') { // fprintf(file, ",%.16g", r); // } else { // // separator is e.g. ';' or '\t' // doubleToCommaString(buffer, r); // fprintf(file, "%c%s", separator, buffer); // } // break; // case elm_Integer: // case elm_Enumeration: // fmu->getInteger(c, &vr, 1, &i); // fprintf(file, "%c%d", separator, i); // break; // case elm_Boolean: // fmu->getBoolean(c, &vr, 1, &b); // fprintf(file, "%c%d", separator, b); // break; // case elm_String: // fmu->getString(c, &vr, 1, &s); // fprintf(file, "%c%s", separator, s); // break; // default: // fprintf(file, "%cNoValueForType=%d", separator, getElementType(getTypeSpec(sv))); // } // } // } // for // // // terminate this row // fprintf(file, "\n"); //} // static const char* fmi2StatusToString(fmi2Status status){ switch (status){ case fmi2OK: return "ok"; case fmi2Warning: return "warning"; case fmi2Discard: return "discard"; case fmi2Error: return "error"; case fmi2Fatal: return "fatal"; #ifdef FMI_COSIMULATION case fmi2Pending: return "fmi2Pending"; #endif default: return "?"; } } // search a fmu for the given variable, matching the type specified. // return NULL if not found //static ScalarVariable* getSV(FMU* fmu, char type, fmi2ValueReference vr) { // return NULL; // int i; // int n = getScalarVariableSize(fmu->modelDescription); // Elm tp; // // switch (type) { // case 'r': tp = elm_Real; break; // case 'i': tp = elm_Integer; break; // case 'b': tp = elm_Boolean; break; // case 's': tp = elm_String; break; // default : tp = elm_BAD_DEFINED; // } // for (i = 0; i < n; i++) { // ScalarVariable* sv = getScalarVariable(fmu->modelDescription ,i); // if (vr == getValueReference(sv) && tp == getElementType(getTypeSpec(sv))) { // return sv; // } // } // return NULL; //} // replace e.g. #r1365# by variable name and ## by # in message // copies the result to buffer static void replaceRefsInMessage(const char* msg, char* buffer, int nBuffer, FMU* fmu){ int i = 0; // position in msg int k = 0; // position in buffer int n; char c = msg[i]; while (c != '\0' && k < nBuffer) { if (c != '#') { buffer[k++] = c; i++; c = msg[i]; } else { char* end = strchr(msg + i + 1, '#'); if (!end) { printf("unmatched '#' in '%s'\n", msg); buffer[k++] = '#'; break; } n = end - (msg + i); if (n == 1) { // ## detected, output # buffer[k++] = '#'; i += 2; c = msg[i]; } else { char type = msg[i + 1]; // one of ribs fmi2ValueReference vr; int nvr = sscanf(msg + i + 2, "%u", &vr); if (nvr == 1) { // vr of type detected, e.g. #r12# //ScalarVariable* sv = getSV(fmu, type, vr); //const char* name = sv ? getAttributeValue((Element *)sv, att_name) : "?"; //sprintf(buffer + k, "%s", name); //k += strlen(name); //i += (n+1); //c = msg[i]; } else { // could not parse the number printf("illegal value reference at position %d in '%s'\n", i + 2, msg); buffer[k++] = '#'; break; } } } } // while buffer[k] = '\0'; } #define MAX_MSG_SIZE 1000 void fmuLogger(void *componentEnvironment, fmi2String instanceName, fmi2Status status, fmi2String category, fmi2String message, ...) { char msg[MAX_MSG_SIZE]; char* copy; va_list argp; // replace C format strings va_start(argp, message); vsprintf(msg, message, argp); va_end(argp); // replace e.g. ## and #r12# copy = strdup(msg); // replaceRefsInMessage(copy, msg, MAX_MSG_SIZE, NULL); free(copy); // print the final message if (!instanceName) instanceName = "?"; if (!category) category = "?"; printf("%s %s (%s): %s\n", fmi2StatusToString(status), instanceName, category, msg); } int error(const char* message){ printf("%s\n", message); return 0; } // //void parseArguments(int argc, char *argv[], const char **fmuFileName, double *tEnd, double *h, // int *loggingOn, char *csv_separator, int *nCategories, char **logCategories[]) { // // parse command line arguments // if (argc > 1) { // *fmuFileName = argv[1]; // } else { // printf("error: no fmu file\n"); // printHelp(argv[0]); // exit(EXIT_FAILURE); // } // if (argc > 2) { // if (sscanf(argv[2],"%lf", tEnd) != 1) { // printf("error: The given end time (%s) is not a number\n", argv[2]); // exit(EXIT_FAILURE); // } // } // if (argc > 3) { // if (sscanf(argv[3],"%lf", h) != 1) { // printf("error: The given stepsize (%s) is not a number\n", argv[3]); // exit(EXIT_FAILURE); // } // } // if (argc > 4) { // if (sscanf(argv[4],"%d", loggingOn) != 1 || *loggingOn < 0 || *loggingOn > 1) { // printf("error: The given logging flag (%s) is not boolean\n", argv[4]); // exit(EXIT_FAILURE); // } // } // if (argc > 5) { // if (strlen(argv[5]) != 1) { // printf("error: The given CSV separator char (%s) is not valid\n", argv[5]); // exit(EXIT_FAILURE); // } // switch (argv[5][0]) { // case 'c': *csv_separator = ','; break; // comma // case 's': *csv_separator = ';'; break; // semicolon // default: *csv_separator = argv[5][0]; break; // any other char // } // } // if (argc > 6) { // int i; // *nCategories = argc - 6; // *logCategories = (char **)calloc(sizeof(char *), *nCategories); // for (i = 0; i < *nCategories; i++) { // (*logCategories)[i] = argv[i + 6]; // } // } //} // //void printHelp(const char *fmusim) { // printf("command syntax: %s \n", fmusim); // printf(" .... path to FMU, relative to current dir or absolute, required\n"); // printf(" ......... end time of simulation, optional, defaults to 1.0 sec\n"); // printf(" ............ step size of simulation, optional, defaults to 0.1 sec\n"); // printf(" .... 1 to activate logging, optional, defaults to 0\n"); // printf(" . separator in csv file, optional, c for ',', s for';', defaults to c\n"); // printf(" . list of active categories, optional, see modelDescription.xml for possible values\n"); //}