| /////////////////////////////////////////////////////////////////////////////// |
| // // |
| // Copyright (c) 2000-2019 Ericsson Telecom AB // |
| // // |
| // All rights reserved. This program and the accompanying materials // |
| // are made available under the terms of the Eclipse Public License v2.0 // |
| // which accompanies this distribution, and is available at // |
| // https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////// |
| // Module: EPTF_CLL_Variable_Functions |
| // |
| // Purpose: |
| // This module contains the implementation of generic EPTF_Variable functions. |
| // |
| // Module Parameters: |
| // tsp_EPTF_Var_enableName2Id - *boolean* - if true hashmap database is maintained to get the id from a variable name, default: true |
| // tsp_EPTF_Var_enableCompRef2Id - *boolean* - if true hashmap database is maintained to get the id from a component variable, default: true |
| // tsp_EPTF_Var_enableEmptyTimeLine - *boolean* - if true timeline message will always be sent at the sync-time even if empty, default: false |
| // tsp_EPTF_Var_cfg - <EPTF_Var_InitialValueList> - the initial value list of variables to load |
| // tsp_EPTF_Var_maxWaitTime - *float* - the max time to wait for responses (default: 120.0 sec) |
| // tsp_EPTF_Var_maxWaitTimeForByeAck - *float* - the max time to wait for ByeAck messages (default: 240.0 sec) |
| // tsp_EPTF_Var_debug - *boolean* - to switch on debugging (default: false) |
| // |
| // Module depends on: |
| // <EPTF_CLL_Variable_Definitions> |
| // <EPTF_CLL_Base_Definitions> |
| // <EPTF_CLL_Base_Functions> |
| // <EPTF_CLL_Common_Definitions> |
| // <EPTF_CLL_Common_Functions> |
| // <EPTF_CLL_HashMapStr2Int_Functions> |
| // <EPTF_CLL_HashMapOct2Int_Functions> |
| // <TCCFileIO_Functions> |
| // <TCCDateTime_Functions> |
| // <EPTF_CLL_Logging_Definitions> |
| // <EPTF_CLL_Logging_Functions> |
| // <EPTF_CLL_Scheduler_Definitions> |
| // <EPTF_CLL_RBTScheduler_Functions> |
| // <EPTF_CLL_HashMap_Functions> |
| // <EPTF_CLL_FBQ_Functions> |
| // |
| // Current Owner: |
| // EFLOATT |
| // |
| // Last Review Date: |
| // 2010-xx-xx |
| // |
| // Detailed Comments: |
| // This module contains the interface functions for the EPTF_Variable. |
| // Public functions: |
| // <f_EPTF_Var_init_CT> |
| // <f_EPTF_Var_Log> |
| // <f_EPTF_Var_CT_LogAll> |
| // <f_EPTF_Var_logNames> |
| // <f_EPTF_Var_newIntRef> |
| // <f_EPTF_Var_newFloatRef> |
| // <f_EPTF_Var_newBoolRef> |
| // <f_EPTF_Var_newCharstringRef> |
| // <f_EPTF_Var_newOctetstringRef> |
| // <f_EPTF_Var_newHexstringRef> |
| // <f_EPTF_Var_newBitstringRef> |
| // <f_EPTF_Var_newIntegerlistRef> |
| // <f_EPTF_Var_newFloatlistRef> |
| // <f_EPTF_Var_newCharstringlistRef> |
| // <f_EPTF_Var_newStatusLEDRef> |
| // <f_EPTF_Var_newVar> |
| // <f_EPTF_Var_createVarFromCfg> |
| // <f_EPTF_Var_loadVarFromCfg> |
| // <f_EPTF_Var_saveVarToCfg> |
| // <f_EPTF_Var_saveVarToCfgStr> |
| // <f_EPTF_Var_registerVarToSave> |
| // <f_EPTF_Var_deregisterVarFromSave> |
| // <f_EPTF_Var_saveVars> |
| // <f_EPTF_Var_saveVars2tsp> |
| // <f_EPTF_Var_save> |
| // <f_EPTF_Var_load> |
| // <f_EPTF_Var_loadVarsFromCfg> |
| // <f_EPTF_Var_removeSelfName> |
| // <f_EPTF_Var_newInt> |
| // <f_EPTF_Var_newFloat> |
| // <f_EPTF_Var_newBool> |
| // <f_EPTF_Var_newCharstring> |
| // <f_EPTF_Var_newOctetstring> |
| // <f_EPTF_Var_newHexstring> |
| // <f_EPTF_Var_newBitstring> |
| // <f_EPTF_Var_newIntegerlist> |
| // <f_EPTF_Var_newFloatlist> |
| // <f_EPTF_Var_newCharstringlist> |
| // <f_EPTF_Var_newStatusLED> |
| // <f_EPTF_Var_isValid> |
| // <f_EPTF_Var_getIntValue> |
| // <f_EPTF_Var_getFloatValue> |
| // <f_EPTF_Var_getBoolValue> |
| // <f_EPTF_Var_getCharstringValue> |
| // <f_EPTF_Var_getOctetstringValue> |
| // <f_EPTF_Var_getHexstringValue> |
| // <f_EPTF_Var_getBitstringValue> |
| // <f_EPTF_Var_getIntegerlistValue> |
| // <f_EPTF_Var_getFloatlistValue> |
| // <f_EPTF_Var_getCharstringlistValue> |
| // <f_EPTF_Var_getStatusLEDValue> |
| // <f_EPTF_Var_getContent> |
| // <f_EPTF_Var_setContent> |
| // <f_EPTF_Var_updateRef> |
| // <f_EPTF_Var_getId> |
| // <f_EPTF_Var_getName> |
| // <f_EPTF_Var_intCompRef2Id> |
| // <f_EPTF_Var_Id2CompRef> |
| // <f_EPTF_Var_floatCompRef2Id> |
| // <f_EPTF_Var_boolCompRef2Id> |
| // <f_EPTF_Var_charstringCompRef2Id> |
| // <f_EPTF_Var_octetstringCompRef2Id> |
| // <f_EPTF_Var_hexstringCompRef2Id> |
| // <f_EPTF_Var_bitstringCompRef2Id> |
| // <f_EPTF_Var_integerlistCompRef2Id> |
| // <f_EPTF_Var_floatlistCompRef2Id> |
| // <f_EPTF_Var_charstringlistCompRef2Id> |
| // <f_EPTF_Var_statusLEDCompRef2Id> |
| // <f_EPTF_Var_getValueRef> |
| // <f_EPTF_Var_directContent2RefType> |
| // <f_EPTF_Var_subscribeLocal> |
| // <f_EPTF_Var_addLocalProviders> |
| // <f_EPTF_Var_removeLocalProviders> |
| // <f_EPTF_Var_isPresentRemote> |
| // <f_EPTF_Var_subscribeRemote> |
| // <f_EPTF_Var_resubscribeRemote> |
| // <f_EPTF_Var_isSubscribeRemoteFinished> |
| // <f_EPTF_Var_subscribeRemoteIntRef> |
| // <f_EPTF_Var_subscribeRemoteFloatRef> |
| // <f_EPTF_Var_subscribeRemoteBoolRef> |
| // <f_EPTF_Var_subscribeRemoteCharstringRef> |
| // <f_EPTF_Var_subscribeRemoteOctetstringRef> |
| // <f_EPTF_Var_subscribeRemoteHexstringRef> |
| // <f_EPTF_Var_subscribeRemoteBitstringRef> |
| // <f_EPTF_Var_subscribeRemoteIntegerlistRef> |
| // <f_EPTF_Var_subscribeRemoteFloatlistRef> |
| // <f_EPTF_Var_subscribeRemoteCharstringlistRef> |
| // <f_EPTF_Var_subscribeRemoteStatusLEDValRef> |
| // <f_EPTF_Var_subscribeRemoteRef> |
| // <f_EPTF_Var_unsubscribe> |
| // <f_EPTF_Var_callCalcFn> |
| // <f_EPTF_Var_callPostProcFns> |
| // <f_EPTF_Var_addPostProcFn> |
| // <f_EPTF_Var_removePostProcFn> |
| // <f_EPTF_Var_callGuardFns> |
| // <f_EPTF_Var_addGuardFn> |
| // <f_EPTF_Var_removeGuardFn> |
| // <f_EPTF_Var_callUnsubscribeNotifyFns> |
| // <f_EPTF_Var_addUnsubscribeNotifyFn> |
| // <f_EPTF_Var_removeUnsubscribeNotifyFn> |
| // <f_EPTF_Var_callSubsCanAdjustNotifyFns> |
| // <f_EPTF_Var_addSubsCanAdjustNotifyFn> |
| // <f_EPTF_Var_removeSubsCanAdjustNotifyFn> |
| // <f_EPTF_Var_callSyncCallBackFns> |
| // <f_EPTF_Var_addSyncCallBackFn> |
| // <f_EPTF_Var_removeSyncCallBackFn> |
| // <f_EPTF_Var_refreshContent> |
| // <f_EPTF_Var_getSubsCanAdjust> |
| // >f_EPTF_Var_setSubsCanAdjust> |
| // <f_EPTF_Var_adjustContent> |
| // <f_EPTF_Var_adjustContent_Blocking> |
| // <f_EPTF_Var_getRemoteContent> |
| // <f_EPTF_Var_adjustRemoteContent> |
| // <f_EPTF_Var_adjustRemoteContent_Blocking> |
| // <f_EPTF_Var_setMaxWaitTimeForByeAck> |
| // <f_EPTF_Var_getVarRefreshRate> |
| // <f_EPTF_Var_getRefreshPeriod> |
| // <f_EPTF_Var_getRefreshRate> |
| // <f_EPTF_Var_getRefreshRateId> |
| // <f_EPTF_Var_getTimeLine> |
| // <f_EPTF_Var_setSyncInterval> |
| // <f_EPTF_Var_setMinSyncInterval> |
| // <f_EPTF_Var_setMaxWaitTime> |
| // <f_EPTF_Var_content2str> |
| // <f_EPTF_Var_str2content> |
| // <f_EPTF_Var_content2string> |
| // <f_EPTF_Var_upcast> |
| // <f_EPTF_Var_downcast> |
| // <f_EPTF_Var_getIntRef> |
| // <f_EPTF_Var_derefInt> |
| // <f_EPTF_Var_modifyIntRefValue> |
| // <f_EPTF_Var_getFloatRef> |
| // <f_EPTF_Var_derefFloat> |
| // <f_EPTF_Var_modifyFloatRefValue> |
| // <f_EPTF_Var_getBoolRef> |
| // <f_EPTF_Var_derefBool> |
| // <f_EPTF_Var_modifyBoolRefValue> |
| // <f_EPTF_Var_getCharstringRef> |
| // <f_EPTF_Var_derefCharstring> |
| // <f_EPTF_Var_modifyCharstringRefValue> |
| // <f_EPTF_Var_getOctetstringRef> |
| // <f_EPTF_Var_derefOctetstring> |
| // <f_EPTF_Var_modifyOctetstringRefValue> |
| // <f_EPTF_Var_getHexstringRef> |
| // <f_EPTF_Var_derefHexstring> |
| // <f_EPTF_Var_modifyHexstringRefValue> |
| // <f_EPTF_Var_getBitstringRef> |
| // <f_EPTF_Var_derefBitstring> |
| // <f_EPTF_Var_modifyBitstringRefValue> |
| // <f_EPTF_Var_getIntegerlistRef> |
| // <f_EPTF_Var_derefIntegerlist> |
| // <f_EPTF_Var_modifyIntegerlistRefValue> |
| // <f_EPTF_Var_getFloatlistRef> |
| // <f_EPTF_Var_derefFloatlist> |
| // <f_EPTF_Var_modifyFloatlistRefValue> |
| // <f_EPTF_Var_getCharstringlistRef> |
| // <f_EPTF_Var_derefCharstringlist> |
| // <f_EPTF_Var_modifyCharstringlistRefValue> |
| // <f_EPTF_Var_getStatusLEDRef> |
| // <f_EPTF_Var_derefStatusLED> |
| // <f_EPTF_Var_modifyStatusLEDRefValue> |
| // |
| // <f_EPTF_Var_checkName> |
| // <f_EPTF_Var_directContent2str> |
| // <f_EPTF_Var_str2directContent> |
| // <f_EPTF_Var_removeVar> |
| // <f_EPTF_Var_getTopProviderType> |
| // <f_EPTF_Var_checkSubscriptionMode> |
| // <f_EPTF_Var_useCompRef2Id> |
| // <f_EPTF_Var_useName2Id> |
| // <f_EPTF_Var_getHashmap_Hashmap_CompRef2Id> |
| // <f_EPTF_Var_getHashmap_Name2Id> |
| // <f_EPTF_Var_enableDebug> |
| // <f_EPTF_Var_updateTimeLine> |
| // <f_EPTF_Var_sendTimeLine> |
| // <f_EPTF_Var_subscribeRemote_nonBlocking> |
| // |
| /////////////////////////////////////////////////////////////// |
| |
| module EPTF_CLL_Variable_Functions { |
| |
| import from EPTF_CLL_Variable_Definitions all; |
| import from EPTF_CLL_Base_Definitions all; |
| import from EPTF_CLL_Base_Functions all; |
| import from EPTF_CLL_Common_Definitions all; // EPTF_IntegerList |
| import from EPTF_CLL_Common_Functions all; |
| import from EPTF_CLL_HashMapStr2Int_Functions all; |
| import from EPTF_CLL_HashMapOct2Int_Functions all; |
| import from TCCFileIO_Functions all; |
| import from TCCDateTime_Functions all; |
| import from EPTF_CLL_Logging_Definitions all; |
| import from EPTF_CLL_Logging_Functions all; |
| import from EPTF_CLL_Scheduler_Definitions all; |
| import from EPTF_CLL_RBTScheduler_Functions all; |
| import from EPTF_CLL_HashMap_Functions all; |
| import from EPTF_CLL_FBQ_Functions all; |
| |
| modulepar boolean tsp_EPTF_Var_enableName2Id := true; // if true hashmap database is maintained to get the id from a variable name |
| modulepar boolean tsp_EPTF_Var_enableCompRef2Id := true; // if true hashmap database is maintained to get the id from a component variable |
| modulepar boolean tsp_EPTF_Var_enableEmptyTimeLine := false; // if true timeline message will always be sent at the sync-time even if empty |
| |
| modulepar float tsp_EPTF_Var_maxWaitTime := 120.0; // the max time to wait for responses (default: 120.0 sec) |
| modulepar float tsp_EPTF_Var_maxWaitTimeForByeAck := 240.0; // the max time to wait for ByeAck messages (default: 240.0 sec) |
| modulepar boolean tsp_EPTF_Var_debug := false; // switch on debugging |
| modulepar EPTF_Var_InitialValueList tsp_EPTF_Var_cfg := {}; // the initial value list of variables to load |
| |
| |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| // public: |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////// |
| // Group: Public |
| // |
| // Purpose: |
| // Public functions. Only these functions can be used by the user of <EPTF_Var_CT> |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group Public { |
| |
| // LOGGING |
| |
| /////////////////////////////////////////////////////////// |
| // Group: Logging |
| // |
| // Purpose: |
| // Logging functions. |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group Logging { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_CT_LogAll |
| // |
| // Purpose: |
| // Log everything (important) in <EPTF_Var_CT> component |
| // |
| // Parameters: |
| // pl_msg - *in* *charstring* - message to log. It is printed before and after the component data |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_CT_LogAll(in charstring pl_msg) runs on EPTF_Var_CT { |
| if (pl_msg!="") { |
| f_EPTF_Var_debug(pl_msg); |
| }; |
| f_EPTF_Var_debug(log2str("EPTF_Var_CT.v_EPTF_Vars: ", v_EPTF_Vars)); |
| f_EPTF_Var_debug(log2str("EPTF_Var_CT.v_syncBuffer: ", v_syncBuffer)); |
| f_EPTF_Var_debug(log2str("EPTF_Var_CT.adjustContentResp_handler_ParamStack:", adjustContentResp_handler_ParamStack)); |
| f_EPTF_Var_debug(log2str("EPTF_Var_CT.v_EPTF_Var_varsToSave", v_EPTF_Var_varsToSave)); |
| if (pl_msg!="") { |
| f_EPTF_Var_debug(pl_msg); |
| }; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_Log |
| // |
| // Purpose: |
| // Log a given EPTF Variable |
| // |
| // Parameters: |
| // pl_msg - *in* *charstring* - message to log. It is printed before and after the variable data |
| // pl_idx - *in* *integer* - the idx of the EPTF Variable to log |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_Log(in charstring pl_msg, in integer pl_idx) runs on EPTF_Var_CT { |
| if (pl_msg!="") { |
| f_EPTF_Var_debug(pl_msg); |
| }; |
| f_EPTF_Var_debug(log2str("EPTF_Var_CT.v_EPTF_Vars[",pl_idx,"]: ", v_EPTF_Vars[pl_idx])); |
| if (pl_msg!="") { |
| f_EPTF_Var_debug(pl_msg); |
| }; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_logNames |
| // |
| // Purpose: |
| // Log all variable names |
| // |
| // Parameters: |
| // pl_msg - *in* *charstring* - message to log. It is printed before and after the variable data |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_logNames(in charstring pl_msg) runs on EPTF_Var_CT { |
| if (pl_msg!="") { |
| f_EPTF_Var_debug(pl_msg); |
| }; |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars); i:=i+1) { |
| f_EPTF_Var_debug(log2str("Name of v_EPTF_Vars[",i,"]: ", v_EPTF_Vars[i].name)); |
| } |
| if (pl_msg!="") { |
| f_EPTF_Var_debug(pl_msg); |
| }; |
| } |
| |
| } // group Logging |
| |
| /////////////////////////////////////////////////////////// |
| // Group: CompInit |
| // |
| // Purpose: |
| // Functions to initialize the <EPTF_Var_CT> component. |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group CompInit { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_init_CT |
| // |
| // Purpose: |
| // Initializes the EPTF_Var_CT component |
| // |
| // Parameters: |
| // pl_selfName - *in* *charstring* - name of the component |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function should be called before using the EPTF Variable |
| // component. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_init_CT(in charstring pl_selfName) runs on EPTF_Var_CT { |
| if (v_EPTF_Var_initialized) { |
| // set the priority of the altstep to the highest by reactivating it: |
| deactivate(v_EPTF_Var_def); |
| v_EPTF_Var_def := activate(as_EPTF_Var_mainHandler_MgmtIf()); |
| return; // already initialized |
| } |
| |
| // activate with lowest priority (befor the init function calls): |
| v_EPTF_Var_def := activate(as_EPTF_Var_mainHandler_MgmtIf()); |
| |
| f_EPTF_Base_init_CT(pl_selfName); |
| |
| f_EPTF_FBQ_init_CT(pl_selfName); |
| |
| f_EPTF_Scheduler_init_CT(pl_selfName); |
| |
| f_EPTF_Logging_init_CT(pl_selfName); |
| |
| f_EPTF_HashMap_init_CT (pl_selfName); |
| |
| f_EPTF_Var_setMaxWaitTime(tsp_EPTF_Var_maxWaitTime);//HM27497 |
| v_Var_loggingMaskId := f_EPTF_Logging_registerComponentMasks(tsp_EPTF_Var_loggingComponentMask, c_EPTF_Var_loggingEventClasses, EPTF_Logging_CLL); |
| if(tsp_EPTF_Var_debug) { |
| f_EPTF_Logging_enableLocalMask(v_Var_loggingMaskId, c_EPTF_Var_loggingClassIdx_Debug); |
| } else { |
| f_EPTF_Logging_disableLocalMask(v_Var_loggingMaskId, c_EPTF_Var_loggingClassIdx_Debug); |
| } |
| |
| v_EPTF_Var_enableName2Id := tsp_EPTF_Var_enableName2Id; |
| v_EPTF_Var_enableCompRef2Id := tsp_EPTF_Var_enableCompRef2Id; |
| if (v_EPTF_Var_enableName2Id) { |
| v_EPTF_Var_Hashmap_Name2Id := f_EPTF_str2int_HashMap_New("EPTF_Var_Hashmap_Name2Id"); |
| } |
| if (v_EPTF_Var_enableCompRef2Id) { |
| v_EPTF_Var_Hashmap_CompRef2Id := f_EPTF_oct2int_HashMap_New("EPTF_Var_Hashmap_CompRef2Id"); |
| } |
| |
| v_EPTF_Var_Hashmap_Provider2Id := f_EPTF_str2int_HashMap_New("EPTF_Var_Hashmap_Provider2Id"); |
| |
| v_EPTF_Var_Hashmap_SyncBuffer := f_EPTF_str2int_HashMap_New("EPTF_Var_Hashmap_SyncBuffer"); |
| |
| v_EPTF_Vars := {}; |
| var integer vl_refreshRateId := 0; |
| v_syncBuffer[vl_refreshRateId].refreshRate := 0; // default refresh method |
| v_syncBuffer[vl_refreshRateId].eventIdx := -1; // invalid index |
| v_syncBuffer[vl_refreshRateId].syncBuffer := {}; |
| v_syncInterval := tsp_EPTF_Var_SyncInterval; |
| v_minSyncInterval := tsp_EPTF_ELEMENTARY_TIMESTEP_PARAM; |
| if(f_EPTF_SchedulerComp_scheduleAction( |
| pl_when := f_EPTF_Base_getRelTimeInSecs()+v_syncInterval, |
| pl_actionHandler := refers(f_EPTF_Var_syncTimeoutHandler), |
| pl_action := {vl_refreshRateId}, |
| pl_eventIndex := v_syncBuffer[vl_refreshRateId].eventIdx |
| )){/*remove the warning*/}; |
| v_EPTF_Var_syncCallbackFns := {}; |
| v_EPTF_Var_varsToSave := {}; |
| f_EPTF_initEPTF_Var_adjustContentResp_handlerPool(adjustContentResp_handler_ParamStack); |
| f_EPTF_initbooleanPool(v_booleanPool); |
| v_EPTF_Var_pendingByeNum := 0; |
| v_EPTF_Var_varsToUpdate := {}; |
| f_EPTF_Var_setRefreshSubscribersPeriod(); |
| v_EPTF_Var_numPendingHellos := 0; |
| v_EPTF_Var_maxWaitTimeForByeAck := tsp_EPTF_Var_maxWaitTimeForByeAck; |
| |
| |
| v_EPTF_Var_Msg_Buffer := {}; |
| v_EPTF_Var_Msg_BufferStartIdx := 0; |
| v_EPTF_Var_nofPendingMsgs := 0; |
| |
| v_EPTF_Var_Connections := {}; |
| v_EPTF_Var_resubscribeRemoteResp_handler_DB := {}; |
| v_EPTF_Var_msgBufferBeforeConnect := {}; |
| v_EPTF_Var_nonBlockingEnabled := {}; |
| |
| v_EPTF_Var_initialized := true; |
| |
| f_EPTF_Base_registerCleanup(refers(f_EPTF_Var_cleanup_CT)); |
| |
| f_EPTF_Var_debug("---- EPTF_Variable INIT "&pl_selfName&" DONE ----"); |
| } |
| |
| } // group CompInit |
| |
| /////////////////////////////////////////////////////////// |
| // Group: VaribleCreationValueAssignment |
| // |
| // Purpose: |
| // Functions to create EPTF Variables and and assign value. |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group VaribleCreationValueAssignment { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newIntRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* *integer* - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newIntRef(in charstring pl_name, inout integer pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getIntRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=intType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newFloatRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* *float* - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newFloatRef(in charstring pl_name, inout float pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getFloatRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=floatType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newBoolRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* *boolean* - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newBoolRef(in charstring pl_name, inout boolean pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getBoolRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=boolType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newCharstringRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* *charstring* - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newCharstringRef(in charstring pl_name, inout charstring pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getCharstringRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=charstringType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newOctetstringRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* *octetstring* - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newOctetstringRef(in charstring pl_name, inout octetstring pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getOctetstringRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=octetstringType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newHexstringRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* *hexstring* - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newHexstringRef(in charstring pl_name, inout hexstring pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getHexstringRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=hexstringType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newBitstringRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* *bitstring* - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newBitstringRef(in charstring pl_name, inout bitstring pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getBitstringRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=bitstringType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newIntegerlistRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* <EPTF_IntegerList> - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newIntegerlistRef(in charstring pl_name, inout EPTF_IntegerList pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getIntegerlistRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=integerlistType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newFloatlistRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* <EPTF_FloatList> - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newFloatlistRef(in charstring pl_name, inout EPTF_FloatList pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getFloatlistRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=floatlistType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newCharstringlistRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* <EPTF_CharstringList> - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newCharstringlistRef(in charstring pl_name, inout EPTF_CharstringList pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getCharstringlistRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=charstringlistType, valueRef := vl_valueRef}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newStatusLEDRef |
| // |
| // Purpose: |
| // Creates a new EPTF_Var that is a reference to an existing component variable |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_compVar - *inout* *EPTF_StatusLED* - component variable for which the EPTF Variable is assigned |
| // pl_idx - *out* *integer* - the idx of the assigned new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newStatusLEDRef(in charstring pl_name, inout EPTF_StatusLED pl_compVar, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| var octetstring vl_valueRef := f_EPTF_Var_getStatusLEDRef(pl_compVar); |
| f_EPTF_Var_initContentRef(pl_idx, {refType:=statusLEDType, valueRef := vl_valueRef}); |
| } |
| //... |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newVar |
| // |
| // Purpose: |
| // Creates a new EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* <EPTF_Var_DirectContent> - initial value of the variable |
| // |
| // Return Value: |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newVar(in charstring pl_name, in EPTF_Var_DirectContent pl_initValue) runs on EPTF_Var_CT return integer { |
| var integer pl_idx; |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, pl_initValue); |
| return pl_idx; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_createVarFromCfg |
| // |
| // Purpose: |
| // Creates a new EPTF_Var and sets its initial value from cfg data |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable to create automatically if found in the pl_cfg |
| // pl_cfg - *in* <EPTF_Var_InitialValueList> - List of initial values of the variables to search for pl_name. Default: tsp_EPTF_Var_cfg |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the created variable will be the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the created variable name will be pl_name, i.e. the component name (selfName) is |
| // removed from the name of the variable. Default: true |
| // |
| // Return Value: |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_createVarFromCfg(in charstring pl_name, in EPTF_Var_InitialValueList pl_cfg := tsp_EPTF_Var_cfg, in boolean pl_removeSelfNameFromParamName := true) runs on EPTF_Var_CT return integer |
| { |
| |
| for (var integer i:= 0; i<sizeof(pl_cfg); i:=i+1) { |
| if (f_EPTF_Base_selfName()&"."&pl_name == pl_cfg[i].name and pl_removeSelfNameFromParamName) { |
| return f_EPTF_Var_newVar(pl_name, pl_cfg[i].initValue); |
| } |
| if (pl_name == pl_cfg[i].name and not pl_removeSelfNameFromParamName) { |
| return f_EPTF_Var_newVar(pl_name, pl_cfg[i].initValue); |
| } |
| } |
| return -1; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_loadVarFromCfg |
| // |
| // Purpose: |
| // Loads a the value of an existing EPTF_Var and sets its initial value from cfg data |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable to load if found in the pl_cfg |
| // pl_cfg - *in* <EPTF_Var_InitialValueList> - List of initial values of the variables to search for pl_name. Default: tsp_EPTF_Var_cfg |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the variable should be the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the variable name should be pl_name, i.e. the component name (selfName) is |
| // removed from the name of the variable. Default: true |
| // |
| // Return Value: |
| // pl_idx - *out* *integer* - the idx of the loaded EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_loadVarFromCfg(in charstring pl_name, in EPTF_Var_InitialValueList pl_cfg := tsp_EPTF_Var_cfg, in boolean pl_removeSelfNameFromParamName := true) runs on EPTF_Var_CT return integer |
| { |
| if (pl_name=="") { |
| return -1; // variables with empty names are not loaded |
| } |
| var integer vl_idx := f_EPTF_Var_getId(pl_name); |
| if (vl_idx == -1) { |
| f_EPTF_Var_warning(log2str("Cannot load Variable ", pl_name, " from config: Variable does not exist.")); |
| return -1; // variable does not exist |
| } |
| var charstring vl_name := pl_name; // cfg file name and variable name is the same |
| if (pl_removeSelfNameFromParamName) { |
| vl_name := f_EPTF_Base_selfName()&"."&pl_name; // cfg file name contains selfName, but variable name does not |
| } |
| for (var integer i:= 0; i<sizeof(pl_cfg); i:=i+1) { |
| if (vl_name == pl_cfg[i].name) { |
| f_EPTF_Var_adjustContent(vl_idx, pl_cfg[i].initValue); |
| return vl_idx; |
| } |
| } |
| f_EPTF_Var_warning(log2str("No entry found for Variable ", vl_name, " in config. Variable ",pl_name," is not loaded.")); |
| return -1; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_saveVarToCfg |
| // |
| // Purpose: |
| // Saves a the value of the given EPTF_Var to cfg data |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable to load if found in the pl_cfg |
| // pl_cfg - *out* <EPTF_Var_InitialValueList> - Initial value of the variable with its name |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the variable should be the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the variable name should be pl_name, i.e. the component name (selfName) is |
| // removed from the name of the variable. Default: true |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is not used. Would be useful if there were a toStr function for EPTF_Var_InitialValue |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_saveVarToCfg(in charstring pl_name, out EPTF_Var_InitialValue pl_cfg, in boolean pl_removeSelfNameFromParamName := true) runs on EPTF_Var_CT |
| { |
| var integer vl_idx := f_EPTF_Var_getId(pl_name); |
| if (vl_idx == -1) { |
| pl_cfg := { |
| name := "-NOTFOUND: in component "&f_EPTF_Base_selfName()&": "&pl_name&"-", |
| initValue := {intVal := -1} |
| } |
| return; |
| } |
| // f_EPTF_Base_assert("Cannot save Variable " &pl_name& " to config: Variable does not exist.", vl_idx != -1); |
| if (pl_removeSelfNameFromParamName) { |
| pl_cfg.name := f_EPTF_Base_selfName()&"."&pl_name; // cfg file name contains selfName, but variable name does not |
| } else { |
| pl_cfg.name := pl_name; // cfg file name and variable name is the same |
| } |
| f_EPTF_Var_debug(log2str("saved to: ", pl_cfg)); |
| f_EPTF_Var_getContent(vl_idx,pl_cfg.initValue); |
| //var charstring vl_contentStr := f_EPTF_Var_content2string(pl_cfg.initValue); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_saveVarToCfgStr |
| // |
| // Purpose: |
| // Saves a the value of the given EPTF_Var to cfg string |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable to load if found in the pl_cfg |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the variable should be the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the variable name should be pl_name, i.e. the component name (selfName) is |
| // removed from the name of the variable. Default: true |
| // |
| // Return Value: |
| // charstring - Value of the variable in loadable format |
| // |
| // Errors: |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_saveVarToCfgStr(in charstring pl_name, in boolean pl_removeSelfNameFromParamName := true) runs on EPTF_Var_CT return charstring |
| { |
| var integer vl_idx := f_EPTF_Var_getId(pl_name); |
| if (vl_idx == -1) { |
| return ""; // if not found: do not save |
| } |
| var charstring vl_contentStr := f_EPTF_Var_content2string(vl_idx); |
| var charstring vl_name := pl_name; // cfg file name and variable name is the same |
| if (pl_removeSelfNameFromParamName) { |
| vl_name := f_EPTF_Base_selfName()&"."&pl_name; // cfg file name contains selfName, but variable name does not |
| } |
| return "{ name := \""&vl_name&"\", initValue := "&vl_contentStr&" }" |
| |
| // var EPTF_Var_InitialValue vl_cfg; |
| // f_EPTF_Var_saveVarToCfg(pl_name,vl_cfg,pl_removeSelfNameFromParamName); |
| // var charstring vl_contentStr := f_EPTF_Var_directContent2string(vl_cfg.initValue); |
| // return "{ name := "&vl_cfg.name&", initValue := "&vl_contentStr&" }" |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_registerVarToSave |
| // |
| // Purpose: |
| // Registers a variable name that will be saved |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // |
| // Detailed Comments: |
| // Does not check if variable exists ( => it is possible to register variables before they are created) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_registerVarToSave(in charstring pl_name) runs on EPTF_Var_CT { |
| if (pl_name=="") { |
| return; // variables with empty names are not saved |
| } |
| v_EPTF_Var_varsToSave[sizeof(v_EPTF_Var_varsToSave)] := pl_name; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_deregisterVarFromSave |
| // |
| // Purpose: |
| // Removes a variable name from the list of varibles registered by <f_EPTF_Var_registerVarToSave> |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // |
| // Detailed Comments: |
| // Does not check if variable exists ( => it is possible to deregister variables before they are created) |
| // |
| /////////////////////////////////////////////////////////// |
| |
| public function f_EPTF_Var_deregisterVarFromSave(in charstring pl_name) runs on EPTF_Var_CT { |
| if (pl_name=="") { |
| return; // variables with empty names are not saved |
| } |
| for (var integer i:=0; i<sizeof(v_EPTF_Var_varsToSave); i:=i+1) { |
| if (v_EPTF_Var_varsToSave[i] == pl_name) { |
| v_EPTF_Var_varsToSave[i] := ""; |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_saveVars |
| // |
| // Purpose: |
| // Saves all registered variables in cfg format |
| // |
| // Parameters: |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the variable should be the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the variable name should be pl_name, i.e. the component name (selfName) is |
| // removed from the name of the variable. Default: true |
| // |
| // Return Value: |
| // charstring - Value of the variables in loadable format |
| // |
| // Errors: |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_saveVars(in boolean pl_removeSelfNameFromParamName := true) runs on EPTF_Var_CT return charstring { |
| var charstring vl_result := ""; |
| for(var integer i:=0; i<sizeof(v_EPTF_Var_varsToSave); i:=i+1) { |
| var charstring vl_saveStr := f_EPTF_Var_saveVarToCfgStr(v_EPTF_Var_varsToSave[i],pl_removeSelfNameFromParamName); |
| if (vl_saveStr!="") { |
| if (vl_result!="") { |
| vl_result := vl_result&",\n"; // add comma if necessary |
| } |
| vl_result := vl_result & vl_saveStr; |
| } |
| } |
| return vl_result; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_saveVars2tsp |
| // |
| // Purpose: |
| // Saves all registered variables in a module parameter tsp_xxx := {***} format |
| // |
| // Parameters: |
| // pl_moduleParName - *in charstring* - the module parameter name to save the values into. Default: tsp_EPTF_Var_cfg |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the variable should be the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the variable name should be pl_name, i.e. the component name (selfName) is |
| // removed from the name of the variable. Default: true |
| // |
| // Return Value: |
| // charstring - Value of the variables in loadable format |
| // |
| // Errors: |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_saveVars2tsp( |
| in charstring pl_moduleParName := "tsp_EPTF_Var_cfg", |
| in boolean pl_removeSelfNameFromParamName := true |
| ) runs on EPTF_Var_CT return charstring { |
| return pl_moduleParName & " := {\n" &f_EPTF_Var_saveVars(pl_removeSelfNameFromParamName)& "\n}\n\n"; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_save |
| // |
| // Purpose: |
| // Saves all registered variables in a file as module parameter tsp_xxx := {***} format |
| // |
| // Parameters: |
| // pl_fileName - *in charstring* - the filename where the variables shall be saved (default: <tsp_EPTF_Var_snapshotFilename>) |
| // pl_timeStampFormat - *in charstring* - the format of the timestamp in the generated filename (pl_fileName<timestamp>). |
| // Can be anything, even empty string. For the supported time-format strings see <f_getTimeFormatted>. Default: tsp_EPTF_Var_snapshotTimestamp |
| // pl_moduleparName - *in charstring* - the module parameter name to save the values into. Default: tsp_EPTF_Var_<selfname>_cfg |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the variable should be the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the variable name should be pl_name, i.e. the component name (selfName) is |
| // removed from the name of the variable. Default: false |
| // |
| // Return Value: |
| // charstring - name of the file the snapshot was saved in. Empty string ("") is returned on error. |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // The name of the file will be: pl_fileName + timestamp |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_save( |
| in charstring pl_fileName := tsp_EPTF_Var_snapshotFilename, |
| in charstring pl_timeStampFormat := tsp_EPTF_Var_snapshotTimestamp, |
| in charstring pl_moduleparName := "", |
| in boolean pl_removeSelfNameFromParamName := false |
| ) runs on EPTF_Var_CT return charstring { |
| var charstring vl_moduleparName := pl_moduleparName; |
| if (vl_moduleparName == "") { |
| vl_moduleparName := "tsp_EPTF_Var_"&f_EPTF_Base_selfName()&"_cfg" |
| } |
| var charstring vl_saveString := "[MODULE_PARAMETERS]\n"&f_EPTF_Var_saveVars2tsp(vl_moduleparName,pl_removeSelfNameFromParamName); |
| var charstring vl_timeStamp := f_getTimeFormatted(float2int(f_EPTF_Base_getAbsTimeInSecs(f_EPTF_SchedulerComp_snapshotTime())),pl_timeStampFormat); |
| var charstring vl_filename := pl_fileName; |
| if (vl_filename=="") { // if pl_fileName=="" the file name will be <selfname><timestamp> |
| vl_filename := f_EPTF_Base_selfName(); |
| } |
| vl_filename := vl_filename&vl_timeStamp; |
| f_EPTF_Var_debug(log2str("vl_filename: ", vl_filename)); |
| f_EPTF_Var_debug(log2str("vl_saveString: ", vl_saveString)); |
| // use filio to save the string to file. // FIXME |
| var integer vl_fd := f_FIO_open_append_wronly_excl(vl_filename); |
| if (vl_fd == -1) { |
| f_EPTF_Var_warning(log2str("f_EPTF_Var_save: cannot open file ", vl_filename, ": ", f_FIO_get_error_string())); |
| return ""; |
| } |
| var charstring vl_fileNameSaved := vl_filename; |
| if (f_FIO_write_text(vl_fd, vl_saveString) == -1) { |
| f_EPTF_Var_warning(log2str("f_EPTF_Var_save: cannot save EPTF_Variable data to file ", vl_filename, ": ", f_FIO_get_error_string())); |
| return ""; |
| }; |
| if (-1==f_FIO_close(vl_fd)) {/*to remove the warning*/}; |
| return vl_filename; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_load |
| // |
| // Purpose: |
| // Loads all variables in a file that was saved earlier by <f_EPTF_Var_save> |
| // |
| // Parameters: |
| // pl_fileName - *in charstring* - the filename from where the variables shall be loaded (default: <tsp_EPTF_Var_snapshotFilename>) |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the variable should be the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the variable name should be pl_name, i.e. the component name (selfName) is |
| // removed from the name of the variable. Default: false |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // |
| // Detailed Comments: |
| // Not implemented yet! Inverse of log2str or parsing needed |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_load( |
| in charstring pl_fileName := tsp_EPTF_Var_snapshotFilename, |
| in boolean pl_removeSelfNameFromParamName := false |
| ) runs on EPTF_Var_CT { |
| // f_EPTF_Var_loadVarsFromCfg(pl_cfg,pl_removeSelfNameFromParamName); |
| return; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_loadVarsFromCfg |
| // |
| // Purpose: |
| // Load all variables that exists in the current component from the initial value list parameter |
| // |
| // Parameters: |
| // pl_cfg - *in* <EPTF_Var_InitialValueList> - List of initial values of the variables to load. Default: tsp_EPTF_Var_cfg |
| // pl_removeSelfNameFromParamName - *in boolean* - if false, the name of the variables are the same as in the pl_cfg. |
| // If true, the <selfName>&"."&pl_name name is searched in pl_cfg, and the variable name should be pl_name, i.e. |
| // the component name (selfName) is removed from the name of the variable. Default: true |
| // |
| // Return Value: |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_loadVarsFromCfg(in EPTF_Var_InitialValueList pl_cfg := tsp_EPTF_Var_cfg, in boolean pl_removeSelfNameFromParamName := true |
| ) runs on EPTF_Var_CT { |
| var charstring vl_varName; |
| for(var integer i:=0; i<sizeof(pl_cfg); i:=i+1) { |
| if (pl_removeSelfNameFromParamName) { |
| // load only if the name begins with selfname |
| vl_varName := f_EPTF_Var_removeSelfName(pl_cfg[i].name); |
| } else { |
| vl_varName := pl_cfg[i].name; |
| } |
| if (vl_varName != "") { |
| // f_EPTF_Var_loadVarFromCfg(vl_varName,pl_cfg,pl_removeSelfNameFromParamName); |
| var integer vl_idx := f_EPTF_Var_getId(vl_varName); |
| if (vl_idx >= 0) { |
| f_EPTF_Var_adjustContent(vl_idx, pl_cfg[i].initValue); |
| } else { |
| f_EPTF_Var_warning(log2str("Cannot load Variable ", vl_varName, " from config: Variable does not exist.")); |
| } |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeSelfName |
| // |
| // Purpose: |
| // Removes selfName from the name (with the dot) and returns the rest. returns "" if selfName cannot be removed |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - a name (of the variable) to remove the selfName from |
| // |
| // Return Value: |
| // charstring - the name without "<selfName>.", or "" of selfName cannot be removed |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_removeSelfName(in charstring pl_name) runs on EPTF_Var_CT return charstring { |
| if (pl_name=="") { |
| return ""; |
| } |
| if (lengthof(f_EPTF_Base_selfName())+1<lengthof(pl_name) // +1 is for the dot; the rest should not be an empty string |
| and substr(pl_name,0,lengthof(f_EPTF_Base_selfName())) == f_EPTF_Base_selfName() |
| ) { |
| // remove the selfname (+1 is the dot): |
| return substr(pl_name, lengthof(f_EPTF_Base_selfName())+1, lengthof(pl_name)-lengthof(f_EPTF_Base_selfName())-1); |
| } else { |
| return ""; |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newInt |
| // |
| // Purpose: |
| // Creates a new integer-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* *integer* - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newInt(in charstring pl_name, in integer pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {intVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newFloat |
| // |
| // Purpose: |
| // Creates a new float-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* *float* - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newFloat(in charstring pl_name, in float pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {floatVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newBool |
| // |
| // Purpose: |
| // Creates a new boolean-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* *boolean* - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newBool(in charstring pl_name, in boolean pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {boolVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newCharstring |
| // |
| // Purpose: |
| // Creates a new charstring-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* *charstring* - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newCharstring(in charstring pl_name, in charstring pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {charstringVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newOctetstring |
| // |
| // Purpose: |
| // Creates a new octetstring-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* *octetstring* - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newOctetstring(in charstring pl_name, in octetstring pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {octetstringVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newHexstring |
| // |
| // Purpose: |
| // Creates a new hexstring-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* *hexstring* - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newHexstring(in charstring pl_name, in hexstring pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {hexstringVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newBitstring |
| // |
| // Purpose: |
| // Creates a new bitstring-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* *bitstring* - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newBitstring(in charstring pl_name, in bitstring pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {bitstringVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newIntegerlist |
| // |
| // Purpose: |
| // Creates a new EPTF_IntegerList-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* <EPTF_IntegerList> - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newIntegerlist(in charstring pl_name, in EPTF_IntegerList pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {integerlistVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newFloatlist |
| // |
| // Purpose: |
| // Creates a new EPTF_FloatList-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* <EPTF_FloatList> - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newFloatlist(in charstring pl_name, in EPTF_FloatList pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {floatlistVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newCharstringlist |
| // |
| // Purpose: |
| // Creates a new EPTF_CharstringList-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* <EPTF_CharstringList> - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newCharstringlist(in charstring pl_name, in EPTF_CharstringList pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {charstringlistVal := pl_initValue}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_newStatusLED |
| // |
| // Purpose: |
| // Creates a new EPTF_StatusLED-type EPTF_Var and sets its initial value |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // pl_initValue - *in* *EPTF_StatusLED* - initial value of the variable |
| // pl_idx - *out* *integer* - the idx of the created new EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_newStatusLED(in charstring pl_name, in EPTF_StatusLED pl_initValue, out integer pl_idx) runs on EPTF_Var_CT { |
| f_EPTF_Var_addNew(pl_idx, pl_name); |
| f_EPTF_Var_initContent(pl_idx, {statusLEDVal := pl_initValue}); |
| } |
| //... |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_isValid |
| // |
| // Purpose: |
| // Returns true if the variable has valid content |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *boolean* - true if the variable has valid content |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_isValid(in integer pl_idx) runs on EPTF_Var_CT return boolean { |
| return not ischosen(v_EPTF_Vars[pl_idx].content.invalid); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getIntValue |
| // |
| // Purpose: |
| // Returns the value as an integer of a direct EPTF_Var or the dereffed value of a referenced intType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *integer* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not an integer referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getIntValue(in integer pl_idx) runs on EPTF_Var_CT return integer { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.intVal)) { |
| f_EPTF_Var_error(log2str("Integer value is requested for the EPTF_Var[",pl_idx,"] which has non-integer content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.intVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.intVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != intType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not an intType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefInt(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return -1; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getFloatValue |
| // |
| // Purpose: |
| // Returns the value as a float of a direct EPTF_Var or the dereffed value of a referenced floatType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *float* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a float referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getFloatValue(in integer pl_idx) runs on EPTF_Var_CT return float { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.floatVal)) { |
| f_EPTF_Var_error(log2str("Float value is requested for the EPTF_Var[",pl_idx,"] which has non-float content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.floatVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.floatVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != floatType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not a floatType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefFloat(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return -1.0; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getBoolValue |
| // |
| // Purpose: |
| // Returns the value as a boolean of a direct EPTF_Var or the dereffed value of a referenced boolType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *boolean* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a boolean referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getBoolValue(in integer pl_idx) runs on EPTF_Var_CT return boolean { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.boolVal)) { |
| f_EPTF_Var_error(log2str("Boolean value is requested for the EPTF_Var[",pl_idx,"] which has non-boolean content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.boolVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.boolVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != boolType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not a boolType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefBool(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return false; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getCharstringValue |
| // |
| // Purpose: |
| // Returns the value as a charstring of a direct EPTF_Var or the dereffed value of a referenced charstringType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *charstring* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a charstring referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getCharstringValue(in integer pl_idx) runs on EPTF_Var_CT return charstring { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.charstringVal)) { |
| f_EPTF_Var_error(log2str("Charstring value is requested for the EPTF_Var[",pl_idx,"] which has non-charstring content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.charstringVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.charstringVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != charstringType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not a charstringType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefCharstring(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return ""; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getOctetstringValue |
| // |
| // Purpose: |
| // Returns the value as a octetstring of a direct EPTF_Var or the dereffed value of a referenced octetstringType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *octetstring* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a charstring referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getOctetstringValue(in integer pl_idx) runs on EPTF_Var_CT return octetstring { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.octetstringVal)) { |
| f_EPTF_Var_error(log2str("Octetstring value is requested for the EPTF_Var[",pl_idx,"] which has non-octetstring content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.octetstringVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.octetstringVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != octetstringType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not an octetstringType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefOctetstring(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return ''O; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getHexstringValue |
| // |
| // Purpose: |
| // Returns the value as a hexstring of a direct EPTF_Var or the dereffed value of a referenced hexstringType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *hexstring* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a hexstring referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getHexstringValue(in integer pl_idx) runs on EPTF_Var_CT return hexstring { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.hexstringVal)) { |
| f_EPTF_Var_error(log2str("Hexstring value is requested for the EPTF_Var[",pl_idx,"] which has non-hexstring content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.hexstringVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.hexstringVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != hexstringType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not a hexstringType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefHexstring(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return ''H; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getBitstringValue |
| // |
| // Purpose: |
| // Returns the value as a bitstring of a direct EPTF_Var or the dereffed value of a referenced bitstringType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *bitstring* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a bitstring referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getBitstringValue(in integer pl_idx) runs on EPTF_Var_CT return bitstring { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.bitstringVal)) { |
| f_EPTF_Var_error(log2str("Bitstring value is requested for the EPTF_Var[",pl_idx,"] which has non-bitstring content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.bitstringVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.bitstringVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != bitstringType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not a bitstringType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefBitstring(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return ''B; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getIntegerlistValue |
| // |
| // Purpose: |
| // Returns the value as an EPTF_IntegerList of a direct EPTF_Var or the dereffed value of a referenced integerlistType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *EPTF_IntegerList* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a EPTF_IntegerList referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getIntegerlistValue(in integer pl_idx) runs on EPTF_Var_CT return EPTF_IntegerList { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.integerlistVal)) { |
| f_EPTF_Var_error(log2str("Integerlist value is requested for the EPTF_Var[",pl_idx,"] which has non-integerlist content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.integerlistVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.integerlistVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != integerlistType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not an integerlistType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefIntegerlist(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return {}; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getFloatlistValue |
| // |
| // Purpose: |
| // Returns the value as an EPTF_FloatList of a direct EPTF_Var or the dereffed value of a referenced floatlistType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *EPTF_FloatList* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a EPTF_FloatList referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getFloatlistValue(in integer pl_idx) runs on EPTF_Var_CT return EPTF_FloatList { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.floatlistVal)) { |
| f_EPTF_Var_error(log2str("Floatlist value is requested for the EPTF_Var[",pl_idx,"] which has non-floatlist content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.floatlistVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.floatlistVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != floatlistType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not an floatlistType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefFloatlist(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return {}; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getCharstringlistValue |
| // |
| // Purpose: |
| // Returns the value as an EPTF_CharstringList of a direct EPTF_Var or the dereffed value of a referenced CharstringlistType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *EPTF_CharstringList* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a EPTF_CharstringList referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getCharstringlistValue(in integer pl_idx) runs on EPTF_Var_CT return EPTF_CharstringList { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.charstringlistVal)) { |
| f_EPTF_Var_error(log2str("Charstringlist value is requested for the EPTF_Var[",pl_idx,"] which has non-charstringlist content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.charstringlistVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.charstringlistVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != charstringlistType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not an charstringlistType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefCharstringlist(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return {}; // just to remove the warning, this is never executed |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getStatusLEDValue |
| // |
| // Purpose: |
| // Returns the value as an EPTF_StatusLED of a direct EPTF_Var or the dereffed value of a referenced statusLEDType EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *EPTF_StatusLED* - the (dereferenced) value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a EPTF_StatusLED referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getStatusLEDValue(in integer pl_idx) runs on EPTF_Var_CT return EPTF_StatusLED { |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| if (not ischosen(vl_currentContent.statusLEDVal)) { |
| f_EPTF_Var_error(log2str("StatusLED value is requested for the EPTF_Var[",pl_idx,"] which has non-statusLED content")); |
| //f_EPTF_Base_stop(); |
| } |
| return vl_currentContent.statusLEDVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| return v_EPTF_Vars[pl_idx].content.direct.statusLEDVal; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != statusLEDType) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] content is not a statusLEDType reference")); |
| //f_EPTF_Base_stop(); |
| } |
| return f_EPTF_Var_derefStatusLED(v_EPTF_Vars[pl_idx].content.reference.valueRef); |
| } |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] has invalid content")); |
| //f_EPTF_Base_stop(); |
| return {color:=led_black, text := ""}; // just to remove the warning, this is never executed |
| } |
| //... |
| |
| /* use f_EPTF_Var_setContent instead! |
| // set the intValue of a direct EPTF_Var or the dereffed value of a referenced intType EPTF_Var |
| private function f_EPTF_Var_setIntValue(in integer pl_idx, in integer pl_newIntValue) runs on EPTF_Var_CT { |
| if (ischosen(v_EPTF_Vars[pl_idx].content.direct)) { |
| v_EPTF_Vars[pl_idx].content.direct.intVal := pl_newIntValue; |
| return; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| if (v_EPTF_Vars[pl_idx].content.reference.refType != intType) { |
| log("ERROR: ", "EPTF_Var[",pl_idx,"] content is not and intType reference"); |
| f_EPTF_Base_stop(); |
| } |
| f_EPTF_Var_modifyIntRefValue(v_EPTF_Vars[pl_idx].content.reference.valueRef, pl_newIntValue); |
| return; |
| } |
| log("ERROR: ", "EPTF_Var[",pl_idx,"] has invalid content"); |
| f_EPTF_Base_stop(); |
| }*/ |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getContent |
| // |
| // Purpose: |
| // Returns the content of an EPTF_Var or the dereffed content of a referenced EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_currentContent - *out* <EPTF_Var_DirectContent> - the content of the EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getContent(in integer pl_idx, out EPTF_Var_DirectContent pl_currentContent) runs on EPTF_Var_CT { |
| var EPTF_Var_DirectContent vl_prevContent; |
| f_EPTF_Var_content2direct(v_EPTF_Vars[pl_idx].content,vl_prevContent); |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,pull)) { |
| v_EPTF_Vars[pl_idx].provider.remote.routeUpdateCounter := v_EPTF_Vars[pl_idx].provider.remote.routeUpdateCounter + 1; |
| var boolean vl_useOriginalProvider := v_EPTF_Vars[pl_idx].provider.remote.routeUpdateCounter >= cg_EPTF_Var_routeUpdatePeriod; |
| if (vl_useOriginalProvider) { |
| v_EPTF_Vars[pl_idx].provider.remote.routeUpdateCounter:=0; |
| } |
| var EPTF_Var_Ref vl_provider; |
| var boolean vl_prevSubsCanAdjust := v_EPTF_Vars[pl_idx].subsCanAdjust; |
| var boolean vl_getContentResult; |
| var boolean vl_subsCanAdjust; |
| if (v_EPTF_Vars[pl_idx].provider.remote.varRef.idx != -1 and not vl_useOriginalProvider) { |
| vl_getContentResult := f_EPTF_Var_getRemoteContentById( |
| pl_remoteCompRef := v_EPTF_Vars[pl_idx].provider.remote.varRef.compRef, |
| pl_remoteVarId := { idx := v_EPTF_Vars[pl_idx].provider.remote.varRef.idx}, |
| pl_content := pl_currentContent, |
| pl_provider := vl_provider, |
| pl_subsCanAdjust := vl_subsCanAdjust |
| ); |
| } else { |
| vl_getContentResult := f_EPTF_Var_getRemoteContentById( |
| pl_remoteCompRef := v_EPTF_Vars[pl_idx].provider.remote.compRef, |
| pl_remoteVarId := {name := v_EPTF_Vars[pl_idx].provider.remote.name}, |
| pl_content := pl_currentContent, |
| pl_provider := vl_provider, |
| pl_subsCanAdjust := vl_subsCanAdjust |
| ); |
| } |
| if (vl_getContentResult) { |
| //initialize the local var: |
| if (ischosen(v_EPTF_Vars[pl_idx].content.invalid)) { |
| v_EPTF_Vars[pl_idx].content.direct := pl_currentContent; |
| } else { |
| f_EPTF_Var_setContent(pl_idx,pl_currentContent); |
| } |
| v_EPTF_Vars[pl_idx].subsCanAdjust := vl_subsCanAdjust; |
| if (vl_prevContent!=pl_currentContent) { |
| f_EPTF_Var_updateTimeLine(pl_idx,pl_currentContent); |
| f_EPTF_Var_callPostProcFns(pl_idx); |
| } |
| if (vl_prevSubsCanAdjust!=v_EPTF_Vars[pl_idx].subsCanAdjust) { |
| f_EPTF_Var_callSubsCanAdjustNotifyFns(pl_idx); |
| } |
| if (vl_provider != {null,-1}) { |
| v_EPTF_Vars[pl_idx].provider.remote.varRef := vl_provider; |
| } |
| } else { |
| // return the cached value if remote value is not available: |
| pl_currentContent := vl_prevContent; |
| } |
| } else { |
| if (f_EPTF_Var_checkLocalSubscriptionMode(pl_idx,pull)) { |
| // calculate the value: |
| // f_EPTF_Var_refreshContent(pl_idx); |
| // TODO: Use refreshContent for the var or the providers only? |
| // var EPTF_Var_DirectContent vl_contentTmp; |
| // // register update for the pull mode providers, do not recalculate: |
| // for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList); i:=i+1) { |
| // if (f_EPTF_Var_checkSubscriptionMode(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList[i],pull) |
| // or f_EPTF_Var_checkLocalSubscriptionMode(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList[i],pull) |
| // ) { |
| // //f_EPTF_Var_refreshContent(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList[i]); |
| // f_EPTF_Var_getContent(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList[i], vl_contentTmp); |
| // } |
| // } |
| f_EPTF_Var_callCalcFn(pl_idx,pl_currentContent); |
| if (vl_prevContent!=pl_currentContent) { |
| f_EPTF_Var_setContent(pl_idx,pl_currentContent); |
| f_EPTF_Var_updateTimeLine(pl_idx,pl_currentContent); |
| f_EPTF_Var_callPostProcFns(pl_idx); |
| } |
| //f_EPTF_Var_refreshContent(pl_idx); |
| } |
| f_EPTF_Var_content2direct(v_EPTF_Vars[pl_idx].content,pl_currentContent); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_setContent |
| // |
| // Purpose: |
| // Sets the content of an EPTF_Var or the dereffed content of a referenced EPTF_Var without invoking the refresh mechanism |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_newContent - *in* <EPTF_Var_DirectContent> - the content of the EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // The refresh mechanism is not invoked. The value is just copied into the content, nothing else. |
| // To invoke automatic refresh, use the function <f_EPTF_Var_adjustContent> instead. |
| // This function allows the user to modify the value of an EPTF Variable several |
| // times before activating the refresh mechanism. When the final value is set, use the function <f_EPTF_Var_refreshContent> |
| // to notify the library about the refresh. |
| // |
| // Type checking is performed in the function <f_EPTF_Var_direct2content> |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_setContent(in integer pl_idx, in EPTF_Var_DirectContent pl_newContent) runs on EPTF_Var_CT { |
| if (not f_EPTF_Var_direct2content(pl_newContent,v_EPTF_Vars[pl_idx].content)) { |
| f_EPTF_Var_error(log2str("ERROR:","Cannot set direct content ",pl_newContent," into variable #", pl_idx, " : ", v_EPTF_Vars[pl_idx])); |
| //f_EPTF_Base_stop(); |
| }; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_updateRef |
| // |
| // Purpose: |
| // Updates the reference of the EPTF Variable to the new reference |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_newReference - *in* *octetstring* - the new reference to the component variable |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // If the content of the EPTF Variable is not a reference it does not do anything. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_updateRef(in integer pl_idx, in octetstring pl_newReference) runs on EPTF_Var_CT { |
| if (ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| v_EPTF_Vars[pl_idx].content.reference.valueRef := pl_newReference; |
| } |
| } |
| |
| } // group VaribleCreationValueAssignment |
| |
| /////////////////////////////////////////////////////////// |
| // Group: LookUp |
| // |
| // Purpose: |
| // Functions to look up an EPTF Variable based on name, component variable, etc. |
| // |
| // Detailed Comments: |
| // Some of the functions need hashmap to be enabled |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group LookUp { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getId |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable name. returns -1 if not found |
| // |
| // Parameters: |
| // pl_name - *in* *charstring* - name of the variable |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // Uses hashmap if enabled, otherwise for-cycle |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getId(in charstring pl_name) runs on EPTF_Var_CT return integer { |
| if (pl_name=="") {return -1;} |
| if (v_EPTF_Var_enableName2Id == false) { |
| // search using for cycle: |
| return f_EPTF_Var_lookupName(pl_name); |
| } |
| var integer vl_idx; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_Var_Hashmap_Name2Id, pl_name, vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getName |
| // |
| // Purpose: |
| // Returns the name for the EPTF variable with the given idx. |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - idx of the variable |
| // |
| // Return Value: |
| // *charstring* - the name of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getName(in integer pl_idx) runs on EPTF_Var_CT return charstring { |
| return v_EPTF_Vars[pl_idx].name; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_intCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* *integer* - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_intCompRef2Id(inout integer pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({intType,f_EPTF_Var_getIntRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getIntRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_Id2CompRef |
| // |
| // Purpose: |
| // Returns the reference for the EPTF variable with the given idx. |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - idx of the variable |
| // |
| // Return Value: |
| // <EPTF_Var_ReferencedContent> - the reference to the component variable referred by the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_Id2CompRef(in integer pl_idx) runs on EPTF_Var_CT return EPTF_Var_ReferencedContent { |
| if(ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| return v_EPTF_Vars[pl_idx].content.reference; |
| } |
| return {intType, ''O}; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_floatCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* *float* - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_floatCompRef2Id(inout float pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({floatType,f_EPTF_Var_getFloatRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getFloatRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_boolCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* *boolean* - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_boolCompRef2Id(inout boolean pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({boolType,f_EPTF_Var_getBoolRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getBoolRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_charstringCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* *integer* - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_charstringCompRef2Id(inout charstring pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({charstringType,f_EPTF_Var_getCharstringRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getCharstringRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_octetstringCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* *octetstring* - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_octetstringCompRef2Id(inout octetstring pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({octetstringType,f_EPTF_Var_getOctetstringRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getOctetstringRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_hexstringCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* *hexstring* - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_hexstringCompRef2Id(inout hexstring pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({hexstringType,f_EPTF_Var_getHexstringRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getHexstringRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_bitstringCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* *bitstring* - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_bitstringCompRef2Id(inout bitstring pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({bitstringType,f_EPTF_Var_getBitstringRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getBitstringRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_integerlistCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* <EPTF_IntegerList> - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_integerlistCompRef2Id(inout EPTF_IntegerList pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({integerlistType,f_EPTF_Var_getIntegerlistRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getIntegerlistRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_floatlistCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* <EPTF_FloatList> - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_floatlistCompRef2Id(inout EPTF_FloatList pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({floatlistType,f_EPTF_Var_getFloatlistRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getFloatlistRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_charstringlistCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* <EPTF_CharstringList> - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_charstringlistCompRef2Id(inout EPTF_CharstringList pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({charstringlistType,f_EPTF_Var_getCharstringlistRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getCharstringlistRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| |
| ////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_statusLEDCompRef2Id |
| // |
| // Purpose: |
| // Returns the idx for the EPTF variable that refers to the given component variable. returns -1 if not found |
| // |
| // Parameters: |
| // pl_compVar - *inout* <EPTF_StatusLED> - the component variable for which the referring EPTF Variable should be found |
| // |
| // Return Value: |
| // *integer* - the idx of the EPTF_Var |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function is one of the type-specific functions that are implemented for |
| // all value types. |
| // The inout for pl_compVar is needed so it is not copied |
| // (which would result in incorrect memory address for the EPTF variable). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_statusLEDCompRef2Id(inout EPTF_StatusLED pl_compVar) runs on EPTF_Var_CT return integer { |
| if (v_EPTF_Var_enableCompRef2Id == false) { |
| return f_EPTF_Var_lookupCompRef({statusLEDType,f_EPTF_Var_getStatusLEDRef(pl_compVar)}); // hasmap is not enabled |
| } |
| var integer vl_idx; |
| if (f_EPTF_oct2int_HashMap_Find(v_EPTF_Var_Hashmap_CompRef2Id, f_EPTF_Var_getStatusLEDRef(pl_compVar), vl_idx)) { |
| return vl_idx; |
| } |
| return -1; |
| } |
| //... |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getValueRef |
| // |
| // Purpose: |
| // Returns the valueRef of a referenced EPTF_Var |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *octetstring* - the reference to the value of the EPTF variable |
| // |
| // Errors: |
| // If the EPTF Variable is not a referenced variable is stops with an error |
| // |
| // Detailed Comments: |
| // |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getValueRef(in integer pl_idx) runs on EPTF_Var_CT return octetstring { |
| if (not ischosen(v_EPTF_Vars[pl_idx].content.reference)) { |
| f_EPTF_Var_error(log2str("EPTF_Var[",pl_idx,"] is not a referenced variable")); |
| //f_EPTF_Base_stop(); |
| } |
| return v_EPTF_Vars[pl_idx].content.reference.valueRef; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_directContent2RefType |
| // |
| // Purpose: |
| // Converts type information in a <EPTF_Var_DirectContent> to the enumerated type <EPTF_Var_RefType> |
| // |
| // Parameters: |
| // pl_directContent - <EPTF_Var_DirectContent> - the direct content to convert |
| // |
| // Return Value: |
| // <EPTF_Var_RefType> - the type as an enumerated |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_directContent2RefType(in EPTF_Var_DirectContent pl_directContent) runs on EPTF_Var_CT return EPTF_Var_RefType { |
| if (ischosen(pl_directContent.intVal)) { |
| return intType; |
| } |
| if (ischosen(pl_directContent.floatVal)) { |
| return floatType; |
| } |
| if (ischosen(pl_directContent.boolVal)) { |
| return boolType; |
| } |
| if (ischosen(pl_directContent.charstringVal)) { |
| return charstringType; |
| } |
| if (ischosen(pl_directContent.octetstringVal)) { |
| return octetstringType; |
| } |
| if (ischosen(pl_directContent.hexstringVal)) { |
| return hexstringType; |
| } |
| if (ischosen(pl_directContent.bitstringVal)) { |
| return bitstringType; |
| } |
| if (ischosen(pl_directContent.integerlistVal)) { |
| return integerlistType; |
| } |
| if (ischosen(pl_directContent.floatlistVal)) { |
| return floatlistType; |
| } |
| if (ischosen(pl_directContent.charstringlistVal)) { |
| return charstringlistType; |
| } |
| if (ischosen(pl_directContent.statusLEDVal)) { |
| return statusLEDType; |
| } |
| //... |
| f_EPTF_Base_stop(); |
| // this is never reached: |
| return intType; |
| } |
| |
| } // group LookUp |
| |
| /////////////////////////////////////////////////////////// |
| // Group: Subscribing |
| // |
| // Purpose: |
| // Functions to subscribe/unsubscribe to other EPTF Variables |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group Subscribing { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeLocal |
| // |
| // Purpose: |
| // Sets the local provider for the subscriber variable pl_idx |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_localProvider - *in* <EPTF_Var_ProviderLocal> - the local provider |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeLocal(in integer pl_idx, in EPTF_Var_ProviderLocal pl_localProvider) runs on EPTF_Var_CT { |
| // create var automatically? subscrLocalRef? |
| if (not ischosen(v_EPTF_Vars[pl_idx].provider.empty)) { |
| f_EPTF_Var_error(log2str("Cannot set local provider for EPTF_Var[",pl_idx,"]. It has already a provider")); |
| //f_EPTF_Base_stop(); |
| } |
| v_EPTF_Vars[pl_idx].provider := {local:=pl_localProvider}; |
| v_EPTF_Vars[pl_idx].subsCanAdjust := false; |
| f_EPTF_Var_addLocalSubscriber(pl_idx, pl_localProvider.calcFn.argList); |
| f_EPTF_Var_refreshContent(pl_idx); |
| f_EPTF_Var_callSubsCanAdjustNotifyFns(pl_idx); |
| f_EPTF_Var_setSubsCanAdjustInAllSubscribers(pl_idx); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addLocalProviders |
| // |
| // Purpose: |
| // Adds the local providers to the variable with ID pl_idx |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_providerList - *in* <EPTF_IntegerList> - the local providers to add |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // The varible should already have local providers. If it does not, |
| // this function stops with an error |
| // |
| // Detailed Comments: |
| // This function can be used to add additional local providers to a |
| // variable that is a local subscriber already (i.e. <f_EPTF_Var_subscribeLocal> |
| // was already called) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_addLocalProviders(in integer pl_idx, in EPTF_IntegerList pl_providerList) |
| runs on EPTF_Var_CT |
| { |
| f_EPTF_Base_assert(%definitionId&": not a local subscription.", ischosen(v_EPTF_Vars[pl_idx].provider.local)); |
| for(var integer i:=0; i<sizeof(pl_providerList); i:=i+1) { |
| v_EPTF_Vars[pl_idx].provider.local.calcFn.argList |
| [sizeof(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList)] := pl_providerList[i]; |
| } |
| f_EPTF_Var_addLocalSubscriber(pl_idx, pl_providerList); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeLocalProviders |
| // |
| // Purpose: |
| // Removes the local providers from the variable with ID pl_idx |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_providerList - *in* <EPTF_IntegerList> - the local providers to remove |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // The varible should already have local providers. If it does not, |
| // this function stops with an error |
| // |
| // Detailed Comments: |
| // This function can be used to remove the given local providers from a |
| // variable that is a local subscriber already (i.e. <f_EPTF_Var_subscribeLocal> |
| // was already called) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_removeLocalProviders(in integer pl_idx, in EPTF_IntegerList pl_providerList) |
| runs on EPTF_Var_CT |
| { |
| f_EPTF_Base_assert(%definitionId&": not a local subscription.", ischosen(v_EPTF_Vars[pl_idx].provider.local)); |
| f_EPTF_Var_removeLocalSubscriber(pl_idx, pl_providerList); |
| var EPTF_IntegerList vl_old := v_EPTF_Vars[pl_idx].provider.local.calcFn.argList; |
| v_EPTF_Vars[pl_idx].provider.local.calcFn.argList := {}; |
| for(var integer i:=0; i<sizeof(vl_old); i:=i+1) { |
| var boolean vl_found := false; |
| for(var integer j:=0; j<sizeof(pl_providerList); j:=j+1) { |
| if(vl_old[i] == pl_providerList[j]) { vl_found := true; break;} |
| } |
| if(not vl_found) { |
| v_EPTF_Vars[pl_idx].provider.local.calcFn.argList |
| [sizeof(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList)] := vl_old[i]; |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_isPresentRemote |
| // |
| // Purpose: |
| // Checks if a variable is present on a remote component |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote variable's component reference |
| // pl_remoteVarName - *in* *charstring* - the remote variable's name |
| // |
| // Return Value: |
| // boolean - true if present, false if not |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_isPresentRemote(in EPTF_Var_CT pl_remoteCompRef, in charstring pl_remoteVarName) runs on EPTF_Var_CT |
| return boolean { |
| |
| var integer vl_blockingFlagIdx := f_EPTF_setNewboolean(v_booleanPool,false); |
| var integer vl_responseIdx := f_EPTF_setNewboolean(v_booleanPool,false); |
| |
| f_EPTF_Var_addConnection(pl_remoteCompRef); |
| f_EPTF_Var_send( |
| {isPresentRemote:={ |
| pl_remoteVarName, |
| vl_blockingFlagIdx, |
| vl_responseIdx |
| }}, |
| pl_remoteCompRef |
| ); |
| timer t_minWait := 0.0; // zero wait |
| timer t_maxWait := v_Var_maxWaitTime; // maximum wait |
| t_minWait.start; |
| t_maxWait.start; |
| // wait until response is received: |
| alt { |
| [f_EPTF_getValueboolean(v_booleanPool,vl_blockingFlagIdx)] t_minWait.timeout; |
| [] t_maxWait.timeout { |
| f_EPTF_Var_warning(log2str("No response received for isPresent for: ", pl_remoteVarName, " from: ", pl_remoteCompRef)); |
| } |
| } |
| // response is received here, boolean at vl_responseIdx is set to the appropriate value |
| var boolean vl_isPresentResponse := f_EPTF_getValueboolean(v_booleanPool,vl_responseIdx); |
| // remove the bool from the pool: |
| f_EPTF_deleteboolean(v_booleanPool,vl_blockingFlagIdx); |
| f_EPTF_deleteboolean(v_booleanPool,vl_responseIdx); |
| return vl_isPresentResponse; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemote |
| // |
| // Purpose: |
| // Creates a new EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" (if not already subscribed) |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // If pl_localName is empty ("") only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| // If subscribing realtime to a local variable and pl_localName is not given or it is the same as pl_remoteProviderVarName, new variable |
| // is not created, instead the id of pl_remoteProviderVarName is returned |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemote( |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| |
| if (pl_remoteCompRef==self and pl_subscriptionMode == realtime) { |
| if (f_EPTF_Var_getId(pl_remoteProviderVarName) == -1) { |
| // remote var does not exist |
| pl_idx := -1; // subscribe is unsuccessful |
| return; |
| } |
| if (pl_remoteProviderVarName==pl_localName or pl_localName=="") { |
| //remote var is on the local component and subscription is realtime and local name is not given or is the same => return the local var |
| pl_idx := f_EPTF_Var_getId(pl_remoteProviderVarName); |
| return; |
| } else { |
| // local name is given but does not match with the already existing local var |
| f_EPTF_Var_debug(%definitionId& |
| ": Subscribing realtime to a local variable with a different name (existing:"&pl_remoteProviderVarName&", given:"&pl_localName&") might cause performance degradation."& |
| " For optimal performance pl_localName should not be specified.") |
| } |
| } |
| |
| // zero or negative pl_refreshRate-s are treated as zero (default refresh method) |
| var integer vl_refreshRate := 0; |
| if (pl_refreshRate>0) { |
| vl_refreshRate := pl_refreshRate; |
| } |
| f_EPTF_Var_findSubscription(pl_remoteCompRef,pl_remoteProviderVarName,pl_idx); |
| if (pl_idx != -1) { |
| f_EPTF_Var_debug(log2str("Already subscribed for ", pl_remoteCompRef,":",pl_remoteProviderVarName, " by v_EPTF_Vars[",pl_idx,"]: ",v_EPTF_Vars[pl_idx])); |
| if ((pl_remoteProviderVarName==pl_localName or pl_localName=="" |
| or pl_localName==v_EPTF_Vars[pl_idx].name) and vl_refreshRate == f_EPTF_Var_getVarRefreshRate(pl_idx)) { |
| return; // using the existing variable (the autoGenerated name is the name of the existing variable) |
| } |
| // // subscribe to the local variable: |
| // // FIXME: this requires more port communication than if subscribing directly to the remote var twice: |
| // This is better: comp1/1->comp2/2 comp1/1->comp2/3 (needs 1 message) than comp1/1->comp2/2->comp2/3 needs 2 messages |
| // f_EPTF_Var_subscribeRemote(self,v_EPTF_Vars[pl_idx].name,pl_subscriptionMode,pl_idx,pl_localName); |
| // |
| // no return: creating new subscriber variable |
| } |
| if (pl_subscriptionMode==pull and pl_localName=="") { |
| // auto-generate name for the pull mode subscriber |
| pl_localName := "PullSubscrOf."&log2str(pl_remoteCompRef)&"."&pl_remoteProviderVarName; |
| pl_idx := f_EPTF_Var_getId(pl_localName); |
| if (pl_idx!=-1) { |
| return; // already subscribed |
| } |
| } |
| |
| f_EPTF_Var_addNew(pl_idx,pl_localName); |
| v_EPTF_Vars[pl_idx].provider := {remote:={pl_remoteProviderVarName, pl_remoteCompRef, {pl_remoteCompRef,-1},pl_subscriptionMode,vl_refreshRate,empty,0}}; |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_Var_Hashmap_Provider2Id,log2str(pl_remoteCompRef)&"."&pl_remoteProviderVarName,pl_idx); |
| |
| if (pl_subscriptionMode==pull) { |
| // This is not needed if No request is sent and there is no response for pull type subscription!!!: |
| f_EPTF_Var_sendSubscribe(pl_idx, pl_remoteCompRef, pl_remoteProviderVarName, pl_subscriptionMode, 0, -1); |
| return; // do not have to block execution for pull mode subscription |
| } |
| |
| // create a blocking flag: |
| timer t_minWait := 0.0; // zero wait |
| timer t_maxWait := v_Var_maxWaitTime; // maximum wait |
| var integer v_blockingFlagIdx := f_EPTF_setNewboolean(v_booleanPool,false); |
| f_EPTF_Var_sendSubscribe(pl_idx, pl_remoteCompRef, pl_remoteProviderVarName, pl_subscriptionMode, vl_refreshRate, v_blockingFlagIdx); |
| t_minWait.start; |
| t_maxWait.start; |
| |
| // block execution until subscribeResp arrives: |
| alt { |
| [f_EPTF_getValueboolean(v_booleanPool,v_blockingFlagIdx)] t_minWait.timeout; |
| [] t_maxWait.timeout { |
| //HM27497 |
| //It must be an error instead of warning |
| f_EPTF_Var_error(log2str("No response received for subscribe with data: ", pl_idx, pl_remoteCompRef, pl_remoteProviderVarName, pl_subscriptionMode, v_blockingFlagIdx)); |
| //f_EPTF_Base_stopAll(); // called by f_EPTF_Var_error |
| } |
| } |
| // here the subscribe resp was handled, which fills in the omit value, the idx, and the name |
| |
| // remove the bool from the pool: |
| f_EPTF_deleteboolean(v_booleanPool,v_blockingFlagIdx); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemote_nonBlocking |
| // |
| // Purpose: |
| // Nonblocking version of <f_EPTF_Var_subscribeRemote>. |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the original name will be reused, otherwise the variable is renamed to this name. |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // pl_respHandler - *in* <EPTF_Var_resubscribeRemoteResp_handler> - subscribe response handler callback function |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // |
| // Detailed Comments: |
| // It creates an "invalid" variable in order to call f_EPTF_Var_resubscribeRemote which does not block execution until resubscription response is received. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemote_nonBlocking( |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1, |
| in EPTF_Var_resubscribeRemoteResp_handler pl_respHandler := cg_EPTF_Var_resubscribeRemoteResp_handler_null |
| ) runs on EPTF_Var_CT { |
| |
| var integer vl_varIdx; |
| f_EPTF_Var_addNew(vl_varIdx,pl_localName); |
| |
| f_EPTF_Var_resubscribeRemote( |
| pl_remoteCompRef := pl_remoteCompRef, |
| pl_remoteProviderVarName := pl_remoteProviderVarName, |
| pl_subscriptionMode := pl_subscriptionMode, |
| pl_idx := vl_varIdx, |
| pl_localName := pl_localName, |
| pl_refreshRate := pl_refreshRate, |
| pl_respHandler := pl_respHandler |
| ) |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_resubscribeRemote |
| // |
| // Purpose: |
| // Resubscribes an existing EPTF Variable to the remote provider (provider on a remote component) |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the original name will be reused, otherwise the variable is renamed to this name. |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // pl_respHandler - *in* <EPTF_Var_resubscribeRemoteResp_handler> - subscribe response handler callback function |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // If pl_localName is empty ("") only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns immediately |
| // This function does not block execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_resubscribeRemote( |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| in integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1, |
| in EPTF_Var_resubscribeRemoteResp_handler pl_respHandler := cg_EPTF_Var_resubscribeRemoteResp_handler_null |
| ) runs on EPTF_Var_CT { |
| |
| if (pl_remoteCompRef==self) { |
| if (f_EPTF_Var_getId(pl_remoteProviderVarName) == -1) { |
| // remote var does not exist |
| // resubscribe is unsuccessful |
| if(pl_respHandler.handlerFn != null) { |
| pl_respHandler.handlerFn.apply(pl_idx,false,pl_respHandler.argList); |
| } |
| return; |
| } |
| if (pl_remoteProviderVarName==f_EPTF_Var_getName(pl_idx)) { |
| // update the name: |
| if (pl_localName != "") { |
| v_EPTF_Vars[pl_idx].name := pl_localName; |
| } |
| if (pl_subscriptionMode != realtime) { |
| f_EPTF_Var_debug(%definitionId&": Resubscribing to the same variable in no-realtime mode would result in an infinite loop. Resubscribe is not done to variable "&pl_remoteProviderVarName); |
| if(pl_respHandler.handlerFn != null) { |
| pl_respHandler.handlerFn.apply(pl_idx,false,pl_respHandler.argList); |
| } |
| return; |
| } |
| //remote var is the same as the var to be subscribed => do nothing for realtime mode |
| if(pl_respHandler.handlerFn != null) { |
| pl_respHandler.handlerFn.apply(pl_idx,true,pl_respHandler.argList); // resubscribe is successful |
| } |
| return; |
| } else { |
| if (pl_subscriptionMode == realtime) { |
| f_EPTF_Var_debug(%definitionId&": Resubscribing to a local variable in realtime mode results in performance degradation."); |
| } |
| } |
| } |
| |
| if( (f_EPTF_Var_checkSubscriptionMode(pl_idx,pl_subscriptionMode) or f_EPTF_Var_checkSubscriptionMode(pl_idx,pull) or pl_subscriptionMode == pull) and |
| ischosen(v_EPTF_Vars[pl_idx].provider.remote) and |
| v_EPTF_Vars[pl_idx].provider.remote.compRef == pl_remoteCompRef and |
| v_EPTF_Vars[pl_idx].provider.remote.name==pl_remoteProviderVarName) { |
| if(pl_respHandler.handlerFn != null) { |
| pl_respHandler.handlerFn.apply(pl_idx,true,pl_respHandler.argList); // resubscribe is successful |
| } |
| return; // already subscribed to the same var |
| } |
| |
| if (not ischosen(v_EPTF_Vars[pl_idx].provider.empty)) { |
| f_EPTF_Var_error(log2str("Cannot resubscribe the variable #",pl_idx," ",v_EPTF_Vars[pl_idx].name, |
| " to variable ",pl_remoteProviderVarName," on component ",pl_remoteCompRef," with subscription mode ",pl_subscriptionMode,": It has a provider already: ",v_EPTF_Vars[pl_idx].provider,". Please unsubscribe it first.")); |
| } |
| |
| // zero or negative pl_refreshRate-s are treated as zero (default refresh method) |
| var integer vl_refreshRate := 0; |
| if (pl_refreshRate>0) { |
| vl_refreshRate := pl_refreshRate; |
| } |
| |
| // FIXME: do we need this? : |
| // if (pl_subscriptionMode==pull and pl_localName=="") { |
| // // auto-generate name for the pull mode subscriber |
| // pl_localName := "PullSubscrOf."&log2str(pl_remoteCompRef)&"."&pl_remoteProviderVarName; |
| // } |
| |
| // update the name: |
| if (pl_localName != "") { |
| v_EPTF_Vars[pl_idx].name := pl_localName; |
| } |
| v_EPTF_Vars[pl_idx].provider := {remote:={pl_remoteProviderVarName, pl_remoteCompRef, {pl_remoteCompRef,-1},pl_subscriptionMode,vl_refreshRate,empty,0}}; |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_Var_Hashmap_Provider2Id,log2str(pl_remoteCompRef)&"."&pl_remoteProviderVarName,pl_idx); |
| |
| // if (pl_subscriptionMode==pull) { |
| // //call handler |
| // if(pl_respHandler.handlerFn != null) { |
| // pl_respHandler.handlerFn.apply(pl_idx,true,pl_respHandler.argList); // resubscribe is successful |
| // } |
| // return; // No request is sent and there is no response for pull type resubscription!!! |
| // } |
| |
| // // create a blocking flag: |
| // timer t_minWait := 0.0; // zero wait |
| // timer t_maxWait := v_Var_maxWaitTime; // maximum wait |
| // t_minWait.start; |
| // t_maxWait.start; |
| |
| // store the subscribe response handler function if it is not null |
| if (pl_respHandler.handlerFn != null) { |
| v_EPTF_Var_resubscribeRemoteResp_handler_DB[pl_idx] := pl_respHandler; |
| } |
| f_EPTF_Var_sendSubscribe_nonBlocking(pl_idx, pl_remoteCompRef, pl_remoteProviderVarName, pl_subscriptionMode, vl_refreshRate); |
| |
| // // block execution until subscribeResp arrives: |
| // alt { |
| // [f_EPTF_getValueboolean(v_booleanPool,v_blockingFlagIdx)] t_minWait.timeout; |
| // [] t_maxWait.timeout { |
| // f_EPTF_Var_error(log2str("No response received for subscribe with data: ", pl_idx, pl_remoteCompRef, pl_remoteProviderVarName, pl_subscriptionMode, v_blockingFlagIdx)); |
| // //f_EPTF_Base_stopAll(); // called by f_EPTF_Var_error |
| // } |
| // } |
| // // here the subscribe resp was handled, which fills in the omit value, the idx, and the name |
| // |
| // // remove the bool from the pool: |
| // f_EPTF_deleteboolean(v_booleanPool,v_blockingFlagIdx); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_isSubscribeRemoteFinished |
| // |
| // Purpose: |
| // Checks if a remote subscription is finished for an existing EPTF Variable |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // *boolean* - true if subscription is done, false if not, or invalid parameters |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_isSubscribeRemoteFinished(in integer pl_idx) runs on EPTF_Var_CT return boolean { |
| return (pl_idx!=-1 and ischosen(v_EPTF_Vars[pl_idx].provider.remote) and v_EPTF_Vars[pl_idx].provider.remote.varRef.idx != -1); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteIntRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* *integer* - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteIntRef( |
| inout integer pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {intType,f_EPTF_Var_getIntRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteFloatRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* *float* - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteFloatRef( |
| inout float pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {floatType,f_EPTF_Var_getFloatRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteBoolRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* *boolean* - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteBoolRef( |
| inout boolean pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {boolType,f_EPTF_Var_getBoolRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteCharstringRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* *charstring* - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteCharstringRef( |
| inout charstring pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {charstringType,f_EPTF_Var_getCharstringRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteOctetstringRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* *octetstring* - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteOctetstringRef( |
| inout octetstring pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {octetstringType,f_EPTF_Var_getOctetstringRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteHexstringRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* *hexstring* - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteHexstringRef( |
| inout hexstring pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {hexstringType,f_EPTF_Var_getHexstringRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteBitstringRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* *bitstring* - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteBitstringRef( |
| inout bitstring pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {bitstringType,f_EPTF_Var_getBitstringRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteIntegerlistRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* <EPTF_IntegerList> - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteIntegerlistRef( |
| inout EPTF_IntegerList pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {integerlistType,f_EPTF_Var_getIntegerlistRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteFloatlistRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* <EPTF_FloatList> - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteFloatlistRef( |
| inout EPTF_FloatList pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {floatlistType,f_EPTF_Var_getFloatlistRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteCharstringlistRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* <EPTF_CharstringList> - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteCharstringlistRef( |
| inout EPTF_CharstringList pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {charstringlistType,f_EPTF_Var_getCharstringlistRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteStatusLEDValRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable to the given component variable) |
| // |
| // Parameters: |
| // pl_compVar - *inout* <EPTF_StatusLED> - the component variable that will be used to create a reference for |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // Only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteStatusLEDValRef( |
| inout EPTF_StatusLED pl_compVar, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_ReferencedContent v_referencedContent := {statusLEDType,f_EPTF_Var_getStatusLEDRef(pl_compVar)}; |
| f_EPTF_Var_subscribeRemoteRef(v_referencedContent,pl_remoteCompRef,pl_remoteProviderVarName,pl_subscriptionMode, pl_idx,pl_localName,pl_refreshRate); // subscribe-ref with local name |
| } |
| //... |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_subscribeRemoteRef |
| // |
| // Purpose: |
| // Creates a new reference-EPTF_Var (this will be the subscriber) and subscribes it to the remote provider (provider on a remote component) |
| // (Same as the function <f_EPTF_Var_subscribeRemote>, but it creates a referenced-content EPTF Variable) |
| // |
| // Parameters: |
| // v_varReference - *in* <EPTF_Var_ReferencedContent> - the reference to a component variable to be used |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - the remote provider variable's component reference |
| // pl_remoteProviderVarName - *in* *charstring* - the remote provider variable's name |
| // pl_subscriptionMode - *in* <EPTF_Var_SubscriptionMode> - subscription mode: sampled or timeLine: buffered; realtime: non-buffered |
| // pl_idx - *out* *integer* - the idx of the new EPTF_Var |
| // pl_localName - *in* *charstring* *optional* - the name of the subscriber variable. If not specified (or "") |
| // the name will be auto-generated by the provider variable as "ProviderCompName.providerVarName" (if not already subscribed) |
| // pl_refreshRate - *in integer* - the refresh rate for the subscription. It is the multiplier of the elementary refresh period. |
| // If it is set to -1: the old refresh period is used (default) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // stops execution if the specified (or autogenerated) name is not unique |
| // |
| // Detailed Comments: |
| // If pl_localName is empty ("") only one subscriber can be created from the same component for a remote provider |
| // If there is a subscriber already, the function returns its index instead of creating |
| // a new subscriber |
| // The type-checking is performed when the subscribeResp is received in the default altstep. |
| // This function blocks execution until subscription response is received. |
| // Buffered mode means that the value of the provider will be received periodically as a time series (timeLine) or a sample (sampled) |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_subscribeRemoteRef( |
| in EPTF_Var_ReferencedContent v_varReference, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| out integer pl_idx, |
| in charstring pl_localName := "", |
| in integer pl_refreshRate := -1 |
| ) runs on EPTF_Var_CT { |
| // zero or negative pl_refreshRate-s are treated as zero (default refresh method) |
| var integer vl_refreshRate := 0; |
| if (pl_refreshRate>0) { |
| vl_refreshRate := pl_refreshRate; |
| } |
| f_EPTF_Var_findSubscription(pl_remoteCompRef,pl_remoteProviderVarName,pl_idx); |
| if (pl_idx != -1) { |
| f_EPTF_Var_debug(log2str("Already subscribed for ", pl_remoteCompRef,":",pl_remoteProviderVarName, " by v_EPTF_Vars[",pl_idx,"]: ",v_EPTF_Vars[pl_idx])); |
| if (pl_localName == "" and vl_refreshRate == f_EPTF_Var_getVarRefreshRate(pl_idx)) { |
| return; // using the existing variable (the autoGenerated name is the name of the existing variable) |
| } |
| // // subscribe to the local variable: |
| // // FIXME: this requires more port communication than if subscribing directly to the remote var twice: |
| // This is better: comp1/1->comp2/2 comp1/1->comp2/3 (needs 1 message) than comp1/1->comp2/2->comp2/3 needs 2 messages |
| // f_EPTF_Var_subscribeRemoteRef(v_varReference,self,v_EPTF_Vars[pl_idx].name,pl_subscriptionMode,pl_idx,pl_localName); |
| // |
| // no return: creating new subscriber variable |
| } |
| f_EPTF_Var_addNew(pl_idx,pl_localName); |
| v_EPTF_Vars[pl_idx].provider := {remote:={pl_remoteProviderVarName, pl_remoteCompRef,{pl_remoteCompRef,-1},pl_subscriptionMode,vl_refreshRate,empty,0}}; |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_Var_Hashmap_Provider2Id,log2str(pl_remoteCompRef)&"."&pl_remoteProviderVarName,pl_idx); |
| f_EPTF_Var_initContentRef(pl_idx,v_varReference); |
| |
| if (pl_subscriptionMode==pull) { |
| // This is not needed if No request is sent and there is no response for pull type subscription!!!: |
| f_EPTF_Var_sendSubscribe(pl_idx, pl_remoteCompRef, pl_remoteProviderVarName, pl_subscriptionMode, 0, -1); |
| return; // do not have to block execution for pull mode subscription |
| } |
| |
| // create a blocking flag: |
| timer t_minWait := 0.0; // zero wait |
| timer t_maxWait := v_Var_maxWaitTime; // maximum wait |
| var integer v_blockingFlagIdx := f_EPTF_setNewboolean(v_booleanPool,false); |
| f_EPTF_Var_sendSubscribe(pl_idx, pl_remoteCompRef, pl_remoteProviderVarName, pl_subscriptionMode, vl_refreshRate, v_blockingFlagIdx); |
| t_minWait.start; |
| t_maxWait.start; |
| |
| // block execution until subscribeResp arrives: |
| alt { |
| [f_EPTF_getValueboolean(v_booleanPool,v_blockingFlagIdx)] t_minWait.timeout; |
| [] t_maxWait.timeout { |
| f_EPTF_Var_error(log2str("No response received for subscribe with data: ", pl_idx, pl_remoteCompRef, pl_remoteProviderVarName, pl_subscriptionMode, v_blockingFlagIdx)); |
| //f_EPTF_Base_stopAll(); // called by f_EPTF_Var_error |
| } |
| } |
| // here the subscribe resp was handled, which fills in the omit value, the idx, and the name |
| |
| // remove the bool from the pool: |
| f_EPTF_deleteboolean(v_booleanPool,v_blockingFlagIdx); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_checkSubscriptionMode |
| // |
| // Purpose: |
| // Checks if the variable has the given subscription mode |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_subscriptionMode - *in* *EPTF_Var_SubscriptionMode* - the expected subscription mode |
| // |
| // Return Value: |
| // boolean - true if the variable was subscribed to a remote variable with the specified mode |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // If the provider of the variable is remote and the subscription mode is the one specified |
| // in the argument pl_subscriptionMode the function returns true, otherwise false. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_checkSubscriptionMode(in integer pl_idx, in EPTF_Var_SubscriptionMode pl_subscriptionMode) |
| runs on EPTF_Var_CT return boolean { |
| return (ischosen(v_EPTF_Vars[pl_idx].provider.remote) and pl_subscriptionMode == v_EPTF_Vars[pl_idx].provider.remote.subscriptionMode); |
| } |
| |
| private function f_EPTF_Var_checkLocalSubscriptionMode(in integer pl_idx, in EPTF_Var_SubscriptionMode pl_subscriptionMode) |
| runs on EPTF_Var_CT return boolean { |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.local)) { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList); i:=i+1) { |
| if (f_EPTF_Var_checkSubscriptionMode(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList[i],pl_subscriptionMode) |
| or f_EPTF_Var_checkLocalSubscriptionMode(v_EPTF_Vars[pl_idx].provider.local.calcFn.argList[i],pl_subscriptionMode)) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_unsubscribe |
| // |
| // Purpose: |
| // Unsubscribes the pl_ids EPTF Variable from its provider(s) |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_unsubscribe(in integer pl_idx) runs on EPTF_Var_CT { |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.local)) { |
| // removes the local-subscriber variable pl_idx from its provider list |
| f_EPTF_Var_removeLocalSubscriber(pl_idx, v_EPTF_Vars[pl_idx].provider.local.calcFn.argList); |
| v_EPTF_Vars[pl_idx].provider := { empty:= {} }; |
| f_EPTF_Var_callUnsubscribeNotifyFns(pl_idx); |
| } else if (ischosen(v_EPTF_Vars[pl_idx].provider.remote)) { |
| // unsubscribes from the remote provider (and removes the EPTF_Var (this was the subscriber)) |
| if (v_EPTF_Vars[pl_idx].provider.remote.subscriptionMode != pull) { |
| // no notification is sent to provider for pull mode subscription |
| if (v_EPTF_Vars[pl_idx].provider.remote.varRef.idx != -1) { |
| // unsubscribe only if we know the owner idx (subscribeResp arrived) |
| f_EPTF_sendUnsubscribe(pl_idx, v_EPTF_Vars[pl_idx].provider.remote.varRef, v_EPTF_Vars[pl_idx].provider.remote.subscriptionMode,v_EPTF_Vars[pl_idx].provider.remote.refreshRate); |
| } |
| } |
| var EPTF_Var_CT vl_remoteCompRef := v_EPTF_Vars[pl_idx].provider.remote.compRef; |
| var charstring vl_remoteProviderVarName :=v_EPTF_Vars[pl_idx].provider.remote.name; |
| f_EPTF_str2int_HashMap_Erase(v_EPTF_Var_Hashmap_Provider2Id,log2str(vl_remoteCompRef)&"."&vl_remoteProviderVarName); |
| v_EPTF_Vars[pl_idx].provider := { empty:= {} }; |
| f_EPTF_Var_callUnsubscribeNotifyFns(pl_idx); |
| //f_EPTF_Var_removeVar(pl_idx); |
| } else if (ischosen(v_EPTF_Vars[pl_idx].provider.empty)) { |
| // nothing to do |
| } |
| } |
| |
| } // group Subscribing |
| |
| /////////////////////////////////////////////////////////// |
| // Group: UserHandlers |
| // |
| // Purpose: |
| // Functions related to user handlers that will be called by the library |
| // at specific events like the value of a variable was updated etc. |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group UserHandlers { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_callCalcFn |
| // |
| // Purpose: |
| // Calls the calcFn function if possible, otherwise returns the current (dereferenced)content |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_retVal - *inout* <EPTF_Var_DirectContent> - the value calculated by the CalcFn function |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_callCalcFn(in integer pl_idx, inout EPTF_Var_DirectContent pl_retVal) runs on EPTF_Var_CT { |
| f_EPTF_Var_content2direct(v_EPTF_Vars[pl_idx].content,pl_retVal); |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.local)) { |
| if (v_EPTF_Vars[pl_idx].provider.local.calcFn.funcRef != null) { |
| v_EPTF_Vars[pl_idx].provider.local.calcFn.funcRef.apply(pl_idx,v_EPTF_Vars[pl_idx].provider.local.calcFn.argList,v_EPTF_Vars[pl_idx].provider.local.calcFn.nonVarArgList,pl_retVal); |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_callPostProcFns |
| // |
| // Purpose: |
| // Calls the prostProcFn functions if possible |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_callPostProcFns(in integer pl_idx) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].postProcFns); i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].postProcFns[i].funcRef != null) { |
| f_EPTF_Var_debug(log2str("Calling postProcFn of var ",pl_idx,": ", v_EPTF_Vars[pl_idx].postProcFns[i].funcRef, |
| " args: ",v_EPTF_Vars[pl_idx].postProcFns[i].argList)); |
| v_EPTF_Vars[pl_idx].postProcFns[i].funcRef.apply(pl_idx,v_EPTF_Vars[pl_idx].postProcFns[i].argList); |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addPostProcFn |
| // |
| // Purpose: |
| // Adds a new postProc function to the pl_idx variable. Checks if it had been added already |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_postProcFn - *in* <EPTF_Var_GenericFn> - the postProc function to add |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_addPostProcFn(in integer pl_idx, in EPTF_Var_GenericFn pl_postProcFn) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].postProcFns);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].postProcFns[i] == pl_postProcFn) { |
| return; // already added |
| } |
| } |
| v_EPTF_Vars[pl_idx].postProcFns[sizeof(v_EPTF_Vars[pl_idx].postProcFns)] := pl_postProcFn; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removePostProcFn |
| // |
| // Purpose: |
| // Removes the postProc function |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_postProcFn - *in* <EPTF_Var_GenericFn> - the postProc function to remove |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_removePostProcFn(in integer pl_idx, in EPTF_Var_GenericFn pl_postProcFn) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].postProcFns);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].postProcFns[i] == pl_postProcFn) { |
| v_EPTF_Vars[pl_idx].postProcFns[i] := {null,{}}; |
| return; |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_callGuardFns |
| // |
| // Purpose: |
| // Calls the guard functions. If any of them returns false, this function will return false, otherwise it'll return true |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_newContent - *in* <EPTF_Var_DirectContent> - the new value to be checked |
| // |
| // Return Value: |
| // *boolean* - true if value accepted, false if not |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_callGuardFns(in integer pl_idx, in EPTF_Var_DirectContent pl_newContent) runs on EPTF_Var_CT return boolean { |
| var boolean vl_result := true; |
| |
| // type compatibility check: |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_content2direct(v_EPTF_Vars[pl_idx].content,vl_currentContent); |
| //f_EPTF_Var_getContent(pl_idx,vl_currentContent); |
| // try to set new content into current: |
| var EPTF_Var_Content vl_content := {direct := vl_currentContent}; |
| if (not f_EPTF_Var_direct2content(pl_newContent,vl_content)) { |
| return false; |
| }; |
| |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].guardFns); i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].guardFns[i].funcRef != null) { |
| vl_result := v_EPTF_Vars[pl_idx].guardFns[i].funcRef.apply(pl_idx,v_EPTF_Vars[pl_idx].guardFns[i].argList,pl_newContent); |
| if (vl_result == false) { |
| f_EPTF_Var_warning(log2str("The guard function #",i," (",v_EPTF_Vars[pl_idx].guardFns[i],") of EPTF_Var[",pl_idx,"]: ",v_EPTF_Vars[pl_idx].name," does not accept the new value: ",pl_newContent)); |
| return false; |
| } |
| } |
| } |
| return true; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addGuardFn |
| // |
| // Purpose: |
| // Adds a new guard function to the pl_idx variable. Checks if it had been added already |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_guardFn - *in* <EPTF_Var_GuardFn> - the guard function to add |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_addGuardFn(in integer pl_idx, in EPTF_Var_GuardFn pl_guardFn) runs on EPTF_Var_CT { |
| // if the variable has a remote provider, warning is shown that the guards are not allowed: |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.remote)) { |
| f_EPTF_Var_warning(log2str(%definitionId, " Guard fn ",pl_guardFn," is ignored for " & |
| "Variable[",pl_idx,"] ", v_EPTF_Vars[pl_idx].name,": it has a remote provider." & |
| " Only the guard fns of the top-provider (owner) are called.")); |
| } |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].guardFns);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].guardFns[i] == pl_guardFn) { |
| return; // already added |
| } |
| } |
| v_EPTF_Vars[pl_idx].guardFns[sizeof(v_EPTF_Vars[pl_idx].guardFns)] := pl_guardFn; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeGuardFn |
| // |
| // Purpose: |
| // Removes the guard function |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_guardFn - *in* <EPTF_Var_GuardFn> - the guard function to remove |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_removeGuardFn(in integer pl_idx, in EPTF_Var_GuardFn pl_guardFn) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].guardFns);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].guardFns[i] == pl_guardFn) { |
| v_EPTF_Vars[pl_idx].guardFns[i] := {null,{}}; |
| return; |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_callUnsubscribeNotifyFns |
| // |
| // Purpose: |
| // Calls the unsubscribeNotifyFns functions if possible |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_callUnsubscribeNotifyFns(in integer pl_idx) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].unsubscribeNotifyFns); i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].unsubscribeNotifyFns[i].funcRef != null) { |
| v_EPTF_Vars[pl_idx].unsubscribeNotifyFns[i].funcRef.apply(pl_idx,v_EPTF_Vars[pl_idx].unsubscribeNotifyFns[i].argList); |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addUnsubscribeNotifyFn |
| // |
| // Purpose: |
| // Adds a new unsubscribe function to the pl_idx variable. Checks if it had been added already |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_unsubscribeNotifyFn - *in* <EPTF_Var_GenericFn> - the postProc function to add |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_addUnsubscribeNotifyFn(in integer pl_idx, in EPTF_Var_GenericFn pl_unsubscribeNotifyFn) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].unsubscribeNotifyFns);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].unsubscribeNotifyFns[i] == pl_unsubscribeNotifyFn) { |
| return; // already added |
| } |
| } |
| v_EPTF_Vars[pl_idx].unsubscribeNotifyFns[sizeof(v_EPTF_Vars[pl_idx].unsubscribeNotifyFns)] := pl_unsubscribeNotifyFn; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeUnsubscribeNotifyFn |
| // |
| // Purpose: |
| // Removes the unsubscribe function |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_unsubscribeNotifyFn - *in* <EPTF_Var_PostProcFn> - the postProc function to remove |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_removeUnsubscribeNotifyFn(in integer pl_idx, in EPTF_Var_GenericFn pl_unsubscribeNotifyFn) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].unsubscribeNotifyFns);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].unsubscribeNotifyFns[i] == pl_unsubscribeNotifyFn) { |
| v_EPTF_Vars[pl_idx].unsubscribeNotifyFns[i] := {null,{}}; |
| return; |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_callSubsCanAdjustNotifyFns |
| // |
| // Purpose: |
| // Calls the subsCanAdjustNotifyFn functions if possible |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_callSubsCanAdjustNotifyFns(in integer pl_idx) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns); i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[i].funcRef != null) { |
| f_EPTF_Var_debug(log2str("Calling subsCanAdjustNotifyFn of var ",pl_idx,": ", v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[i].funcRef, |
| " args: ",v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[i].argList)); |
| v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[i].funcRef.apply(pl_idx,v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[i].argList); |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addSubsCanAdjustNotifyFn |
| // |
| // Purpose: |
| // Adds a new subsCanAdjustNotify function to the pl_idx variable. Checks if it had been added already |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_subsCanAdjustNotifyFn - *in* <EPTF_Var_GenericFn> - the subsCanAdjustNotify function to add |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_addSubsCanAdjustNotifyFn(in integer pl_idx, in EPTF_Var_GenericFn pl_subsCanAdjustNotifyFn) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[i] == pl_subsCanAdjustNotifyFn) { |
| return; // already added |
| } |
| } |
| v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[sizeof(v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns)] := pl_subsCanAdjustNotifyFn; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeSubsCanAdjustNotifyFn |
| // |
| // Purpose: |
| // Removes the subsCanAdjustNotify function |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_subsCanAdjustNotifyFn - *in* <EPTF_Var_GenericFn> - the subsCanAdjustNotify function to remove |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_removeSubsCanAdjustNotifyFn(in integer pl_idx, in EPTF_Var_GenericFn pl_subsCanAdjustNotifyFn) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[i] == pl_subsCanAdjustNotifyFn) { |
| v_EPTF_Vars[pl_idx].subsCanAdjustNotifyFns[i] := {null,{}}; |
| return; |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_callSyncCallBackFns |
| // |
| // Purpose: |
| // Calls the syncCallbackFn functions if possible |
| // |
| // Parameters: |
| // pl_syncState - *in* <EPTF_Var_SyncState> - state of the sync event (begin or end) |
| // pl_refreshRateId - *in* *integer* - the refreshRateId in v_syncBuffer (default:0 default refresh rate) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_callSyncCallBackFns(in EPTF_Var_SyncState pl_syncState, in integer pl_refreshRateId := 0) runs on EPTF_Var_CT { |
| if (pl_refreshRateId>=sizeof(v_EPTF_Var_syncCallbackFns)) { |
| return; // index out of range, no callbacks for that rate |
| } |
| for(var integer i:=0; i<sizeof(v_EPTF_Var_syncCallbackFns[pl_refreshRateId]); i:=i+1) { |
| if (v_EPTF_Var_syncCallbackFns[pl_refreshRateId][i].funcRef != null) { |
| // calback function is only called at the specified sync state: |
| if (pl_syncState == v_EPTF_Var_syncCallbackFns[pl_refreshRateId][i].syncState) { |
| v_EPTF_Var_syncCallbackFns[pl_refreshRateId][i].funcRef.apply(v_EPTF_Var_syncCallbackFns[pl_refreshRateId][i].argList); |
| } |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addSyncCallBackFn |
| // |
| // Purpose: |
| // Adds a new callback to the list of syncCallBacks that will be called at the sync event before the timelines are sent. |
| // Checks if it had been added already |
| // |
| // Parameters: |
| // pl_funcRef - *in* <EPTF_Var_fcb_SyncCallbackFn> - the reference to callback function to add to the syncCallback list |
| // pl_argList - *in* <EPTF_IntegerList> - list of indexes used by the function. This arglist will be passed to funcRef as its arguments |
| // pl_syncState - *in* <EPTF_Var_SyncState> - the function is called only at this syncState. |
| // Can be only c_EPTF_Var_syncBegin, or c_EPTF_Var_syncEnd. Default: c_EPTF_Var_syncBegin |
| // pl_refreshRateId - *in* *integer* - the refreshRateId in v_syncBuffer (default:0 default refresh rate) |
| // |
| // Return Value: |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_addSyncCallBackFn( |
| in EPTF_Var_fcb_SyncCallbackFn pl_funcRef, |
| in EPTF_IntegerList pl_argList, |
| in EPTF_Var_SyncState pl_syncState := c_EPTF_Var_syncBegin, |
| in integer pl_refreshRateId := 0 |
| ) runs on EPTF_Var_CT { |
| var EPTF_Var_SyncCallbackFn vl_syncCallbackFn := { |
| pl_funcRef, |
| pl_argList, |
| pl_syncState |
| }; |
| if (pl_refreshRateId>=sizeof(v_EPTF_Var_syncCallbackFns)) { |
| v_EPTF_Var_syncCallbackFns[pl_refreshRateId] := {}; // index out of range, no callbacks for that rate |
| } |
| for(var integer i:=0; i<sizeof(v_EPTF_Var_syncCallbackFns[pl_refreshRateId]);i:=i+1) { |
| if (v_EPTF_Var_syncCallbackFns[pl_refreshRateId][i] == vl_syncCallbackFn) { |
| return; // already added |
| } |
| } |
| v_EPTF_Var_syncCallbackFns[pl_refreshRateId][sizeof(v_EPTF_Var_syncCallbackFns[pl_refreshRateId])] := vl_syncCallbackFn; |
| // schedule sync event if not scheduled (for 0 rate it is scheduled in init function): |
| if (v_syncBuffer[pl_refreshRateId].eventIdx == -1) { |
| if(f_EPTF_SchedulerComp_scheduleAction( |
| pl_when := f_EPTF_Base_getRelTimeInSecs()+int2float(v_syncBuffer[pl_refreshRateId].refreshRate)*v_minSyncInterval, |
| pl_actionHandler := refers(f_EPTF_Var_syncTimeoutHandler), |
| pl_action := {pl_refreshRateId}, |
| pl_eventIndex := v_syncBuffer[pl_refreshRateId].eventIdx |
| )) {/*remove the warning*/}; |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeSyncCallBackFn |
| // |
| // Purpose: |
| // Removes the syncCallback function |
| // |
| // Parameters: |
| // pl_syncCallbackFn - *in* <EPTF_Var_SyncCallbackFn> - the postProc function to remove |
| // pl_refreshRateId - *in* *integer* - the refreshRateId in v_syncBuffer (default:0 default refresh rate) |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_removeSyncCallBackFn(in EPTF_Var_SyncCallbackFn pl_syncCallbackFn, in integer pl_refreshRateId := 0) runs on EPTF_Var_CT { |
| if (pl_refreshRateId>=sizeof(v_EPTF_Var_syncCallbackFns)) { |
| return; // index out of range, no callbacks for that rate |
| } |
| for(var integer i:=0; i<sizeof(v_EPTF_Var_syncCallbackFns[pl_refreshRateId]);i:=i+1) { |
| if (v_EPTF_Var_syncCallbackFns[pl_refreshRateId][i] == pl_syncCallbackFn) { |
| v_EPTF_Var_syncCallbackFns[pl_refreshRateId][i] := {null,{},c_EPTF_Var_syncBegin}; |
| return; |
| } |
| } |
| } |
| |
| } // group UserHandlers |
| |
| /////////////////////////////////////////////////////////// |
| // Group: UpdateContent |
| // |
| // Purpose: |
| // Functions that will nofity the library about the value change of |
| // an EPTF Variable. |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group UpdateContent { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_refreshContent |
| // |
| // Purpose: |
| // Requests the library to recalculate the content of the EPTF_Var. |
| // Also notifies all of its subscribers about the new value |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function can be used to invoke the refresh mechanism of the library |
| // after the content of the variable was changed by the user (e.g. refrenced variables). |
| // Also for EPTF Variables with local provider the calcfn function is called |
| // Then all subscribers are notified about the value change. |
| // This function can be called for EPTF Variables with any kind of provider. |
| // But to change the value of an EPTF Variable with remote or empty provider, use the |
| // function <f_EPTF_Var_adjustContent> instead. |
| // The refresh mechanism makes it possible to update the value of all subscribers |
| // when the owner changes its value. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_refreshContent(in integer pl_idx) runs on EPTF_Var_CT { |
| var EPTF_Var_DirectContent vl_contentNew; |
| f_EPTF_Var_callCalcFn(pl_idx,vl_contentNew); |
| f_EPTF_Var_registerRefresh(pl_idx,vl_contentNew); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getSubsCanAdjust |
| // |
| // Purpose: |
| // Returns the subsCanAdjust flag for the variable. |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // boolean - the value of the subsCanAdjust flag |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getSubsCanAdjust(in integer pl_idx) |
| runs on EPTF_Var_CT |
| return boolean { |
| return v_EPTF_Vars[pl_idx].subsCanAdjust; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_setSubsCanAdjust |
| // |
| // Purpose: |
| // Sets the subsCanAdjust flag for the variable. |
| // Also notifies all of its subscribers about the new value |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_subsCanAdjust - *in* *boolean* - the new value of the subsCanAdjust flag |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // If it is called for a Variable with a local or remote provider. |
| // |
| // Detailed Comments: |
| // This function can be called for EPTF Variables without a provider (provider empty). |
| // If the new falue of the flag is the same as the current value, nothing happens. |
| // The callbacks registered by <f_EPTF_Var_addSubsCanAdjustNotifyFn> are called. |
| // All the subscribers are notified about the value change, and their callbacks are called also. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_setSubsCanAdjust(in integer pl_idx, in boolean pl_subsCanAdjust) runs on EPTF_Var_CT { |
| |
| |
| if (not ischosen(v_EPTF_Vars[pl_idx].provider.empty)) { |
| f_EPTF_Var_error(log2str("Cannot set the subsCanAdjust flag of the EPTF_Var[",pl_idx,"], it has a provider: ", v_EPTF_Vars[pl_idx])); |
| } |
| |
| if (v_EPTF_Vars[pl_idx].subsCanAdjust == pl_subsCanAdjust) { |
| return; |
| } |
| |
| v_EPTF_Vars[pl_idx].subsCanAdjust := pl_subsCanAdjust; |
| f_EPTF_Var_callSubsCanAdjustNotifyFns(pl_idx); |
| f_EPTF_Var_setSubsCanAdjustInAllSubscribers(pl_idx); |
| } |
| |
| private function f_EPTF_Var_setSubsCanAdjustInAllSubscribers(in integer pl_idx) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].subscribers); i:=i+1) { |
| f_EPTF_Var_setSubsCanAdjustInSubscriber(pl_idx, v_EPTF_Vars[pl_idx].subscribers[i]); |
| } |
| } |
| |
| private function f_EPTF_Var_setSubsCanAdjustInSubscriber(in integer pl_idx, in EPTF_Var_Subscriber pl_subscriber) runs on EPTF_Var_CT { |
| if(ischosen(pl_subscriber.local)) { |
| // subscriber is local |
| return; |
| } |
| if(ischosen(pl_subscriber.remote)) { |
| f_EPTF_Var_send( |
| {setSubsCanAdjust:={ |
| pl_subscriber.remote.varRef,v_EPTF_Vars[pl_idx].subsCanAdjust}}, |
| pl_subscriber.remote.varRef.compRef); |
| } |
| } |
| |
| // calls user handler |
| private function f_EPTF_Var_adjustContentRespHandlerForPull( |
| in integer pl_idx, |
| in EPTF_Var_DirectContent pl_content, |
| in boolean pl_result, |
| in EPTF_IntegerList pl_argList |
| ) runs on EPTF_Var_CT { |
| var integer vl_myIdx := pl_argList[0]; |
| var integer vl_respHandlerId := pl_argList[1]; |
| // call user handler: |
| var EPTF_Var_adjustContentResp_handler vl_respHandler; |
| if (f_EPTF_getEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,vl_respHandlerId,vl_respHandler)) { |
| vl_respHandler.handlerFn.apply(vl_myIdx, pl_content, pl_result, vl_respHandler.argList); |
| // release the stack: |
| f_EPTF_deleteEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,vl_respHandlerId); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_adjustContent |
| // |
| // Purpose: |
| // Requests the library to adjust the content of the EPTF_Var. |
| // Also notifies all of its subscribers about the new value |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_newContent - *in* <EPTF_Var_DirectContent> - the new value to try to set |
| // pl_respHandler - <EPTF_Var_adjustContentNack_handler> - user handler to call when the adjust is ready (i.e. when adjustResp arrives, or when the guards accept the new value) |
| // but before the value of the variable is refreshed |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // For EPTF Variables with local provider, the function stops with an error. |
| // Adjustment of calculated variables is not allowed. Call <f_EPTF_Var_refreshContent> instead. |
| // |
| // Detailed Comments: |
| // For EPTF Variables with remote provider a request is sent for its remote provider to |
| // adjust the value. If accepted, the new value is written into the content, if not, |
| // the prevoius value is set into the content. |
| // Using the adjust mechanism for EPTF Variables with remote provider too often |
| // might indicate incorrect design. |
| // |
| // For EPTF Variables with no provider the new value is checked by the guardFns |
| // before it is written into the content. |
| // |
| // After a successful adjust, all subscribers of the owner EPTF Variable |
| // are notified about the new value. Then the postProc functions are called. |
| // |
| // The adjust mechanism allows the user to modify the value of a local parameter (i.e. an EPTF variable with no provider) |
| // or to be able to modify the original EPTF Variable from a remote subscriber. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_adjustContent(in integer pl_idx, in EPTF_Var_DirectContent pl_newContent, in EPTF_Var_adjustContentResp_handler pl_respHandler := {null, {}}) runs on EPTF_Var_CT { |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.local)) { |
| f_EPTF_Var_debug(log2str("Cannot adjust the content of the EPTF_Var[",pl_idx,"]. It has a local provider! ", v_EPTF_Vars[pl_idx])); |
| if (pl_respHandler.handlerFn != null) { |
| pl_respHandler.handlerFn.apply(pl_idx, pl_newContent, false, pl_respHandler.argList); |
| } |
| return; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.empty)) { |
| // I am a "parameter", adjust allowed after the guard fns accept the new value. |
| |
| //call the guard fns: |
| var boolean vl_result := f_EPTF_Var_callGuardFns(pl_idx,pl_newContent); |
| // call the adjustResp handler: |
| if (pl_respHandler.handlerFn != null) { |
| // call the user handler: |
| pl_respHandler.handlerFn.apply(pl_idx, pl_newContent, vl_result, pl_respHandler.argList); |
| } |
| if (not vl_result) { |
| // content not accepted |
| } else { |
| // refreshContent is called to notify subscribers: |
| // and set the received content into the current: |
| f_EPTF_Var_registerRefresh(pl_idx,pl_newContent); |
| } |
| return; |
| } |
| // remote provider: |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.remote)) { |
| |
| if (v_EPTF_Vars[pl_idx].provider.remote.subscriptionMode == pull) { |
| v_EPTF_Vars[pl_idx].provider.remote.routeUpdateCounter := v_EPTF_Vars[pl_idx].provider.remote.routeUpdateCounter + 1; |
| var boolean vl_useOriginalProvider := v_EPTF_Vars[pl_idx].provider.remote.routeUpdateCounter >= cg_EPTF_Var_routeUpdatePeriod; |
| if (vl_useOriginalProvider) { |
| v_EPTF_Vars[pl_idx].provider.remote.routeUpdateCounter:=0; |
| } |
| var EPTF_Var_adjustContentResp_handler vl_respHandler; |
| // store function params into the stack (if not null): |
| var integer vl_respHandlerId := -1; |
| if (pl_respHandler.handlerFn != null) { |
| vl_respHandlerId := f_EPTF_setNewEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_respHandler); |
| vl_respHandler := {refers(f_EPTF_Var_adjustContentRespHandlerForPull), {pl_idx,vl_respHandlerId}} |
| } else { |
| vl_respHandler := pl_respHandler; |
| } |
| if (v_EPTF_Vars[pl_idx].provider.remote.varRef.idx != -1 and not vl_useOriginalProvider) { |
| f_EPTF_Var_adjustRemoteContentByIdx( |
| v_EPTF_Vars[pl_idx].provider.remote.varRef.compRef, |
| v_EPTF_Vars[pl_idx].provider.remote.varRef.idx, |
| pl_newContent, |
| vl_respHandler |
| ); |
| } else { |
| f_EPTF_Var_adjustRemoteContent( |
| v_EPTF_Vars[pl_idx].provider.remote.compRef, |
| v_EPTF_Vars[pl_idx].provider.remote.name, |
| pl_newContent, |
| vl_respHandler |
| ); |
| } |
| return; |
| } |
| |
| if (v_EPTF_Vars[pl_idx].provider.remote.varRef.idx<0) { |
| // subscription is in progress. Have to wait for response to execute the actual adjust: |
| |
| // just store the new value now: |
| f_EPTF_Var_setContent(pl_idx, pl_newContent); |
| // flag this variable that adjust was buffered: |
| v_EPTF_Vars[pl_idx].provider.remote.varRef.idx := -2; |
| // refresh will be done when subscribeResp arrives |
| return; |
| } |
| |
| if (not v_EPTF_Vars[pl_idx].subsCanAdjust) { |
| f_EPTF_Var_debug(log2str("Cannot adjust the content of the EPTF_Var[",pl_idx,"]. The subsCanAdjust flag is false! ", v_EPTF_Vars[pl_idx])); |
| if (pl_respHandler.handlerFn != null) { |
| pl_respHandler.handlerFn.apply(pl_idx, pl_newContent, false, pl_respHandler.argList); |
| } |
| return; |
| } |
| // check top provider type: |
| if (v_EPTF_Vars[pl_idx].provider.remote.topProviderType == local) { |
| f_EPTF_Var_debug(log2str("Cannot adjust the content of the EPTF_Var[",pl_idx,"]. It has a local top-provider! ", v_EPTF_Vars[pl_idx])); |
| if (pl_respHandler.handlerFn != null) { |
| pl_respHandler.handlerFn.apply(pl_idx, pl_newContent, false, pl_respHandler.argList); |
| } |
| return; |
| } |
| // store function params into the stack (if not null): |
| var integer vl_respHandlerId := -1; |
| if (pl_respHandler.handlerFn != null) { |
| vl_respHandlerId := f_EPTF_setNewEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_respHandler); |
| } |
| // send adjust message to the remote provider: |
| f_EPTF_Var_send( |
| {adjustContent:={ |
| {{{self,pl_idx}},0}, |
| v_EPTF_Vars[pl_idx].provider.remote.varRef, |
| pl_newContent, |
| vl_respHandlerId |
| }}, |
| v_EPTF_Vars[pl_idx].provider.remote.varRef.compRef |
| ); |
| return; |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_adjustContent_Blocking |
| // |
| // Purpose: |
| // The blocking version of <f_EPTF_Var_adjustContent> it returns the result of the adjust |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_newContent - *in* <EPTF_Var_DirectContent> - the new value to try to set |
| // |
| // Return Value: |
| // *boolean* - false if adjust failed; true if successful |
| // |
| // Errors: |
| // For EPTF Variables with local provider, the function stops with an error. |
| // Adjustment of calculated variables is not allowed. Call <f_EPTF_Var_refreshContent> instead. |
| // |
| // Detailed Comments: |
| // For EPTF Variables with remote provider a request is sent for its remote provider to |
| // adjust the value. If accepted, the new value is written into the content, if not, |
| // the prevoius value is set into the content. |
| // Using the adjust mechanism for EPTF Variables with remote provider too often |
| // might indicate incorrect design. |
| // |
| // For EPTF Variables with no provider the new value is checked by the guardFns |
| // before it is written into the content. |
| // |
| // After a successful adjust, all subscribers of the owner EPTF Variable |
| // are notified about the new value. Then the postProc functions are called. |
| // |
| // The adjust mechanism allows the user to modify the value of a local parameter (i.e. an EPTF variable with no provider) |
| // or to be able to modify the original EPTF Variable from a remote subscriber. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_adjustContent_Blocking(in integer pl_idx, in EPTF_Var_DirectContent pl_newContent) runs on EPTF_Var_CT return boolean { |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.local)) { |
| f_EPTF_Var_debug(log2str("Cannot adjust the content of the EPTF_Var[",pl_idx,"]. It has a local provider! ", v_EPTF_Vars[pl_idx])); |
| return false; |
| } |
| var boolean vl_result := true; |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.empty)) { |
| // I am a "parameter", adjust allowed after the guard fns accept the new value. |
| |
| //call the guard fns: |
| vl_result := f_EPTF_Var_callGuardFns(pl_idx,pl_newContent); |
| if (not vl_result) { |
| // content not accepted |
| } else { |
| // refreshContent is called to notify subscribers: |
| // and set the received content into the current: |
| f_EPTF_Var_registerRefresh(pl_idx,pl_newContent); |
| } |
| return vl_result; |
| } |
| // remote provider: |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.remote)) { |
| |
| if (v_EPTF_Vars[pl_idx].provider.remote.varRef.idx<0) { |
| // subscription is in progress. Have to wait for response: |
| |
| // wait until subscribed: |
| timer t_waitForSubscr := 0.0; |
| t_waitForSubscr.start; |
| timer t_maxWait := v_Var_maxWaitTime; |
| t_maxWait.start; |
| alt { |
| [f_EPTF_Var_isSubscribeRemoteFinished(pl_idx)] t_waitForSubscr.timeout; |
| [] t_maxWait.timeout { |
| f_EPTF_Var_warning(log2str("No response received for subscribe for variable #", pl_idx, ": ",v_EPTF_Vars[pl_idx])); |
| return false; |
| } |
| } |
| } |
| |
| if (not v_EPTF_Vars[pl_idx].subsCanAdjust) { |
| f_EPTF_Var_debug(log2str("Cannot adjust the content of the EPTF_Var[",pl_idx,"]. The subsCanAdjust flag is false! ", v_EPTF_Vars[pl_idx])); |
| return false; |
| } |
| // check top provider type: |
| if (v_EPTF_Vars[pl_idx].provider.remote.topProviderType == local) { |
| f_EPTF_Var_debug(log2str("Cannot adjust the content of the EPTF_Var[",pl_idx,"]. It has a local top-provider! ", v_EPTF_Vars[pl_idx])); |
| return false; |
| } |
| // send adjust message to the remote provider: |
| f_EPTF_Var_send( |
| {adjustContent:={ |
| {{{self,pl_idx}},0}, |
| v_EPTF_Vars[pl_idx].provider.remote.varRef, |
| pl_newContent,-1 // no handler |
| }}, |
| v_EPTF_Vars[pl_idx].provider.remote.varRef.compRef |
| ); |
| // blocks execution until response arrives: |
| as_EPTF_Var_handle_AdjustContentResp(pl_idx, pl_newContent, vl_result); |
| return vl_result; |
| } |
| return vl_result; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getRemoteContent |
| // |
| // Purpose: |
| // This function returns the content of a remote EPTF Variable (without subscription) |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - reference to the remote component |
| // pl_remoteVarName - *in* *charstring* - name of the EPTF Variable in the remote component |
| // pl_content - *out* <EPTF_Var_DirectContent> - the value of the remote EPTF Variable |
| // |
| // Return Value: |
| // boolean - false, if content is not available, true, if the returned content is valid |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function blocks the execution until the response is received. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getRemoteContent(in EPTF_Var_CT pl_remoteCompRef, in charstring pl_remoteVarName, out EPTF_Var_DirectContent pl_content) runs on EPTF_Var_CT return boolean { |
| var EPTF_Var_Ref vl_provider; |
| var boolean vl_subsCanAdjust; |
| return f_EPTF_Var_getRemoteContentById(pl_remoteCompRef,{name := pl_remoteVarName},pl_content,vl_provider,vl_subsCanAdjust); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getRemoteContentById |
| // |
| // Purpose: |
| // This function returns the content of a remote EPTF Variable (without subscription) |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - reference to the remote component |
| // pl_remoteVarId - *in* <EPTF_Var_VarId> - id of the EPTF Variable in the remote component |
| // pl_content - *out* <EPTF_Var_DirectContent> - the value of the remote EPTF Variable |
| // pl_subsCanAdjust - *out* *boolean* - the value of the subsCanAdjust flag of the remote EPTF Variable |
| // |
| // Return Value: |
| // boolean - false, if content is not available, true, if the returned content is valid |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function blocks the execution until the response is received. |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_getRemoteContentById(in EPTF_Var_CT pl_remoteCompRef, in EPTF_Var_VarId pl_remoteVarId, |
| out EPTF_Var_DirectContent pl_content, |
| out EPTF_Var_Ref pl_provider, |
| out boolean pl_subsCanAdjust |
| ) runs on EPTF_Var_CT return boolean { |
| if (pl_remoteCompRef==self) { |
| var integer vl_idx; |
| if (ischosen(pl_remoteVarId.name)) { |
| vl_idx := f_EPTF_Var_getId(pl_remoteVarId.name); |
| } else { |
| vl_idx := pl_remoteVarId.idx; |
| } |
| if (vl_idx==-1) { |
| pl_provider:={null,vl_idx}; |
| pl_content:={unknownVal:={omit}} |
| pl_subsCanAdjust := false; |
| return false; |
| } |
| |
| // request original provider if getRemoteContent uses name |
| if (f_EPTF_Var_checkSubscriptionMode(vl_idx,pull) and ischosen(pl_remoteVarId.name)) { |
| v_EPTF_Vars[vl_idx].provider.remote.routeUpdateCounter := cg_EPTF_Var_routeUpdatePeriod; |
| } |
| |
| f_EPTF_Var_getContent(vl_idx,pl_content); |
| pl_provider:={self,vl_idx}; |
| if (f_EPTF_Var_checkSubscriptionMode(vl_idx,pull) |
| and v_EPTF_Vars[vl_idx].provider.remote.varRef.idx != -1 |
| ) { |
| pl_provider := v_EPTF_Vars[vl_idx].provider.remote.varRef; // replace myself with my provider |
| } |
| pl_subsCanAdjust := v_EPTF_Vars[vl_idx].subsCanAdjust; |
| return true; |
| } |
| |
| f_EPTF_Var_addConnection(pl_remoteCompRef); |
| var integer vl_blockingFlagIdx := f_EPTF_setNewboolean(v_booleanPool,false); |
| var integer vl_responseIdx := f_EPTF_setNewboolean(v_booleanPool,false); |
| f_EPTF_Var_send({getRemoteContent := {pl_remoteVarId,vl_blockingFlagIdx,vl_responseIdx}}, pl_remoteCompRef); |
| |
| timer t_minWait := 0.0; // zero wait |
| timer t_maxWait := v_Var_maxWaitTime; // maximum wait |
| t_minWait.start; |
| t_maxWait.start; |
| // wait until response is received: |
| alt { |
| [f_EPTF_getValueboolean(v_booleanPool,vl_blockingFlagIdx)] t_minWait.timeout; |
| [] t_maxWait.timeout { |
| f_EPTF_Var_warning(log2str("No response received for getRemoteContent for: ", pl_remoteVarId, " from: ", pl_remoteCompRef)); |
| } |
| } |
| // response is received here, boolean at vl_responseIdx is set to the appropriate value |
| var boolean vl_result := f_EPTF_getValueboolean(v_booleanPool,vl_responseIdx); |
| // remove the bool from the pool: |
| f_EPTF_deleteboolean(v_booleanPool,vl_blockingFlagIdx); |
| f_EPTF_deleteboolean(v_booleanPool,vl_responseIdx); |
| |
| if (vl_result==false) { |
| f_EPTF_Var_warning(log2str("Content is not available for remote variable: ", pl_remoteVarId, " on component ", pl_remoteCompRef)); |
| pl_content := {unknownVal := {omit}}; |
| pl_provider := {null,-1}; |
| pl_subsCanAdjust := false; |
| } else { |
| pl_content := v_EPTF_Var_getRemoteContentResultList[vl_responseIdx].content; |
| pl_provider := v_EPTF_Var_getRemoteContentResultList[vl_responseIdx].provider; |
| pl_subsCanAdjust := v_EPTF_Var_getRemoteContentResultList[vl_responseIdx].subsCanAdjust; |
| } |
| return vl_result; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_adjustRemoteContent |
| // |
| // Purpose: |
| // This function send an adjust request to adjust the content of a remote EPTF Variable (without subscription) |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - reference to the remote component |
| // pl_remoteVarName - *in* *charstring* - name of the EPTF Variable in the remote component |
| // pl_content - *in* <EPTF_Var_DirectContent> - the new value to be adjusted on the remote EPTF Variable |
| // pl_respHandler - <EPTF_Var_adjustContentResp_handler> - user handler to call when the adjust is ready (i.e. when adjustResp arrives, or when the guards accept the new value) |
| // but before the value of the variable is refreshed |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // Note, that pl_respHandler is always called with pl_idx argument set to -1, because there is no EPTF Variable in the local component. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_adjustRemoteContent(in EPTF_Var_CT pl_remoteCompRef, in charstring pl_remoteVarName, in EPTF_Var_DirectContent pl_content, in EPTF_Var_adjustContentResp_handler pl_respHandler := {null, {}}) runs on EPTF_Var_CT { |
| f_EPTF_Var_addConnection(pl_remoteCompRef); |
| // store function params into the stack (if not null): |
| var integer vl_respHandlerId := -1; |
| if (pl_respHandler.handlerFn != null) { |
| vl_respHandlerId := f_EPTF_setNewEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_respHandler); |
| } |
| f_EPTF_Var_send({adjustRemoteContent := {varId := {name := pl_remoteVarName}, content := pl_content, respHandlerId := vl_respHandlerId, |
| blockingFlagIdx := -1, responseIdx := -1}}, pl_remoteCompRef); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_adjustRemoteContentByIdx |
| // |
| // Purpose: |
| // This function send an adjust request to adjust the content of a remote EPTF Variable (without subscription) |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - reference to the remote component |
| // pl_remoteVarIdx - *in* *integer* - idx of the EPTF Variable in the remote component |
| // pl_content - *in* <EPTF_Var_DirectContent> - the new value to be adjusted on the remote EPTF Variable |
| // pl_respHandler - <EPTF_Var_adjustContentResp_handler> - user handler to call when the adjust is ready (i.e. when adjustResp arrives, or when the guards accept the new value) |
| // but before the value of the variable is refreshed |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // Note, that pl_respHandler is always called with pl_idx argument set to -1, because there is no EPTF Variable in the local component. |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_adjustRemoteContentByIdx(in EPTF_Var_CT pl_remoteCompRef, in integer pl_remoteVarIdx, in EPTF_Var_DirectContent pl_content, in EPTF_Var_adjustContentResp_handler pl_respHandler := {null, {}}) runs on EPTF_Var_CT { |
| f_EPTF_Var_addConnection(pl_remoteCompRef); |
| // store function params into the stack (if not null): |
| var integer vl_respHandlerId := -1; |
| if (pl_respHandler.handlerFn != null) { |
| vl_respHandlerId := f_EPTF_setNewEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_respHandler); |
| } |
| f_EPTF_Var_send({adjustRemoteContent := {varId := {idx := pl_remoteVarIdx}, content := pl_content, respHandlerId := vl_respHandlerId, |
| blockingFlagIdx := -1, responseIdx := -1}}, pl_remoteCompRef); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_adjustRemoteContent_Blocking |
| // |
| // Purpose: |
| // The blocking version of the function <f_EPTF_Var_adjustRemoteContent> |
| // |
| // Parameters: |
| // pl_remoteCompRef - *in* <EPTF_Var_CT> - reference to the remote component |
| // pl_remoteVarName - *in* *charstring* - name of the EPTF Variable in the remote component |
| // pl_content - *in* <EPTF_Var_DirectContent> - the new value to be adjusted on the remote EPTF Variable |
| // |
| // Return Value: |
| // boolean - false, if adjust failed |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This function blocks the execution until the response is received |
| // and until all respHandlers returned. |
| // This means that the response handlers are called before the function returns. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_adjustRemoteContent_Blocking(in EPTF_Var_CT pl_remoteCompRef, in charstring pl_remoteVarName, in EPTF_Var_DirectContent pl_content, in EPTF_Var_adjustContentResp_handler pl_respHandler := {null, {}}) runs on EPTF_Var_CT return boolean { |
| f_EPTF_Var_addConnection(pl_remoteCompRef); |
| var integer vl_blockingFlagIdx := f_EPTF_setNewboolean(v_booleanPool,false); |
| var integer vl_responseIdx := f_EPTF_setNewboolean(v_booleanPool,false); |
| // store function params into the stack (if not null): |
| var integer vl_respHandlerId := -1; |
| if (pl_respHandler.handlerFn != null) { |
| vl_respHandlerId := f_EPTF_setNewEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_respHandler); |
| } |
| f_EPTF_Var_send({adjustRemoteContent := {varId := {name := pl_remoteVarName}, content := pl_content, respHandlerId := vl_respHandlerId, |
| blockingFlagIdx := vl_blockingFlagIdx, responseIdx := vl_responseIdx}}, pl_remoteCompRef); |
| |
| // blocks execution until response arrives: |
| timer t_minWait := 0.0; // zero wait |
| timer t_maxWait := v_Var_maxWaitTime; // maximum wait |
| t_minWait.start; |
| t_maxWait.start; |
| // wait until response is received: |
| alt { |
| [f_EPTF_getValueboolean(v_booleanPool,vl_blockingFlagIdx)] t_minWait.timeout; |
| [] t_maxWait.timeout { |
| f_EPTF_Var_warning(log2str("No response received for adjustRemoteContent for: ", pl_remoteVarName, " from: ", pl_remoteCompRef)); |
| } |
| } |
| // response is received here, boolean at vl_responseIdx is set to the appropriate value |
| var boolean vl_result := f_EPTF_getValueboolean(v_booleanPool,vl_responseIdx); |
| // remove the bool from the pool: |
| f_EPTF_deleteboolean(v_booleanPool,vl_blockingFlagIdx); |
| f_EPTF_deleteboolean(v_booleanPool,vl_responseIdx); |
| |
| if (vl_result==false) { |
| f_EPTF_Var_warning(log2str("AdjustRemoteContent is not allowed for remote variable: ", pl_remoteVarName, " on component ", pl_remoteCompRef)); |
| } |
| return vl_result; |
| } |
| |
| } // group UpdateContent |
| |
| /////////////////////////////////////////////////////////// |
| // Group: Cleanup |
| // |
| // Purpose: |
| // Functions that will cleanup the <EPTF_Var_CT> before exit. |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group Cleanup { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_cleanup_CT |
| // |
| // Purpose: |
| // This function should be called before the EPTF_Var_CT component shuts down. |
| // |
| // Parameters: |
| // - |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // The function is registered by <f_EPTF_Base_registerCleanup> as a cleanup function in the init function for the ETPF_Var_CT component. |
| // This function makes it possible to be able to shut down the |
| // EPTF_Var_CT component gracefully. |
| // It sends a notification to all connected components, |
| // and disconnects from all remote components when the response for the notification is received, |
| // before the component terminates. |
| // This function can be called inside or outside the main alt-loop. The main alt-loop |
| // will terminate after all connections had been shut down if there is no 'repeat' |
| // statement after calling f_EPTF_Var_cleanup_CT. |
| // The function blocks execution until the last response for bye messages |
| // have received, or until 0.5secs between byeAck-s elapsed. |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_cleanup_CT() runs on EPTF_Var_CT { |
| if (v_EPTF_Var_initialized == false) { |
| return; |
| } |
| |
| v_EPTF_Var_Msg_Buffer := {}; |
| v_EPTF_Var_Msg_BufferStartIdx := 0; |
| v_EPTF_Var_nofPendingMsgs := 0; |
| |
| // wait until all pending connetions establised: |
| if (v_EPTF_Var_numPendingHellos>0) { |
| f_EPTF_Var_debug(log2str("Waiting for ", v_EPTF_Var_numPendingHellos, " number of pending hello messages...")); |
| timer t_pendingMaxWait := v_EPTF_Var_maxWaitTimeForByeAck; |
| timer t_event := 0.0; |
| t_event.start; |
| t_pendingMaxWait.start; |
| alt { |
| [v_EPTF_Var_numPendingHellos==0] t_event.timeout { |
| f_EPTF_Var_debug(log2str("All response is received for hello messages. Continuing cleanup...")); |
| } |
| [] t_pendingMaxWait.timeout { |
| f_EPTF_Var_debug(log2str("Max wait time expired. No response is received for hello in ", v_EPTF_Var_numPendingHellos, " number of cases. Continuing cleanup...")); |
| } |
| } |
| } |
| |
| var boolean vl_waitForResponse := false; |
| v_EPTF_Var_pendingByeNum := 0; |
| var EPTF_IntegerList vl_byeSentCompIds := {}; |
| for(var integer vl_refreshRateId := 0; vl_refreshRateId<sizeof(v_syncBuffer); vl_refreshRateId:=vl_refreshRateId+1) { |
| for(var integer i:=0; i<sizeof(v_syncBuffer[vl_refreshRateId].syncBuffer); i:=i+1) { |
| if (v_syncBuffer[vl_refreshRateId].syncBuffer[i].remoteCompRef != null) { |
| // check if bye was already sent for this comp: |
| var boolean vl_sent := false; |
| var integer vl_currentCompId := f_EPTF_Base_upcast(v_syncBuffer[vl_refreshRateId].syncBuffer[i].remoteCompRef); |
| for(var integer c:=0; c<sizeof(vl_byeSentCompIds); c:=c+1) { |
| if (vl_currentCompId == vl_byeSentCompIds[c]) { |
| vl_sent := true; |
| break; |
| } |
| } |
| if (not vl_sent) { |
| vl_byeSentCompIds[sizeof(vl_byeSentCompIds)] := vl_currentCompId; |
| // Note: buffer is intentionally not sent at cleanup. |
| f_EPTF_Var_send({bye:={}},v_syncBuffer[vl_refreshRateId].syncBuffer[i].remoteCompRef); |
| //v_syncBuffer[vl_refreshRateId].syncBuffer[i] := { |
| // remoteCompRef := null, |
| // flushCounter:=0, |
| // compBufferData := {} |
| //} |
| vl_waitForResponse := true; |
| v_EPTF_Var_pendingByeNum := v_EPTF_Var_pendingByeNum + 1; |
| } |
| } |
| } |
| if (v_syncBuffer[vl_refreshRateId].eventIdx!=-1) { |
| if(f_EPTF_SchedulerComp_CancelEvent(v_syncBuffer[vl_refreshRateId].eventIdx)){/*remove the warning*/}; |
| v_syncBuffer[vl_refreshRateId].eventIdx := -1; |
| } |
| } |
| f_EPTF_Var_setRefreshSubscribersPeriod(-1.0); // stop the local variable refresh |
| if (vl_waitForResponse) { |
| timer t_wait := v_EPTF_Var_maxWaitTimeForByeAck; |
| t_wait.start; |
| var EPTF_Var_MgmtMsg vl_EPTF_Var_MgmtIf_msg; |
| var EPTF_Var_CT vl_EPTF_Var_MgmtIf_msg_sender; |
| // bye and byeAck messages are processed, all others are ignored |
| alt { |
| [] as_EPTF_Var_handle_ByeAck(t_wait); |
| [] as_EPTF_Var_handle_Bye(); |
| [] EPTF_Var_MgmtIf.receive(?) -> value vl_EPTF_Var_MgmtIf_msg sender vl_EPTF_Var_MgmtIf_msg_sender { |
| f_EPTF_Var_debug(log2str("Unexpected message received from ",vl_EPTF_Var_MgmtIf_msg_sender," during cleanup. Message dropped: ",vl_EPTF_Var_MgmtIf_msg)); |
| repeat; |
| } |
| } |
| } |
| |
| if (v_EPTF_Var_enableName2Id) { |
| f_EPTF_str2int_HashMap_Delete("EPTF_Var_Hashmap_Name2Id"); |
| v_EPTF_Var_Hashmap_Name2Id := -1; |
| } |
| if (v_EPTF_Var_enableCompRef2Id) { |
| f_EPTF_oct2int_HashMap_Delete("EPTF_Var_Hashmap_CompRef2Id"); |
| v_EPTF_Var_Hashmap_CompRef2Id := -1; |
| } |
| |
| f_EPTF_str2int_HashMap_Delete("EPTF_Var_Hashmap_Provider2Id"); |
| v_EPTF_Var_Hashmap_Provider2Id := -1 |
| |
| f_EPTF_str2int_HashMap_Delete("EPTF_Var_Hashmap_SyncBuffer"); |
| v_EPTF_Var_Hashmap_SyncBuffer := -1; |
| |
| deactivate(v_EPTF_Var_def); |
| v_EPTF_Var_def := null; |
| v_EPTF_Var_initialized := false; |
| if (tsp_EPTF_Var_debug) { |
| f_EPTF_Var_CT_LogAll("----- VAR CLEANUP DONE -------"); |
| } else { |
| f_EPTF_Var_debug("----- VAR CLEANUP DONE -------"); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_setMaxWaitTimeForByeAck |
| // |
| // Purpose: |
| // Set the maximimum wait time for ByeAck messages during cleanup |
| // |
| // Parameters: |
| // pl_waitTime - *in* *float* - the time to wait |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_setMaxWaitTimeForByeAck(in float pl_waitTime) runs on EPTF_Var_CT { |
| v_EPTF_Var_maxWaitTimeForByeAck := pl_waitTime; |
| if (v_EPTF_Var_maxWaitTimeForByeAck<0.0) { |
| v_EPTF_Var_maxWaitTimeForByeAck := 0.0; |
| } |
| } |
| |
| } // group Cleanup |
| |
| /////////////////////////////////////////////////////////// |
| // Group: Timeline |
| // |
| // Purpose: |
| // Functions that handle the timeline of a buffered EPTF Variable. |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group Timeline { |
| |
| |
| // returns true if variable has a timeLine subscriber |
| private function f_EPTF_Var_hasTimeLineSubscriber(in integer pl_idx) runs on EPTF_Var_CT return boolean { |
| return v_EPTF_Vars[pl_idx].nofTimelineSubscribers>0; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getVarRefreshRate |
| // |
| // Purpose: |
| // Returns the refresh rate for a given variable. |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // integer - the refresh rate (-1 if no refresh rate found) |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getVarRefreshRate(in integer pl_idx) runs on EPTF_Var_CT return integer { |
| f_EPTF_Base_assert(%definitionId&": Invalid var index: "&int2str(pl_idx), pl_idx>=0 and pl_idx<sizeof(v_EPTF_Vars)); |
| |
| if (not ischosen(v_EPTF_Vars[pl_idx].provider.remote)) { |
| return -1; // no refresh rate |
| } |
| |
| return v_EPTF_Vars[pl_idx].provider.remote.refreshRate; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getRefreshPeriod |
| // |
| // Purpose: |
| // Returns the refresh rate for a given refreshRateId. |
| // |
| // Parameters: |
| // pl_refreshRateId - *in* *integer* - the refreshRateId in v_syncBuffer |
| // |
| // Return Value: |
| // float - the refresh period in seconds |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getRefreshPeriod(in integer pl_refreshRateId) runs on EPTF_Var_CT return float { |
| f_EPTF_Base_assert(%definitionId&": Invalid refreshRateId: "&int2str(pl_refreshRateId), pl_refreshRateId>=0 and pl_refreshRateId<sizeof(v_syncBuffer)); |
| if (pl_refreshRateId==0) { |
| return v_syncInterval; |
| } |
| return int2float(v_syncBuffer[pl_refreshRateId].refreshRate) * v_minSyncInterval; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getRefreshRate |
| // |
| // Purpose: |
| // Returns the refresh rate for a given refreshRateId. |
| // |
| // Parameters: |
| // pl_refreshRateId - *in* *integer* - the refreshRateId in v_syncBuffer |
| // |
| // Return Value: |
| // integer - the refresh rate |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getRefreshRate(in integer pl_refreshRateId) runs on EPTF_Var_CT return integer { |
| f_EPTF_Base_assert(%definitionId&": Invalid refreshRateId: "&int2str(pl_refreshRateId), pl_refreshRateId>=0 and pl_refreshRateId<sizeof(v_syncBuffer)); |
| return v_syncBuffer[pl_refreshRateId].refreshRate; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getRefreshRateId |
| // |
| // Purpose: |
| // Returns the refresh rate id for a given refreshRate. |
| // |
| // Parameters: |
| // pl_refreshRate - *in* *integer* - the refreshRate |
| // |
| // Return Value: |
| // integer - the id of the refresh rate in v_syncBuffer. -1 if not found |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // If pl_refreshRateId == -1, the timeLine belonging to the refreshRate of the remote provider is returned |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getRefreshRateId(in integer pl_refreshRate) runs on EPTF_Var_CT return integer { |
| var integer vl_refreshRateId := 0; |
| var integer vl_compBufferIdx; |
| f_EPTF_Var_checkConnection(null,pl_refreshRate,vl_refreshRateId,vl_compBufferIdx); |
| return vl_refreshRateId; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getTimeLine |
| // |
| // Purpose: |
| // Returns the timeLine for a variable for a given refreshRateId. |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_timeLine - *in* <EPTF_Var_TimeLine> - the idx of the EPTF_Var |
| // pl_refreshRateId - *in* *integer* - the refreshRateId |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // If pl_refreshRateId == -1, the timeLine belonging to the refreshRate of the remote provider is returned |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getTimeLine(in integer pl_idx, out EPTF_Var_TimeLine pl_timeLine, in integer pl_refreshRateId := -1) runs on EPTF_Var_CT { |
| pl_timeLine.size := 0; |
| pl_timeLine.timeLineData := {}; |
| |
| if (pl_refreshRateId==-1) { |
| // return the timeLine for the subscription's refreshRate: |
| // the refreshRateId is retrieved from the remote provider: |
| // FIXME: timeLine needed for sampled also because UIHandlerWidgetFunctions uses it? |
| if (f_EPTF_Var_checkSubscriptionMode(pl_idx,timeLine) |
| or f_EPTF_Var_checkSubscriptionMode(pl_idx,sampled) or f_EPTF_Var_checkSubscriptionMode(pl_idx,sampledAtSync)) { |
| var integer vl_compBufferIdx; |
| f_EPTF_Var_checkConnection(null,v_EPTF_Vars[pl_idx].provider.remote.refreshRate,pl_refreshRateId,vl_compBufferIdx); |
| } |
| if (pl_refreshRateId==-1) { |
| // no timeline is available |
| return; |
| } |
| } |
| |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].timeLineBuffer);i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].timeLineBuffer[i].refreshRateId == pl_refreshRateId) { |
| pl_timeLine := v_EPTF_Vars[pl_idx].timeLineBuffer[i].timeLine; |
| return; |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_updateTimeLine |
| // |
| // Purpose: |
| // Appends new content to the timeLine if the variable is buffered, uses the current time for timeStamp if no timestamp is specified. |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_contentNew - *in* <EPTF_Var_DirectContent> - the content to be added |
| // pl_timeStamp - *in* *float* *optional* - the timestamp for the data. If not specified, current time is used. |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_updateTimeLine(in integer pl_idx, in EPTF_Var_DirectContent pl_contentNew, in float pl_timeStamp := -1.0) runs on EPTF_Var_CT { |
| // if i am a buffered subscriber (i.e. my provider is remote buffered): |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.remote) and |
| ( v_EPTF_Vars[pl_idx].provider.remote.subscriptionMode == sampled or v_EPTF_Vars[pl_idx].provider.remote.subscriptionMode == sampledAtSync |
| or v_EPTF_Vars[pl_idx].provider.remote.subscriptionMode == timeLine )) { |
| return; |
| } |
| |
| var float vl_timeStamp := pl_timeStamp; |
| if (vl_timeStamp<0.0) { |
| vl_timeStamp := f_EPTF_Base_getAbsTimeInSecs(f_EPTF_SchedulerComp_snapshotTime()) |
| } |
| |
| // update the timeline for all refreshRates: |
| for(var integer vl_refreshRateIdInTimeLineBuffer := 0;vl_refreshRateIdInTimeLineBuffer<sizeof(v_EPTF_Vars[pl_idx].timeLineBuffer);vl_refreshRateIdInTimeLineBuffer:=vl_refreshRateIdInTimeLineBuffer+1) { |
| // if i don't have a buffered subscriber: |
| if (v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].bufferNum==0) { |
| continue; // nothing to do |
| } |
| var integer vl_refreshRateId := v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].refreshRateId; |
| |
| if (f_EPTF_Var_hasTimeLineSubscriber(pl_idx)) { |
| // append the new sample into the timeLine: |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.timeLineData[v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size] := { |
| vl_timeStamp, |
| pl_contentNew |
| }; |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size := v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size + 1; |
| } else { |
| // set the new sample into the timeLine == overwrite/create the 0-th element in the timeline |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.timeLineData[0] := { |
| vl_timeStamp, |
| pl_contentNew |
| }; |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size := 1; // store only the last value |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_setSyncInterval |
| // |
| // Purpose: |
| // Sets the timeLine sync interval. |
| // |
| // Parameters: |
| // pl_syncInterval - *in* *float* - the new sync interval |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This sync interval is used to send the buffered timeLines periodically |
| // to the subscribers (with default refreshRate(=zero)). |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_setSyncInterval(in float pl_syncInterval) runs on EPTF_Var_CT { |
| v_syncInterval := pl_syncInterval; |
| // reschedule the default event: |
| var integer vl_refreshRateId := 0; // default refresh method |
| f_EPTF_SchedulerComp_CancelEvent(v_syncBuffer[vl_refreshRateId].eventIdx); |
| if(f_EPTF_SchedulerComp_scheduleAction( |
| pl_when := f_EPTF_Base_getRelTimeInSecs()+v_syncInterval, |
| pl_actionHandler := refers(f_EPTF_Var_syncTimeoutHandler), |
| pl_action := {vl_refreshRateId}, |
| pl_eventIndex := v_syncBuffer[vl_refreshRateId].eventIdx |
| )){/*remove the warning*/}; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_setMinSyncInterval |
| // |
| // Purpose: |
| // Sets the minima of the sync interval for refreshRates. |
| // |
| // Parameters: |
| // pl_minSyncInterval - *in* *float* - the new minima of sync interval |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This sync interval is used to send the buffered timeLines periodically |
| // to the subscribers. The length of the period is calculated as |
| // minSyncInterval * refreshRate, where refreshRate is a positive integer |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_setMinSyncInterval(in float pl_minSyncInterval) runs on EPTF_Var_CT { |
| v_minSyncInterval := pl_minSyncInterval; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_setMaxWaitTime |
| // |
| // Purpose: |
| // Sets the minima of the sync interval for refreshRates. |
| // |
| // Parameters: |
| // pl_maxWaitTime - *in* *float* - the new maximal waiting time for responses |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // This parameter is used when a response is expected from another |
| // component. This function sets the maximal time to wait for the response. |
| // If the time expires, an error/false result is generated. |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_setMaxWaitTime(in float pl_maxWaitTime) |
| runs on EPTF_Var_CT{ |
| v_Var_maxWaitTime := pl_maxWaitTime; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_sendTimeLine |
| // |
| // Purpose: |
| // Sends the timeLine for the given EPTF Var only for all of its remote subscribers. |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // - |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_sendTimeLine(in integer pl_idx) runs on EPTF_Var_CT { |
| // send timeLines |
| var EPTF_Var_TimeLineList vl_refreshTimeLineList; |
| for(var integer vl_refreshRateId:=0;vl_refreshRateId<sizeof(v_syncBuffer);vl_refreshRateId:=vl_refreshRateId+1) { |
| for(var integer i:=0; i<sizeof(v_syncBuffer[vl_refreshRateId].syncBuffer); i:=i+1) { |
| if (v_syncBuffer[vl_refreshRateId].syncBuffer[i].remoteCompRef!=null) { |
| vl_refreshTimeLineList := {}; |
| for(var integer j:=0; j<sizeof(v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData); j:=j+1) { |
| var integer vl_varIdx := v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].localIdx; |
| if (pl_idx == vl_varIdx) { |
| // find timeLine for the refreshRate: |
| var integer vl_refreshRateIdInTimeLineBuffer := -1; |
| for (var integer ii := 0; ii<sizeof(v_EPTF_Vars[vl_varIdx].timeLineBuffer); ii:=ii+1) { |
| if (v_EPTF_Vars[vl_varIdx].timeLineBuffer[ii].refreshRateId == vl_refreshRateId) { |
| vl_refreshRateIdInTimeLineBuffer := ii; |
| break; |
| } |
| } |
| if(vl_refreshRateIdInTimeLineBuffer!=-1) { |
| // there is timeline for this variable with this refreshRate |
| // only add to message if timeLine is not empty: |
| if (v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size>0) { |
| // if subscription mode of the variable is timeLine |
| if (v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].subscriptionMode == timeLine) { |
| vl_refreshTimeLineList[sizeof(vl_refreshTimeLineList)] := { |
| v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].remoteIdx, |
| v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine |
| } |
| } else if (v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].subscriptionMode == sampled) { |
| // sampled: send only the last element in the timeLine: |
| vl_refreshTimeLineList[sizeof(vl_refreshTimeLineList)] := { |
| v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].remoteIdx, |
| {1,{v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.timeLineData[v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size-1]}} |
| } |
| } |
| } |
| } |
| |
| if (v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].subscriptionMode == sampledAtSync) { |
| // sampledAtSync: send only the current content in the timeLine: |
| var EPTF_Var_DirectContent vl_currentContent; |
| var float vl_timestamp := f_EPTF_Base_getAbsTimeInSecs(f_EPTF_SchedulerComp_snapshotTime()); |
| f_EPTF_Var_getContent(vl_varIdx, vl_currentContent); |
| if (v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].prevContent != vl_currentContent) { |
| vl_refreshTimeLineList[sizeof(vl_refreshTimeLineList)] := { |
| v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].remoteIdx, |
| {1,{{vl_timestamp,vl_currentContent}}} |
| } |
| // store current value for sampledAtSync |
| v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].prevContent := vl_currentContent; |
| } |
| } |
| } |
| } |
| // no 'if' needed: send empty message in case of no change |
| if (tsp_EPTF_Var_enableEmptyTimeLine or sizeof(vl_refreshTimeLineList)>0) { |
| f_EPTF_Var_send( |
| {refreshTimeLines := {v_syncBuffer[vl_refreshRateId].refreshRate, v_syncBuffer[vl_refreshRateId].syncBuffer[i].flushCounter, vl_refreshTimeLineList}}, |
| v_syncBuffer[vl_refreshRateId].syncBuffer[i].remoteCompRef |
| ); |
| // increase the counter: |
| v_syncBuffer[vl_refreshRateId].syncBuffer[i].flushCounter := v_syncBuffer[vl_refreshRateId].syncBuffer[i].flushCounter+1; |
| } |
| } |
| } |
| // reset timeLines: |
| for(var integer i:=0; i<sizeof(v_syncBuffer[vl_refreshRateId].syncBuffer); i:=i+1) { |
| if (v_syncBuffer[vl_refreshRateId].syncBuffer[i].remoteCompRef!=null) { |
| for(var integer j:=0; j<sizeof(v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData); j:=j+1) { |
| var integer vl_varIdx := v_syncBuffer[vl_refreshRateId].syncBuffer[i].compBufferData[j].localIdx; |
| if (pl_idx == vl_varIdx) { |
| // find timeLine for the refreshRate: |
| var integer vl_refreshRateIdInTimeLineBuffer := -1; |
| for (var integer ii := 0; ii<sizeof(v_EPTF_Vars[vl_varIdx].timeLineBuffer); ii:=ii+1) { |
| if (v_EPTF_Vars[vl_varIdx].timeLineBuffer[ii].refreshRateId == vl_refreshRateId) { |
| vl_refreshRateIdInTimeLineBuffer := ii; |
| break; |
| } |
| } |
| if(vl_refreshRateIdInTimeLineBuffer==-1) { |
| continue; // no timeline for this variable with this refreshRate |
| } |
| // only reset timeLine if timeLine is not empty: |
| if (v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size>0) { |
| v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine := {0,{}}; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| } // group Timeline |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_content2str |
| // |
| // Purpose: |
| // Returns the value of the content for the EPTF Variable as a charstring |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_content2str(in integer pl_idx) runs on EPTF_Var_CT return charstring { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx, vl_currentContent); |
| return f_EPTF_Var_directContent2str(vl_currentContent); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_str2content |
| // |
| // Purpose: |
| // Sets the value of the content for the EPTF Variable from a charstring |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // pl_valueStr - *in* *charstring* - the value of the variable as charsting |
| // (same format as retuned by <f_EPTF_Var_content2str>) |
| // |
| // Return Value: |
| // *integer* - error code: 0 if successful, nonzero if conversion failed |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_str2content(in integer pl_idx, in charstring pl_valueStr) runs on EPTF_Var_CT return integer { |
| var EPTF_Var_DirectContent vl_content; |
| f_EPTF_Var_getContent(pl_idx,vl_content); |
| var integer vl_errorCode := f_EPTF_Var_str2directContent(pl_valueStr,vl_content); |
| if (vl_errorCode==0) { |
| f_EPTF_Var_adjustContent(pl_idx,vl_content); |
| } |
| return vl_errorCode; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_content2string |
| // |
| // Purpose: |
| // Returns the the content for the EPTF Variable as a charstring in module parameter format |
| // |
| // Parameters: |
| // pl_idx - *in* *integer* - the idx of the EPTF_Var |
| // |
| // Return Value: |
| // |
| // Errors: |
| // - |
| // |
| // Detailed Comments: |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_content2string(in integer pl_idx) runs on EPTF_Var_CT return charstring { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(pl_idx, vl_currentContent); |
| return f_EPTF_Var_directContent2string(vl_currentContent); |
| } |
| |
| // externals: |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_upcast |
| // |
| // Purpose: |
| // Cast EPTF_Var_CT to EPTF_Base_CT |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_upcast(in EPTF_Var_CT pl_compRef) return EPTF_Base_CT; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_downcast |
| // |
| // Purpose: |
| // Cast EPTF_Base_CT to EPTF_Var_CT |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_downcast(in EPTF_Base_CT pl_baseCompRef) return EPTF_Var_CT; |
| |
| // External functions needed for the implemented types: |
| |
| // integer |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getIntRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getIntRef(in integer pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefInt |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefInt(in octetstring pl_compVarRef) return integer; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyIntRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyIntRefValue(in octetstring pl_compVarRef, in integer pl_newValue); |
| |
| // float |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getFloatRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getFloatRef(in float pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefFloat |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefFloat(in octetstring pl_compVarRef) return float; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyFloatRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyFloatRefValue(in octetstring pl_compVarRef, in float pl_newValue); |
| |
| // boolean |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getBoolRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getBoolRef(in boolean pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefBool |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefBool(in octetstring pl_compVarRef) return boolean; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyBoolRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyBoolRefValue(in octetstring pl_compVarRef, in boolean pl_newValue); |
| |
| // charstring |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getCharstringRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getCharstringRef(in charstring pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefCharstring |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefCharstring(in octetstring pl_compVarRef) return charstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyCharstringRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyCharstringRefValue(in octetstring pl_compVarRef, in charstring pl_newValue); |
| |
| // octetstring |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getOctetstringRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getOctetstringRef(in octetstring pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefOctetstring |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefOctetstring(in octetstring pl_compVarRef) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyOctetstringRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyOctetstringRefValue(in octetstring pl_compVarRef, in octetstring pl_newValue); |
| |
| // hexstring |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getHexstringRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getHexstringRef(in hexstring pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefHexstring |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefHexstring(in octetstring pl_compVarRef) return hexstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyHexstringRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyHexstringRefValue(in octetstring pl_compVarRef, in hexstring pl_newValue); |
| |
| // bitstring |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getBitstringRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getBitstringRef(in bitstring pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefBitstring |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefBitstring(in octetstring pl_compVarRef) return bitstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyBitstringRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyBitstringRefValue(in octetstring pl_compVarRef, in bitstring pl_newValue); |
| |
| // integerlist |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getIntegerlistRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getIntegerlistRef(in EPTF_IntegerList pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefIntegerlist |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefIntegerlist(in octetstring pl_compVarRef) return EPTF_IntegerList; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyIntegerlistRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyIntegerlistRefValue(in octetstring pl_compVarRef, in EPTF_IntegerList pl_newValue); |
| |
| // floatlist |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getFloatlistRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getFloatlistRef(in EPTF_FloatList pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefFloatlist |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefFloatlist(in octetstring pl_compVarRef) return EPTF_FloatList; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyFloatlistRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyFloatlistRefValue(in octetstring pl_compVarRef, in EPTF_FloatList pl_newValue); |
| |
| // charstringlist |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getCharstringlistRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getCharstringlistRef(in EPTF_CharstringList pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefCharstringlist |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefCharstringlist(in octetstring pl_compVarRef) return EPTF_CharstringList; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyCharstringlistRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyCharstringlistRefValue(in octetstring pl_compVarRef, in EPTF_CharstringList pl_newValue); |
| |
| // statusLED |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getStatusLEDRef |
| // |
| // Purpose: |
| // Returns the address of the component variable |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_getStatusLEDRef(in EPTF_StatusLED pl_compVar) return octetstring; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_derefStatusLED |
| // |
| // Purpose: |
| // Returns the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_derefStatusLED(in octetstring pl_compVarRef) return EPTF_StatusLED; |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_modifyStatusLEDRefValue |
| // |
| // Purpose: |
| // Modifies the value of the component variable at the given address |
| /////////////////////////////////////////////////////////// |
| public external function f_EPTF_Var_modifyStatusLEDRefValue(in octetstring pl_compVarRef, in EPTF_StatusLED pl_newValue); |
| |
| //... |
| |
| } // group Public |
| |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| // private: |
| ////////////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| /////////////////////////////////////////////////////////// |
| // Group: Private |
| // |
| // Purpose: |
| // Private functions. These functions must not be used by the user of <EPTF_Var_CT> |
| // |
| // Elements: |
| /////////////////////////////////////////////////////////// |
| group Private { |
| |
| |
| // enable/disable compRef2id |
| public function f_EPTF_Var_useCompRef2Id(in boolean pl_enableCompRef2Id) runs on EPTF_Var_CT { |
| if (pl_enableCompRef2Id != v_EPTF_Var_enableCompRef2Id) { |
| v_EPTF_Var_enableCompRef2Id := pl_enableCompRef2Id; |
| if (v_EPTF_Var_enableCompRef2Id) { |
| v_EPTF_Var_Hashmap_CompRef2Id := f_EPTF_oct2int_HashMap_New("EPTF_Var_Hashmap_CompRef2Id"); |
| } |
| } |
| } |
| // enable/disable name2id |
| public function f_EPTF_Var_useName2Id(in boolean pl_enableName2Id) runs on EPTF_Var_CT { |
| if (pl_enableName2Id != v_EPTF_Var_enableName2Id) { |
| v_EPTF_Var_enableName2Id := pl_enableName2Id; |
| if (v_EPTF_Var_enableName2Id) { |
| v_EPTF_Var_Hashmap_Name2Id := f_EPTF_str2int_HashMap_New("EPTF_Var_Hashmap_Name2Id"); |
| } |
| } |
| } |
| |
| public function f_EPTF_Var_getHashmap_Hashmap_CompRef2Id() runs on EPTF_Var_CT return integer { |
| return v_EPTF_Var_Hashmap_CompRef2Id; |
| } |
| |
| public function f_EPTF_Var_getHashmap_Name2Id() runs on EPTF_Var_CT return integer { |
| return v_EPTF_Var_Hashmap_Name2Id; |
| } |
| |
| // VARIABLE HANDLING |
| |
| const EPTF_Var c_newVar := { |
| provider := { empty := {} }, // the provider, those varible(s) that value is used to calculate this var's value |
| subscribers := {}, // subscriber list, who should be notified if the value of this var changes |
| name := "", // name of the variable |
| subsCanAdjust := true, // if false: subscribers cannot adjust the content |
| content := {invalid := {}}, // content (value or reference to a value) of the variable |
| postProcFns := {}, // called by the library after the value of the EPTF Variable was changed |
| guardFns := {}, // function pointers to the guard functions |
| unsubscribeNotifyFns := {}, // functions called after the variable is unsubsribed (or when bye is received). Notifies the user about the unsubscribe |
| subsCanAdjustNotifyFns := {}, // called by the library after the value of subsCanAdjust of the EPTF Variable was changed |
| timeLineBuffer := {}, // buffered timeLine for subscribers for each refresh rate |
| nofTimelineSubscribers := 0 // the number of timeLine subscribers |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addNew |
| // |
| // Purpose: |
| // Creates a new EPTF Variable and returns its idx |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_addNew(out integer pl_idx, in charstring pl_name := "") runs on EPTF_Var_CT { |
| var integer vl_idx; |
| if (f_EPTF_Var_checkName(pl_name,vl_idx) == false) { |
| f_EPTF_Var_error(log2str("New EPTF Variable name is not unique: ", pl_name," Already defined by EPTF_Var[",vl_idx,"]: ", v_EPTF_Vars[vl_idx])); |
| //f_EPTF_Base_stop(); |
| } |
| pl_idx := sizeof(v_EPTF_Vars); |
| f_EPTF_Var_initVar(pl_idx); |
| v_EPTF_Vars[pl_idx].name := pl_name; |
| // register the name into the hashmap: |
| if (v_EPTF_Var_enableName2Id and pl_name != "") { |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_Var_Hashmap_Name2Id,pl_name,pl_idx); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_checkName |
| // |
| // Purpose: |
| // Checks if the name is valid (unique in the current component), |
| // returns true (pl_idx = -1) if ok; returns false (pl_idx = index of the variable) if the name exists |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_checkName(in charstring pl_name, out integer pl_idx) runs on EPTF_Var_CT return boolean { |
| pl_idx := -1; |
| if (pl_name=="") { |
| return true; |
| } |
| // find the name: |
| pl_idx := f_EPTF_Var_getId(pl_name); |
| if (pl_idx == -1) { |
| return true; |
| } |
| return false; // name is not unique |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_initVar |
| // |
| // Purpose: |
| // Initializes the variable at the given idx, |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_initVar(in integer pl_idx) runs on EPTF_Var_CT { |
| v_EPTF_Vars[pl_idx] := c_newVar; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeVar |
| // |
| // Purpose: |
| // Removes the variable |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_removeVar(in integer pl_idx) runs on EPTF_Var_CT { |
| if (not ischosen(v_EPTF_Vars[pl_idx].provider.empty)) { |
| f_EPTF_Var_warning(log2str(%definitionId, ": Cannot remove variable ", v_EPTF_Vars[pl_idx].name, " : It has a provider. Unsubscribe it first!")); |
| return; |
| } |
| if (v_EPTF_Var_enableName2Id and v_EPTF_Vars[pl_idx].name != "") { |
| f_EPTF_str2int_HashMap_Erase(v_EPTF_Var_Hashmap_Name2Id,v_EPTF_Vars[pl_idx].name); |
| } |
| f_EPTF_Var_initVar(pl_idx); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_initContentRef |
| // |
| // Purpose: |
| // Sets the content to a reference |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_initContentRef(in integer pl_idx, in EPTF_Var_ReferencedContent pl_contentRef) runs on EPTF_Var_CT { |
| v_EPTF_Vars[pl_idx].content := { |
| reference := pl_contentRef |
| } |
| // register the variable ref into the hashmap: |
| if (v_EPTF_Var_enableCompRef2Id) { |
| f_EPTF_oct2int_HashMap_Insert(v_EPTF_Var_Hashmap_CompRef2Id,pl_contentRef.valueRef,pl_idx); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_initContent |
| // |
| // Purpose: |
| // Sets the content to a directContent |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_initContent(in integer pl_idx, in EPTF_Var_DirectContent pl_content) runs on EPTF_Var_CT { |
| v_EPTF_Vars[pl_idx].content := { |
| direct := pl_content |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_initContentInvalid |
| // |
| // Purpose: |
| // Sets the content to a invalid |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_initContentInvalid(in integer pl_idx) runs on EPTF_Var_CT { |
| v_EPTF_Vars[pl_idx].content := { |
| invalid := {} |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_content2direct |
| // |
| // Purpose: |
| // Converts the content of an EPTF variable to direct content (dereferences if it is a reference) |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_content2direct(in EPTF_Var_Content pl_content, out EPTF_Var_DirectContent pl_directContent) runs on EPTF_Var_CT { |
| if (ischosen(pl_content.invalid)) { |
| //f_EPTF_Var_error(log2str("ERROR:","Cannot convert invalid content to direct content ",pl_directContent,".")); |
| //f_EPTF_Base_stop(); |
| pl_directContent := {unknownVal := {omit}}; |
| return; |
| } |
| if (ischosen(pl_content.direct)) { |
| pl_directContent := pl_content.direct; |
| return; |
| } |
| // referenced content |
| if (pl_content.reference.refType == intType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { intVal := 0 }; |
| return; |
| } |
| pl_directContent := { intVal := f_EPTF_Var_derefInt(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == floatType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { floatVal := 0.0 }; |
| return; |
| } |
| pl_directContent := { floatVal := f_EPTF_Var_derefFloat(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == boolType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { boolVal := false }; |
| return; |
| } |
| pl_directContent := { boolVal := f_EPTF_Var_derefBool(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == charstringType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { charstringVal := "" }; |
| return; |
| } |
| pl_directContent := { charstringVal := f_EPTF_Var_derefCharstring(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == octetstringType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { octetstringVal := ''O }; |
| return; |
| } |
| pl_directContent := { octetstringVal := f_EPTF_Var_derefOctetstring(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == hexstringType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { hexstringVal := ''H }; |
| return; |
| } |
| pl_directContent := { hexstringVal := f_EPTF_Var_derefHexstring(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == bitstringType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { bitstringVal := ''B }; |
| return; |
| } |
| pl_directContent := { bitstringVal := f_EPTF_Var_derefBitstring(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == integerlistType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { integerlistVal := {} }; |
| return; |
| } |
| pl_directContent := { integerlistVal := f_EPTF_Var_derefIntegerlist(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == floatlistType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { floatlistVal := {} }; |
| return; |
| } |
| pl_directContent := { floatlistVal := f_EPTF_Var_derefFloatlist(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == charstringlistType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { charstringlistVal := {} }; |
| return; |
| } |
| pl_directContent := { charstringlistVal := f_EPTF_Var_derefCharstringlist(pl_content.reference.valueRef) }; |
| return; |
| } |
| if (pl_content.reference.refType == statusLEDType) { |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| // cleanup is in progress: if referred variable accessed: default value is returned |
| pl_directContent := { statusLEDVal := {color:=led_black,text:="N/A"} }; |
| return; |
| } |
| pl_directContent := { statusLEDVal := f_EPTF_Var_derefStatusLED(pl_content.reference.valueRef) }; |
| return; |
| } |
| //... |
| |
| f_EPTF_Var_error(log2str("ERROR:","Cannot convert this content to direct content: ",pl_content)); |
| //f_EPTF_Base_stop(); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_direct2content |
| // |
| // Purpose: |
| // Converts a direct content of an EPTF variable to content (dereferences if it is a reference) |
| // Returns true on success, fail on error |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_direct2content(in EPTF_Var_DirectContent pl_directContent, inout EPTF_Var_Content pl_content) runs on EPTF_Var_CT |
| return boolean { |
| if (ischosen(pl_content.invalid)) { |
| if (not ischosen(pl_directContent.unknownVal)) { |
| f_EPTF_Var_warning(log2str("ERROR:","Cannot convert direct content ",pl_directContent," to invalid content.")); |
| return false; |
| //f_EPTF_Base_stop(); |
| } else { |
| return true; // Do nothing, leave it invalid |
| } |
| } |
| if (ischosen(pl_content.direct)) { |
| if (ischosen(pl_content.direct.intVal) and ischosen(pl_directContent.intVal)) { |
| pl_content.direct.intVal := pl_directContent.intVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.floatVal) and ischosen(pl_directContent.floatVal)) { |
| pl_content.direct.floatVal := pl_directContent.floatVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.boolVal) and ischosen(pl_directContent.boolVal)) { |
| pl_content.direct.boolVal := pl_directContent.boolVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.charstringVal) and ischosen(pl_directContent.charstringVal)) { |
| pl_content.direct.charstringVal := pl_directContent.charstringVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.octetstringVal) and ischosen(pl_directContent.octetstringVal)) { |
| pl_content.direct.octetstringVal := pl_directContent.octetstringVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.hexstringVal) and ischosen(pl_directContent.hexstringVal)) { |
| pl_content.direct.hexstringVal := pl_directContent.hexstringVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.bitstringVal) and ischosen(pl_directContent.bitstringVal)) { |
| pl_content.direct.bitstringVal := pl_directContent.bitstringVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.integerlistVal) and ischosen(pl_directContent.integerlistVal)) { |
| pl_content.direct.integerlistVal := pl_directContent.integerlistVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.floatlistVal) and ischosen(pl_directContent.floatlistVal)) { |
| pl_content.direct.floatlistVal := pl_directContent.floatlistVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.charstringlistVal) and ischosen(pl_directContent.charstringlistVal)) { |
| pl_content.direct.charstringlistVal := pl_directContent.charstringlistVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.statusLEDVal) and ischosen(pl_directContent.statusLEDVal)) { |
| pl_content.direct.statusLEDVal := pl_directContent.statusLEDVal; |
| return true; |
| } |
| if (ischosen(pl_content.direct.unknownVal) and ischosen(pl_directContent.unknownVal)) { |
| pl_content.direct.unknownVal := pl_directContent.unknownVal; |
| return true; |
| } |
| //... |
| f_EPTF_Var_warning(log2str("ERROR:","Cannot convert direct content ",pl_directContent," to direct content ",pl_content,". Types are incompatible")); |
| return false; |
| //f_EPTF_Base_stop(); |
| } |
| // referenced content |
| if (not f_EPTF_Base_cleanupIsInProgress()) { |
| return true;// cleanup is in progress: referred variable is not modified |
| } |
| if ((pl_content.reference.refType == intType) and ischosen(pl_directContent.intVal)) { |
| f_EPTF_Var_modifyIntRefValue(pl_content.reference.valueRef, pl_directContent.intVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == floatType) and ischosen(pl_directContent.floatVal)) { |
| f_EPTF_Var_modifyFloatRefValue(pl_content.reference.valueRef, pl_directContent.floatVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == boolType) and ischosen(pl_directContent.boolVal)) { |
| f_EPTF_Var_modifyBoolRefValue(pl_content.reference.valueRef, pl_directContent.boolVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == charstringType) and ischosen(pl_directContent.charstringVal)) { |
| f_EPTF_Var_modifyCharstringRefValue(pl_content.reference.valueRef, pl_directContent.charstringVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == octetstringType) and ischosen(pl_directContent.octetstringVal)) { |
| f_EPTF_Var_modifyOctetstringRefValue(pl_content.reference.valueRef, pl_directContent.octetstringVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == hexstringType) and ischosen(pl_directContent.hexstringVal)) { |
| f_EPTF_Var_modifyHexstringRefValue(pl_content.reference.valueRef, pl_directContent.hexstringVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == bitstringType) and ischosen(pl_directContent.bitstringVal)) { |
| f_EPTF_Var_modifyBitstringRefValue(pl_content.reference.valueRef, pl_directContent.bitstringVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == integerlistType) and ischosen(pl_directContent.integerlistVal)) { |
| f_EPTF_Var_modifyIntegerlistRefValue(pl_content.reference.valueRef, pl_directContent.integerlistVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == floatlistType) and ischosen(pl_directContent.floatlistVal)) { |
| f_EPTF_Var_modifyFloatlistRefValue(pl_content.reference.valueRef, pl_directContent.floatlistVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == charstringlistType) and ischosen(pl_directContent.charstringlistVal)) { |
| f_EPTF_Var_modifyCharstringlistRefValue(pl_content.reference.valueRef, pl_directContent.charstringlistVal); |
| return true; |
| } |
| if ((pl_content.reference.refType == statusLEDType) and ischosen(pl_directContent.statusLEDVal)) { |
| f_EPTF_Var_modifyStatusLEDRefValue(pl_content.reference.valueRef, pl_directContent.statusLEDVal); |
| return true; |
| } |
| //... |
| f_EPTF_Var_warning(log2str("ERROR:","Cannot convert direct content ",pl_directContent," to referenced content ",pl_content)); |
| return false; |
| //f_EPTF_Base_stop(); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_directContent2str |
| // |
| // Purpose: |
| // Converts direct content to charstring |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_directContent2str(in EPTF_Var_DirectContent pl_directContent) return charstring { |
| if (ischosen(pl_directContent.intVal)) { |
| return int2str(pl_directContent.intVal); |
| } |
| if (ischosen(pl_directContent.floatVal)) { |
| return float2str(pl_directContent.floatVal); |
| } |
| if (ischosen(pl_directContent.boolVal)) { |
| if (pl_directContent.boolVal) { |
| return "true"; |
| } |
| return "false"; |
| } |
| if (ischosen(pl_directContent.charstringVal)) { |
| return pl_directContent.charstringVal; |
| } |
| if (ischosen(pl_directContent.octetstringVal)) { |
| return oct2str(pl_directContent.octetstringVal); |
| } |
| if (ischosen(pl_directContent.hexstringVal)) { |
| return hex2str(pl_directContent.hexstringVal); |
| } |
| if (ischosen(pl_directContent.bitstringVal)) { |
| return bit2str(pl_directContent.bitstringVal); |
| } |
| if (ischosen(pl_directContent.integerlistVal)) { |
| var charstring vl_result := "{ "; |
| for (var integer i:=0; i<sizeof(pl_directContent.integerlistVal); i:=i+1) { |
| if (i>0) { |
| vl_result := vl_result & ", "; |
| } |
| vl_result := vl_result & int2str(pl_directContent.integerlistVal[i]); |
| } |
| vl_result := vl_result & " }"; |
| return vl_result; |
| } |
| if (ischosen(pl_directContent.floatlistVal)) { |
| var charstring vl_result := "{ "; |
| for (var integer i:=0; i<sizeof(pl_directContent.floatlistVal); i:=i+1) { |
| if (i>0) { |
| vl_result := vl_result & ", "; |
| } |
| vl_result := vl_result & float2str(pl_directContent.floatlistVal[i]); |
| } |
| vl_result := vl_result & " }"; |
| return vl_result; |
| } |
| if (ischosen(pl_directContent.charstringlistVal)) { |
| var charstring vl_result := "{ "; |
| for (var integer i:=0; i<sizeof(pl_directContent.charstringlistVal); i:=i+1) { |
| if (i>0) { |
| vl_result := vl_result & ", "; |
| } |
| vl_result := vl_result & log2str(pl_directContent.charstringlistVal[i]); |
| } |
| vl_result := vl_result & " }"; |
| return vl_result; |
| } |
| if (ischosen(pl_directContent.statusLEDVal)) |
| { |
| var charstring vl_ledText := ""; |
| if (ispresent(pl_directContent.statusLEDVal.text)) { |
| vl_ledText:=pl_directContent.statusLEDVal.text; |
| } |
| if (pl_directContent.statusLEDVal.color == led_blue) { return "[led:blue]" & vl_ledText } |
| else if (pl_directContent.statusLEDVal.color == led_black) { return "[led:black]" & vl_ledText } |
| else if (pl_directContent.statusLEDVal.color == led_yellow) { return "[led:yellow]" & vl_ledText } |
| else if (pl_directContent.statusLEDVal.color == led_green) { return "[led:green]" & vl_ledText } |
| else if (pl_directContent.statusLEDVal.color == led_red) { return "[led:red]" & vl_ledText } |
| return "[led:black]" & vl_ledText & " ERROR:color of LED is not supported! Color set to BLACK."; |
| } |
| if (ischosen(pl_directContent.unknownVal)) { |
| return "unknownValueOfType "&ttcn2string(pl_directContent.unknownVal); |
| } |
| //... |
| f_EPTF_Common_error(log2str("ERROR:","Cannot convert direct content ",pl_directContent," to string.")); |
| //f_EPTF_Logging_error(true,log2str("Cannot convert direct content ",pl_directContent," to string.")); |
| stop; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_str2directContent |
| // |
| // Purpose: |
| // Converts charstring to direct content |
| // The pl_directContent determines the type of the result |
| // |
| // Return Value: |
| // *integer* - error code: 0 if OK, nonzero if conversion failed |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_str2directContent(in charstring pl_valueStr, inout EPTF_Var_DirectContent pl_directContent) return integer { |
| if (ischosen(pl_directContent.intVal)) { |
| var charstring vl_currentValueStr := regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_integerNumber&c_EPTF_Var_whitespace,0); |
| if (vl_currentValueStr!="") { |
| pl_directContent.intVal := str2int(vl_currentValueStr); |
| } else { |
| return 1; // error |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.floatVal)) { |
| var charstring vl_currentValueStr := regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_floatNumber&c_EPTF_Var_whitespace,0); |
| if (vl_currentValueStr!="") { |
| pl_directContent.floatVal := str2float(vl_currentValueStr); |
| } else { |
| return 1; // error |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.boolVal)) { |
| var charstring vl_currentValueStr := regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_anyWord&c_EPTF_Var_whitespace,0); |
| if (vl_currentValueStr == "true" or vl_currentValueStr == "false" ) { |
| pl_directContent.boolVal := "true" == vl_currentValueStr |
| } else { |
| return 1; // error |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.charstringVal)) { |
| pl_directContent.charstringVal := pl_valueStr; |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.octetstringVal)) { |
| var charstring vl_currentValueStr := regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_octetstringNumber&c_EPTF_Var_whitespace,0); |
| if (vl_currentValueStr!="") { |
| pl_directContent.octetstringVal := str2oct(vl_currentValueStr); |
| } else if ("" == regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_anyWord&c_EPTF_Var_whitespace,0)) { |
| pl_directContent.octetstringVal := ''O; |
| } else { |
| return 1; // error |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.hexstringVal)) { |
| var charstring vl_currentValueStr := regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_hexstringNumber&c_EPTF_Var_whitespace,0); |
| if (vl_currentValueStr!="") { |
| pl_directContent.hexstringVal := str2hex(vl_currentValueStr); |
| } else if ("" == regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_anyWord&c_EPTF_Var_whitespace,0)) { |
| pl_directContent.hexstringVal := ''H; |
| } else { |
| return 1; // error |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.bitstringVal)) { |
| var charstring vl_currentValueStr := regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_bitstringNumber&c_EPTF_Var_whitespace,0); |
| if (vl_currentValueStr!="") { |
| pl_directContent.bitstringVal := str2bit(vl_currentValueStr); |
| } else if ("" == regexp(pl_valueStr,c_EPTF_Var_whitespace&c_EPTF_Var_anyWord&c_EPTF_Var_whitespace,0)) { |
| pl_directContent.bitstringVal := ''B; |
| } else { |
| return 1; // error |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.integerlistVal)) { |
| pl_directContent.integerlistVal := {}; |
| var charstring vl_remaining := regexp(pl_valueStr,c_EPTF_Var_whitespace&"{"&c_EPTF_Var_whitespace&c_EPTF_Var_everything&c_EPTF_Var_whitespace&"}"&c_EPTF_Var_whitespace,0); // trim down the {}-s |
| var charstring vl_emptyList := regexp(pl_valueStr,c_EPTF_Var_whitespace&"({"&c_EPTF_Var_whitespace&"})"&c_EPTF_Var_whitespace,0); // check empty list |
| if (vl_emptyList!="") { // empty list |
| return 0; // OK |
| } |
| |
| if (vl_remaining=="" // not matched or empty list |
| and "" == vl_emptyList) { // not empty list |
| return 1; // syntax error |
| } |
| |
| var charstring vl_currentValueStr := regexp(vl_remaining,c_EPTF_Var_integerNumber&c_EPTF_Var_everything,0); // first element |
| if (vl_remaining != "" and vl_currentValueStr == "") { |
| return 1; // syntax error: string does not begin with integer |
| } |
| for(var integer i:=0; vl_currentValueStr != ""; i:=i+1) { |
| pl_directContent.integerlistVal[i] := str2int(vl_currentValueStr); |
| vl_remaining := regexp(vl_remaining,c_EPTF_Var_integerNumber&c_EPTF_Var_whitespace&"[,]#(0,1)"&c_EPTF_Var_whitespace&c_EPTF_Var_everything,1); // the rest |
| vl_currentValueStr := regexp(vl_remaining,c_EPTF_Var_integerNumber&c_EPTF_Var_everything,0); // next element |
| if (vl_remaining != "" and vl_currentValueStr == "") { |
| return 1; // syntax error: string does not begin with integer |
| } |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.floatlistVal)) { |
| pl_directContent.floatlistVal := {}; |
| var charstring vl_remaining := regexp(pl_valueStr,c_EPTF_Var_whitespace&"{"&c_EPTF_Var_whitespace&c_EPTF_Var_everything&c_EPTF_Var_whitespace&"}"&c_EPTF_Var_whitespace,0); // trim down the {}-s |
| var charstring vl_emptyList := regexp(pl_valueStr,c_EPTF_Var_whitespace&"({"&c_EPTF_Var_whitespace&"})"&c_EPTF_Var_whitespace,0); // check empty list |
| if (vl_emptyList!="") { // empty list |
| return 0; // OK |
| } |
| |
| if (vl_remaining=="" // not matched or empty list |
| and "" == vl_emptyList) { // not empty list |
| return 1; // syntax error |
| } |
| |
| var charstring vl_currentValueStr := regexp(vl_remaining,c_EPTF_Var_floatNumber&c_EPTF_Var_everything,0); // first element |
| if (vl_remaining != "" and vl_currentValueStr == "") { |
| return 1; // syntax error: string does not begin with float |
| } |
| for(var integer i:=0; vl_currentValueStr != ""; i:=i+1) { |
| pl_directContent.floatlistVal[i] := str2float(vl_currentValueStr); |
| vl_remaining := regexp(vl_remaining,c_EPTF_Var_floatNumber&c_EPTF_Var_whitespace&"[,]#(0,1)"&c_EPTF_Var_whitespace&c_EPTF_Var_everything,2); // the rest |
| vl_currentValueStr := regexp(vl_remaining,c_EPTF_Var_floatNumber&c_EPTF_Var_everything,0); // next element |
| if (vl_remaining != "" and vl_currentValueStr == "") { |
| return 1; // syntax error: string does not begin with float |
| } |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.charstringlistVal)) { |
| pl_directContent.charstringlistVal := {}; |
| var charstring vl_remaining := regexp(pl_valueStr,c_EPTF_Var_whitespace&"{"&c_EPTF_Var_whitespace&c_EPTF_Var_everything&c_EPTF_Var_whitespace&"}"&c_EPTF_Var_whitespace,0); // trim down the {}-s |
| var charstring vl_emptyList := regexp(pl_valueStr,c_EPTF_Var_whitespace&"({"&c_EPTF_Var_whitespace&"})"&c_EPTF_Var_whitespace,0); // check empty list |
| if (vl_emptyList!="") { // empty list |
| return 0; // OK |
| } |
| |
| if (vl_remaining=="" // not matched or empty list |
| and "" == vl_emptyList) { // not empty list |
| return 1; // syntax error |
| } |
| |
| for(var integer i:=0; vl_remaining != ""; i:=i+1) { |
| var charstring vl_currentValueStr := regexp(vl_remaining,c_EPTF_Var_charstringValue&c_EPTF_Var_everything,0); // next element |
| if (vl_remaining != "" and vl_currentValueStr == "" // current value does not match or string is empty |
| and "" == regexp(vl_remaining,"("""")"&c_EPTF_Var_everything,0)) { // not starts with empty string |
| return 1; // syntax error: string does not begin with string |
| } |
| vl_remaining := regexp(vl_remaining,c_EPTF_Var_charstringValue&c_EPTF_Var_whitespace&"[,]#(0,1)"&c_EPTF_Var_whitespace&c_EPTF_Var_everything,1); // the rest |
| pl_directContent.charstringlistVal[i] := vl_currentValueStr; |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.statusLEDVal)) |
| { |
| var charstring vl_ledColor := regexp(pl_valueStr,c_EPTF_Var_whitespace&"\\["&c_EPTF_Var_anyWord&"\\]"&c_EPTF_Var_everything,0); |
| var charstring vl_ledText := regexp(pl_valueStr,c_EPTF_Var_whitespace&"\\["&c_EPTF_Var_anyWord&"\\]"&c_EPTF_Var_everything,1); |
| if (vl_ledText != "") { |
| pl_directContent.statusLEDVal.text := vl_ledText; |
| } else { |
| pl_directContent.statusLEDVal.text := omit; |
| } |
| if (vl_ledColor == "led:blue") { pl_directContent.statusLEDVal.color := led_blue } |
| else if (vl_ledColor == "led:black") { pl_directContent.statusLEDVal.color := led_black } |
| else if (vl_ledColor == "led:yellow") { pl_directContent.statusLEDVal.color := led_yellow } |
| else if (vl_ledColor == "led:green") { pl_directContent.statusLEDVal.color := led_green } |
| else if (vl_ledColor == "led:red") { pl_directContent.statusLEDVal.color := led_red } |
| else { |
| return 1; // invalid color |
| } |
| return 0; // OK |
| } |
| if (ischosen(pl_directContent.unknownVal)) { |
| var charstring vl_currentValueStr := regexp(pl_valueStr,c_EPTF_Var_whitespace&"unknownValueOfType "&c_EPTF_Var_everything,0); |
| if (vl_currentValueStr!="") { |
| string2ttcn(vl_currentValueStr, pl_directContent.unknownVal.dataType); |
| } else { |
| return 1; // error |
| } |
| return 0; // OK |
| } |
| //... |
| return 1; // error (never executed) |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_directContent2string |
| // |
| // Purpose: |
| // Converts direct content to charstring (cfg file format) |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_directContent2string(in EPTF_Var_DirectContent pl_directContent) return charstring { |
| if (ischosen(pl_directContent.intVal)) { |
| return "{ intVal := " &f_EPTF_Var_directContent2str(pl_directContent)&" }"; |
| } |
| if (ischosen(pl_directContent.floatVal)) { |
| return "{ floatVal := " &f_EPTF_Var_directContent2str(pl_directContent)&" }"; |
| } |
| if (ischosen(pl_directContent.boolVal)) { |
| return "{ boolVal := " &f_EPTF_Var_directContent2str(pl_directContent)&" }"; |
| } |
| if (ischosen(pl_directContent.charstringVal)) { |
| return "{ charstringVal := \"" &f_EPTF_Var_directContent2str(pl_directContent)&"\" }"; |
| } |
| if (ischosen(pl_directContent.octetstringVal)) { |
| return "{ octetstringVal := '" &f_EPTF_Var_directContent2str(pl_directContent)&"'O }"; |
| } |
| if (ischosen(pl_directContent.hexstringVal)) { |
| return "{ hexstringVal := '" &f_EPTF_Var_directContent2str(pl_directContent)&"'H }"; |
| } |
| if (ischosen(pl_directContent.bitstringVal)) { |
| return "{ bitstringVal := '" &f_EPTF_Var_directContent2str(pl_directContent)&"'B }"; |
| } |
| if (ischosen(pl_directContent.integerlistVal)) { |
| return "{ integerlistVal := " &f_EPTF_Var_directContent2str(pl_directContent)&" }"; |
| } |
| if (ischosen(pl_directContent.floatlistVal)) { |
| return "{ floatlistVal := " &f_EPTF_Var_directContent2str(pl_directContent)&" }"; |
| } |
| if (ischosen(pl_directContent.charstringlistVal)) { |
| return "{ charstringlistVal := " &f_EPTF_Var_directContent2str(pl_directContent)&" }"; |
| } |
| if (ischosen(pl_directContent.statusLEDVal)) { |
| var charstring vl_ledText := ""; |
| if (ispresent(pl_directContent.statusLEDVal.text)) { |
| vl_ledText:=pl_directContent.statusLEDVal.text; |
| } |
| var charstring vl_ledColor := "led_black"; |
| if (pl_directContent.statusLEDVal.color == led_blue) { vl_ledColor := "led_blue" } |
| else if (pl_directContent.statusLEDVal.color == led_black) { vl_ledColor := "led_black" } |
| else if (pl_directContent.statusLEDVal.color == led_yellow) { vl_ledColor := "led_yellow" } |
| else if (pl_directContent.statusLEDVal.color == led_green) { vl_ledColor := "led_green" } |
| else if (pl_directContent.statusLEDVal.color == led_red) { vl_ledColor := "led_red" } |
| return "{ statusLEDVal := { color := "&vl_ledColor&", text := \""&vl_ledText&"\" } }"; |
| } |
| //... |
| f_EPTF_Common_error(log2str("ERROR:","Cannot convert direct content ",pl_directContent," to string.")); |
| //f_EPTF_Logging_error(true,log2str("Cannot convert direct content ",pl_directContent," to string.")); |
| stop; |
| } |
| |
| // SUBSCRIBING |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addLocalSubscriber |
| // |
| // Purpose: |
| // Adds the pl_idx variable as a local subscriber to the local variables given by pl_argList |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_addLocalSubscriber(in integer pl_idx, in EPTF_IntegerList pl_argList) runs on EPTF_Var_CT { |
| var integer vl_last, vl_providerIdx; |
| for(var integer i:=0; i<sizeof(pl_argList); i:=i+1) { |
| vl_providerIdx := pl_argList[i]; |
| vl_last := sizeof(v_EPTF_Vars[vl_providerIdx].subscribers); |
| v_EPTF_Vars[vl_providerIdx].subscribers[vl_last] := { |
| local := pl_idx |
| } |
| if (not f_EPTF_Var_checkSubscriptionMode(vl_providerIdx,pull) and not f_EPTF_Var_checkLocalSubscriptionMode(vl_providerIdx,pull)) { |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_getContent(vl_providerIdx,vl_currentContent); |
| f_EPTF_Var_registerRefresh(vl_providerIdx,vl_currentContent); |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeLocalSubscriber |
| // |
| // Purpose: |
| // Removes the pl_idx variable as a local subscriber from the local variables given by pl_argList |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_removeLocalSubscriber(in integer pl_idx, in EPTF_IntegerList pl_argList) runs on EPTF_Var_CT { |
| var integer vl_last, vl_providerIdx; |
| var EPTF_Var_Subscribers vl_oldSubscribers; |
| for(var integer i:=0; i<sizeof(pl_argList); i:=i+1) { |
| vl_providerIdx := pl_argList[i]; |
| vl_oldSubscribers := v_EPTF_Vars[vl_providerIdx].subscribers; |
| vl_last := sizeof(vl_oldSubscribers); |
| v_EPTF_Vars[vl_providerIdx].subscribers := {}; |
| for (var integer j:=0; j<vl_last; j:=j+1) { |
| if (not (ischosen(vl_oldSubscribers[j].local) and vl_oldSubscribers[j].local == pl_idx) ) { |
| v_EPTF_Vars[vl_providerIdx].subscribers[sizeof(v_EPTF_Vars[vl_providerIdx].subscribers)] := vl_oldSubscribers[j] |
| } |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addRemoteSubscriber |
| // |
| // Purpose: |
| // Adds the remote provider as a remote subscriber to the pl_idx variable, |
| // the subscription mode can be set in the remote provider |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_addRemoteSubscriber(in integer pl_idx, in EPTF_Var_SubscriberRemote pl_remoteProvider) runs on EPTF_Var_CT { |
| var integer vl_last := sizeof(v_EPTF_Vars[pl_idx].subscribers); |
| v_EPTF_Vars[pl_idx].subscribers[vl_last] := { |
| remote := pl_remoteProvider |
| } |
| if (pl_remoteProvider.subscriptionMode == timeLine) { |
| v_EPTF_Vars[pl_idx].nofTimelineSubscribers := v_EPTF_Vars[pl_idx].nofTimelineSubscribers + 1; |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeRemoteSubscriber |
| // |
| // Purpose: |
| // Removes the remote provider as a remote subscriber from the pl_idx variable |
| // the subscription mode can be set in the remote provider |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_removeRemoteSubscriber(in integer pl_idx, in EPTF_Var_Ref pl_remoteProvider) runs on EPTF_Var_CT { |
| var integer vl_last; |
| var EPTF_Var_Subscribers vl_oldSubscribers; |
| vl_oldSubscribers := v_EPTF_Vars[pl_idx].subscribers; |
| vl_last := sizeof(vl_oldSubscribers); |
| v_EPTF_Vars[pl_idx].subscribers := {}; |
| for (var integer j:=0; j<vl_last; j:=j+1) { |
| if (not (ischosen(vl_oldSubscribers[j].remote) and vl_oldSubscribers[j].remote.varRef == pl_remoteProvider) ) { |
| v_EPTF_Vars[pl_idx].subscribers[sizeof(v_EPTF_Vars[pl_idx].subscribers)] := vl_oldSubscribers[j] |
| } else { |
| if (vl_oldSubscribers[j].remote.subscriptionMode == timeLine) { |
| v_EPTF_Vars[pl_idx].nofTimelineSubscribers := v_EPTF_Vars[pl_idx].nofTimelineSubscribers - 1; |
| } |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getTopProviderType |
| // |
| // Purpose: |
| // Returns the top provider type of the given EPTF Variable |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_getTopProviderType(in integer pl_idx, out EPTF_TopProviderType pl_topProviderType) runs on EPTF_Var_CT { |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.empty)) { |
| pl_topProviderType := empty; |
| return; |
| } |
| if (ischosen(v_EPTF_Vars[pl_idx].provider.local)) { |
| pl_topProviderType := local; |
| return; |
| } |
| pl_topProviderType := v_EPTF_Vars[pl_idx].provider.remote.topProviderType; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_findSubscription |
| // |
| // Purpose: |
| // Finds the variable that has subscribed for pl_remoteProviderRef, |
| // if not found pl_idx is set to -1. |
| // Buffered and non-buffered subscriptions modes are treated the same way (subscriptions mode flag is ignored) |
| // This makes it impossible to subscribe in a non-buffered way and then subscribe in buffered way |
| // to the same variable |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_findSubscription(in EPTF_Var_CT pl_remoteCompRef, in charstring pl_remoteProviderVarName, out integer pl_idx) runs on EPTF_Var_CT { |
| pl_idx := -1; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_Var_Hashmap_Provider2Id,log2str(pl_remoteCompRef)&"."&pl_remoteProviderVarName,pl_idx)) { |
| //remove the warning |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_sendSubscribe |
| // |
| // Purpose: |
| // Sends the subscribe message to the remote provider |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_sendSubscribe( |
| in integer pl_idx, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| in integer pl_refreshRate, |
| in integer pl_blockingFlagIdx := -1 |
| ) runs on EPTF_Var_CT { |
| f_EPTF_Var_addConnection(pl_remoteCompRef); |
| f_EPTF_Var_send({subscribe := {v_EPTF_Vars[pl_idx].name,{self,pl_idx},pl_remoteProviderVarName,pl_subscriptionMode,pl_refreshRate,pl_blockingFlagIdx}}, pl_remoteCompRef); |
| } |
| |
| // removes the pl_idx variable as a remote subscriber from the remote provider |
| private function f_EPTF_sendUnsubscribe(in integer pl_idx, in EPTF_Var_Ref pl_remoteProviderRef, in EPTF_Var_SubscriptionMode pl_subscriptionMode, in integer pl_refreshRate) runs on EPTF_Var_CT { |
| f_EPTF_Var_send({unsubscribe := {{self,pl_idx},pl_remoteProviderRef,pl_subscriptionMode,pl_refreshRate}}, pl_remoteProviderRef.compRef); |
| f_EPTF_Var_removeConnection(pl_idx, pl_remoteProviderRef); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_sendSubscribe_nonBlocking |
| // |
| // Purpose: |
| // Nonblocking version of <f_EPTF_Var_sendSubscribe>. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_sendSubscribe_nonBlocking( |
| in integer pl_idx, |
| in EPTF_Var_CT pl_remoteCompRef, |
| in charstring pl_remoteProviderVarName, |
| in EPTF_Var_SubscriptionMode pl_subscriptionMode, |
| in integer pl_refreshRate |
| ) runs on EPTF_Var_CT { |
| |
| var EPTF_Var_MgmtMsg vl_msgToSend := { |
| subscribe := { |
| subscriberVarName := v_EPTF_Vars[pl_idx].name, |
| subscriber := {self,pl_idx}, |
| providerVarName := pl_remoteProviderVarName, |
| subscriptionMode := pl_subscriptionMode, |
| refreshRate := pl_refreshRate, |
| blockingFlagIdx := -1 |
| } |
| } |
| |
| if (f_EPTF_Var_isConnected(pl_remoteCompRef)){ |
| f_EPTF_Var_send(vl_msgToSend, pl_remoteCompRef); |
| }else{ // if not connected buffering the messages until HelloAck arrives |
| var integer vl_bufferIdx := f_EPTF_Base_upcast(pl_remoteCompRef); |
| if(not isbound(v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx])){ |
| v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx] := {}; |
| } |
| v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx][sizeof(v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx])] := { |
| msg := vl_msgToSend, |
| destinationCompRef := pl_remoteCompRef |
| } |
| f_EPTF_Var_addConnection_nonBlocking(pl_remoteCompRef); |
| } |
| } |
| |
| private function f_EPTF_Var_connectCallback(in EPTF_Var_CT pl_remoteCompRef) runs on EPTF_Var_CT { |
| |
| var integer vl_bufferIdx := f_EPTF_Base_upcast(pl_remoteCompRef); |
| |
| if(f_EPTF_Var_isConnected(pl_remoteCompRef)){ |
| for(var integer i:= 0; i<sizeof(v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx]); i:=i+1) { |
| f_EPTF_Var_send(v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx][i].msg,v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx][i].destinationCompRef); |
| } |
| }else{ |
| if(sizeof(v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx])>0){ |
| f_EPTF_Var_warning(log2str(%definitionId, ": No connection towards component ", pl_remoteCompRef, ". Message is not sent, ignored.")); |
| } |
| } |
| v_EPTF_Var_msgBufferBeforeConnect[vl_bufferIdx] := {}; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addConnection |
| // |
| // Purpose: |
| // Checks if there is a connection towards the pl_remoteProvider. if connection does not exist creates it. |
| // uses the 0-th syncBuffer for that. The variable is only added to the syncBuffer if the subscription is buffered, |
| // but the sync buffer for that component is always created. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_addConnection(in EPTF_Var_CT pl_remoteCompRef) runs on EPTF_Var_CT { |
| if (f_EPTF_Var_getConnectionState(pl_remoteCompRef) == terminated) { |
| // no more connection possible |
| f_EPTF_Var_warning(log2str(%definitionId, ": Cannot create new connection towards component ", pl_remoteCompRef, " : Component has already terminated!")); |
| return; |
| } |
| |
| // if not connected: |
| if (not f_EPTF_Var_isConnected(pl_remoteCompRef)) { |
| f_EPTF_Var_connect(pl_remoteCompRef); |
| // f_EPTF_Var_registerConnection is called when helloAck arrives in f_EPTF_Var_handle_HelloAck |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_addConnection_nonBlocking |
| // |
| // Purpose: |
| // Nonblocking version of <f_EPTF_Var_addConnection>. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_addConnection_nonBlocking( |
| in EPTF_Var_CT pl_remoteCompRef |
| ) runs on EPTF_Var_CT { |
| if (f_EPTF_Var_getConnectionState(pl_remoteCompRef) == terminated) { |
| // no more connection possible |
| f_EPTF_Var_warning(log2str(%definitionId, ": Cannot create new connection towards component ", pl_remoteCompRef, " : Component has already terminated!")); |
| // call handler function |
| f_EPTF_Var_connectCallback(pl_remoteCompRef); |
| return; |
| } |
| |
| // if not connected: |
| if (not f_EPTF_Var_isConnected(pl_remoteCompRef)) { |
| f_EPTF_Var_connect_nonBlocking(pl_remoteCompRef); |
| // f_EPTF_Var_registerConnection is called when helloAck arrives in f_EPTF_Var_handle_HelloAck |
| }else { // already connected therefore call the connect handler |
| f_EPTF_Var_connectCallback(pl_remoteCompRef); |
| } |
| } |
| |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_connect |
| // |
| // Purpose: |
| // Sets up a connection towards the remote component. |
| // If the setup is successful (helloAck arrives) it continues execution. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_connect(in EPTF_Var_CT pl_remoteCompRef) runs on EPTF_Var_CT { |
| connect(self:EPTF_Var_MgmtIf,pl_remoteCompRef:EPTF_Var_MgmtIf); |
| |
| // send hello and wait for the answer |
| var integer vl_trID := f_EPTF_setNewboolean(v_booleanPool,false); |
| EPTF_Var_MgmtIf.send( |
| {hello:={ |
| vl_trID |
| }} |
| ) to pl_remoteCompRef; |
| |
| v_EPTF_Var_numPendingHellos := v_EPTF_Var_numPendingHellos + 1; |
| |
| // create a blocking flag & block execution until helloAck arrives |
| timer t_minWait := 0.0; // zero wait |
| timer t_maxWait := v_EPTF_Var_maxWaitTimeForByeAck; // maximum wait |
| t_minWait.start; |
| t_maxWait.start; |
| // wait until response is received: |
| alt { |
| [f_EPTF_getValueboolean(v_booleanPool,vl_trID)] t_minWait.timeout; |
| [] t_maxWait.timeout { |
| f_EPTF_Var_warning(log2str("Connection establishment is unsuccessful: No response received for hello from: ", pl_remoteCompRef)); |
| } |
| } |
| // remove the bool from the pool: |
| f_EPTF_deleteboolean(v_booleanPool,vl_trID); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_connect_nonBlocking |
| // |
| // Purpose: |
| // Non-blocking version of <f_EPTF_Var_connect>. |
| // It does not wait until the helloAck arrives. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_connect_nonBlocking( |
| in EPTF_Var_CT pl_remoteCompRef |
| ) runs on EPTF_Var_CT { |
| v_EPTF_Var_nonBlockingEnabled[f_EPTF_Base_upcast(pl_remoteCompRef)] := true; |
| connect(self:EPTF_Var_MgmtIf,pl_remoteCompRef:EPTF_Var_MgmtIf); |
| |
| // send hello and don't wait for the answer |
| var integer vl_trID := f_EPTF_setNewboolean(v_booleanPool,false); |
| EPTF_Var_MgmtIf.send( |
| {hello:={ |
| vl_trID |
| }} |
| ) to pl_remoteCompRef; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_isConnected |
| // |
| // Purpose: |
| // Checks if there is a connection towards the pl_remoteCompRef. if connection exists returns true, |
| // else it returns false. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_isConnected(in EPTF_Var_CT pl_remoteCompRef) runs on EPTF_Var_CT return boolean { |
| return f_EPTF_Var_getConnectionState(pl_remoteCompRef) == connected; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_checkConnection |
| // |
| // Purpose: |
| // Checks if there is a connection towards the pl_remoteCompRef for a given refreshRate. if connection exists sets pl_refreshRateId and pl_compBufferIdx to its idx, |
| // else it is set to -1. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_checkConnection(in EPTF_Var_CT pl_remoteCompRef, in integer pl_refreshRate, out integer pl_refreshRateId, out integer pl_compBufferIdx) runs on EPTF_Var_CT { |
| |
| pl_compBufferIdx := -1; |
| pl_refreshRateId := -1; |
| |
| for(var integer r := 0; r<sizeof(v_syncBuffer); r:=r+1) { |
| if (v_syncBuffer[r].refreshRate == pl_refreshRate) { |
| pl_refreshRateId := r; |
| break; |
| } |
| } |
| if (pl_refreshRateId==-1) { |
| return; |
| } |
| if (pl_remoteCompRef==null) { |
| return; // do not search for compBufferIdx |
| } |
| for(var integer i:=0; i<sizeof(v_syncBuffer[pl_refreshRateId].syncBuffer); i:=i+1) { |
| if (v_syncBuffer[pl_refreshRateId].syncBuffer[i].remoteCompRef == pl_remoteCompRef) { |
| pl_compBufferIdx := i; |
| return; |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_registerConnection |
| // |
| // Purpose: |
| // Adds a new connection to the syncBuffer for a given refreshRate |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_registerConnection(in EPTF_Var_CT pl_remoteCompRef, in integer pl_refreshRate, out integer pl_refreshRateId, out integer pl_compBufferIdx) runs on EPTF_Var_CT { |
| pl_refreshRateId := -1; |
| for(var integer r := 0; r<sizeof(v_syncBuffer); r:=r+1) { |
| if (v_syncBuffer[r].refreshRate == pl_refreshRate) { |
| pl_refreshRateId := r; |
| break; |
| } |
| } |
| if (pl_refreshRateId==-1) { |
| pl_refreshRateId := sizeof(v_syncBuffer); |
| v_syncBuffer[pl_refreshRateId].refreshRate := pl_refreshRate; |
| v_syncBuffer[pl_refreshRateId].eventIdx := -1; // invalid index |
| v_syncBuffer[pl_refreshRateId].syncBuffer := {}; |
| } |
| |
| pl_compBufferIdx := sizeof(v_syncBuffer[pl_refreshRateId].syncBuffer); |
| v_syncBuffer[pl_refreshRateId].syncBuffer[pl_compBufferIdx]:= { |
| remoteCompRef := pl_remoteCompRef, |
| flushCounter := 0, |
| compBufferData := {} |
| } |
| v_EPTF_Var_Connections[f_EPTF_Base_upcast(pl_remoteCompRef)] := connected; |
| } |
| |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_removeConnection |
| // |
| // Purpose: |
| // The variable is only removed from the syncBuffer if the subscription is buffered, |
| // but the sync buffer for that component is not removed. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_removeConnection(in integer pl_idx, in EPTF_Var_Ref pl_remoteProviderRef) runs on EPTF_Var_CT { |
| // nothing to do |
| //If you implement it, take care of |
| //f_EPTF_Var_checkConnection and f_EPTF_Var_registerConnection functions. |
| //Continuity must be checked there |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_deregisterConnection |
| // |
| // Purpose: |
| // Removed a connection from the syncBuffer |
| // |
| // Returns: |
| // *boolean* - true if there are still alive connections, false if all connections are closed |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_deregisterConnection(in EPTF_Var_CT pl_remoteCompRef) runs on EPTF_Var_CT return boolean { |
| var boolean vl_result := false; |
| for(var integer vl_refreshRateId := 0; vl_refreshRateId<sizeof(v_syncBuffer); vl_refreshRateId := vl_refreshRateId+1) { |
| for(var integer i:=0; i<sizeof(v_syncBuffer[vl_refreshRateId].syncBuffer); i:=i+1) { |
| // remove connection from database: |
| if (v_syncBuffer[vl_refreshRateId].syncBuffer[i].remoteCompRef == pl_remoteCompRef) { |
| v_syncBuffer[vl_refreshRateId].syncBuffer[i] := { |
| remoteCompRef := null, |
| flushCounter := 0, |
| compBufferData := {} |
| } |
| } else if (vl_result==false and v_syncBuffer[vl_refreshRateId].syncBuffer[i].remoteCompRef != null ) { |
| vl_result := true; // other connections still exist |
| } |
| } |
| } |
| v_EPTF_Var_Connections[f_EPTF_Base_upcast(pl_remoteCompRef)] := terminated; |
| return vl_result; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_getConnectionState |
| // |
| // Purpose: |
| // Returns the connection state towards the given remote component |
| // |
| // Returns: |
| // <EPTF_Var_ConnectionState> - state of the connection towards the remote component |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_getConnectionState(in EPTF_Var_CT pl_remoteCompRef) runs on EPTF_Var_CT return EPTF_Var_ConnectionState { |
| if (not isbound(v_EPTF_Var_Connections[f_EPTF_Base_upcast(pl_remoteCompRef)])) { |
| return idle; |
| } |
| return v_EPTF_Var_Connections[f_EPTF_Base_upcast(pl_remoteCompRef)]; |
| } |
| |
| // SEND FUNCTION |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_send |
| // |
| // Purpose: |
| // Send a message on the Variable interface |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_send(in EPTF_Var_MgmtMsg pl_EPTF_Var_MgmtMsg, in EPTF_Var_CT pl_remoteCompRef) runs on EPTF_Var_CT { |
| if (not f_EPTF_Var_isConnected(pl_remoteCompRef)) { |
| return; // no connection towards remote component |
| } |
| |
| if (ischosen(pl_EPTF_Var_MgmtMsg.subscribe)) { |
| //action("*** Msg added to buffer"); |
| var integer vl_bufferSize := sizeof(v_EPTF_Var_Msg_Buffer); |
| if (vl_bufferSize==0) { |
| t_EPTF_Var_Msg_Buffer_timer.start; |
| } |
| v_EPTF_Var_Msg_Buffer[vl_bufferSize] := { pl_EPTF_Var_MgmtMsg, pl_remoteCompRef }; |
| } else { |
| EPTF_Var_MgmtIf.send(pl_EPTF_Var_MgmtMsg) to pl_remoteCompRef; |
| } |
| } |
| |
| private function f_EPTF_Var_calculateNofMsgsToSend() runs on EPTF_Var_CT return integer { |
| |
| var integer vl_buffSize := sizeof(v_EPTF_Var_Msg_Buffer); |
| var integer vl_nofMsgsToSend := v_EPTF_Var_Msg_BufferBurstSize; |
| |
| if (vl_buffSize<vl_nofMsgsToSend + v_EPTF_Var_Msg_BufferStartIdx) { |
| vl_nofMsgsToSend := vl_buffSize - v_EPTF_Var_Msg_BufferStartIdx; |
| } //else { |
| //action("*** BUFFER SIZE: ", sizeof(v_EPTF_Var_Msg_Buffer)); |
| //action("*** msgs to send: ", vl_nofMsgsToSend-v_EPTF_Var_Msg_BufferStartIdx); |
| //action("*** msgs remain: ", vl_buffSize-vl_nofMsgsToSend); |
| //action("*** Time delay : ", f_EPTF_Base_getRelTimeInSecs() - v_EPTF_Var_startTime); |
| //action("*** buffer content: ", v_EPTF_Var_Msg_Buffer); |
| //} |
| |
| // if pending messages would exceed limit, send less messages: |
| if (v_EPTF_Var_maxNofPendingMsgs<v_EPTF_Var_nofPendingMsgs+vl_nofMsgsToSend) { |
| vl_nofMsgsToSend := v_EPTF_Var_maxNofPendingMsgs-v_EPTF_Var_nofPendingMsgs; |
| //action("*** maxNofPendingMsgs reached!: ", v_EPTF_Var_nofPendingMsgs, " msgs to send: ", vl_nofMsgsToSend); |
| } |
| //action("*** vl_nofMsgsToSend:", vl_nofMsgsToSend); |
| return vl_nofMsgsToSend; |
| } |
| |
| private altstep as_EPTF_Var_Msg_Buffer_Handler() runs on EPTF_Var_CT { |
| [sizeof(v_EPTF_Var_Msg_Buffer) != 0 and f_EPTF_Var_calculateNofMsgsToSend()>0] t_EPTF_Var_Msg_Buffer_timer.timeout { |
| // TODO: send buffer with clustering |
| |
| |
| var integer vl_buffSize := sizeof(v_EPTF_Var_Msg_Buffer); |
| var integer vl_lastIdx := v_EPTF_Var_Msg_BufferStartIdx + f_EPTF_Var_calculateNofMsgsToSend(); |
| |
| for(var integer i:=v_EPTF_Var_Msg_BufferStartIdx; i<vl_lastIdx; i:=i+1) { |
| if (f_EPTF_Var_isConnected(v_EPTF_Var_Msg_Buffer[i].destinationCompRef)) { |
| EPTF_Var_MgmtIf.send(v_EPTF_Var_Msg_Buffer[i].msg) to v_EPTF_Var_Msg_Buffer[i].destinationCompRef; |
| } |
| } |
| |
| //action("***sent messages: ", vl_lastIdx-v_EPTF_Var_Msg_BufferStartIdx, " remained in buffer: ", vl_buffSize-vl_lastIdx); |
| |
| //increase number of pending getData counter with the number of messages sent: |
| v_EPTF_Var_nofPendingMsgs := v_EPTF_Var_nofPendingMsgs + vl_lastIdx - v_EPTF_Var_Msg_BufferStartIdx; |
| |
| v_EPTF_Var_Msg_BufferStartIdx := vl_lastIdx; |
| if (v_EPTF_Var_Msg_BufferStartIdx==vl_buffSize) { |
| v_EPTF_Var_Msg_BufferStartIdx := 0; |
| v_EPTF_Var_Msg_Buffer := {}; |
| } else { |
| // there are still messages left in the buffer |
| t_EPTF_Var_Msg_Buffer_timer.start(0.001); |
| //action("**** msgs remain: ", vl_buffSize-v_EPTF_Var_Msg_BufferStartIdx); |
| } |
| repeat; |
| } |
| } |
| |
| // RECEIVING MESSAGES |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_IsPresentRemote |
| // |
| // Purpose: |
| // Handler for IsPresentRemoteResp message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_IsPresentRemote(in EPTF_Var_Msg_IsPresentRemote pl_isPresentRemote, in EPTF_Var_CT pl_remoteCompRef) runs on EPTF_Var_CT { |
| var EPTF_Var_Msg_IsPresentRemoteResp vl_isPresentRemoteResp := { |
| remoteVarName := pl_isPresentRemote.remoteVarName, |
| blockingFlagIdx := pl_isPresentRemote.blockingFlagIdx, |
| responseIdx := pl_isPresentRemote.responseIdx, |
| isPresent := (-1 != f_EPTF_Var_getId(pl_isPresentRemote.remoteVarName)) |
| }; |
| f_EPTF_Var_addConnection(pl_remoteCompRef); |
| f_EPTF_Var_send({isPresentRemoteResp:=vl_isPresentRemoteResp},pl_remoteCompRef); |
| return; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_IsPresentRemoteResp |
| // |
| // Purpose: |
| // Handler for IsPresentRemoteResp message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_IsPresentRemoteResp(in EPTF_Var_Msg_IsPresentRemoteResp pl_isPresentRemoteResp) runs on EPTF_Var_CT { |
| // set the responseValue to the boolean pool: |
| if (pl_isPresentRemoteResp.responseIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_isPresentRemoteResp.responseIdx,pl_isPresentRemoteResp.isPresent); |
| } |
| |
| // disable blocking if it was requested: |
| if (pl_isPresentRemoteResp.blockingFlagIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_isPresentRemoteResp.blockingFlagIdx,true); |
| } |
| return; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_SubscribeResp |
| // |
| // Purpose: |
| // Handler for SubscribeResp message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_SubscribeResp(in EPTF_Var_Msg_SubscribeResp pl_subscribeResp, in EPTF_Var_CT pl_sender) runs on EPTF_Var_CT { |
| if (pl_subscribeResp.content == omit) { |
| f_EPTF_Var_error(log2str("Variable ",pl_subscribeResp.subscriberVarName, " on component ",pl_subscribeResp.provider.compRef," does not exist. Subscribe failed by the subscriber: ", pl_subscribeResp.subscriber)); |
| //f_EPTF_Base_stop(); |
| } |
| var integer vl_myIdx := pl_subscribeResp.subscriber.idx; |
| |
| // change subscription mode to pull if provider is a pull mode subscriber: |
| if (ispresent(pl_subscribeResp.content) and ischosen(pl_subscribeResp.content.unknownVal)) { |
| v_EPTF_Vars[vl_myIdx].provider.remote.subscriptionMode := pull; |
| } |
| |
| if (ischosen(v_EPTF_Vars[vl_myIdx].content.invalid) and not f_EPTF_Var_checkSubscriptionMode(vl_myIdx,pull)) { |
| v_EPTF_Vars[vl_myIdx].content := { direct := pl_subscribeResp.content }; |
| } |
| |
| // get response handler |
| var EPTF_Var_resubscribeRemoteResp_handler vl_respHandler := cg_EPTF_Var_resubscribeRemoteResp_handler_null; |
| if(isbound(v_EPTF_Var_resubscribeRemoteResp_handler_DB[vl_myIdx]) and v_EPTF_Var_resubscribeRemoteResp_handler_DB[vl_myIdx].handlerFn != null){ |
| vl_respHandler := v_EPTF_Var_resubscribeRemoteResp_handler_DB[vl_myIdx]; |
| v_EPTF_Var_resubscribeRemoteResp_handler_DB[vl_myIdx] := cg_EPTF_Var_resubscribeRemoteResp_handler_null; |
| } |
| |
| if(ischosen(v_EPTF_Vars[vl_myIdx].provider.empty)) { |
| f_EPTF_Var_warning(log2str(%definitionId, ": Subscribe resp is ignored for variable ", v_EPTF_Vars[vl_myIdx].name, " : remote component exited.")); |
| // disable blocking if it was requested: |
| if (pl_subscribeResp.blockingFlagIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_subscribeResp.blockingFlagIdx,true); |
| } |
| if(vl_respHandler.handlerFn != null) { |
| vl_respHandler.handlerFn.apply(vl_myIdx,false,vl_respHandler.argList); // resubscribe is unsuccessful |
| } |
| return; |
| } |
| |
| var boolean vl_bufferedAdjust := v_EPTF_Vars[vl_myIdx].provider.remote.varRef.idx == -2; |
| var EPTF_Var_DirectContent vl_bufferedContent; |
| if (vl_bufferedAdjust) { |
| f_EPTF_Var_getContent(vl_myIdx,vl_bufferedContent); |
| } |
| |
| v_EPTF_Vars[vl_myIdx].provider.remote.topProviderType := pl_subscribeResp.topProviderType; |
| v_EPTF_Vars[vl_myIdx].provider.remote.varRef.idx := pl_subscribeResp.provider.idx; |
| v_EPTF_Vars[vl_myIdx].provider.remote.varRef.compRef := pl_subscribeResp.provider.compRef; |
| |
| // update the timeLine of the subscriber if subscription mode is sampled, sampledAtSync or timeLine: |
| if ( |
| f_EPTF_Var_checkSubscriptionMode(vl_myIdx,timeLine) |
| or f_EPTF_Var_checkSubscriptionMode(vl_myIdx,sampled) or f_EPTF_Var_checkSubscriptionMode(vl_myIdx,sampledAtSync)) { |
| // add the timeLine from subscribeResp to the variable: |
| f_EPTF_Var_handle_RefreshTimeLines({ |
| refreshRate := v_EPTF_Vars[vl_myIdx].provider.remote.refreshRate, |
| flushCounter := 1, |
| timeLineList := { |
| { |
| idx := vl_myIdx, |
| timeLine := { |
| size := 1, |
| timeLineData := { { |
| timestamp := pl_subscribeResp.timestamp, |
| content := pl_subscribeResp.content |
| } } |
| } |
| } |
| } |
| }); |
| } |
| |
| if (v_EPTF_Vars[vl_myIdx].name == "") { |
| var charstring vl_autoName := pl_subscribeResp.subscriberVarName; |
| var integer vl_idx; |
| if (f_EPTF_Var_checkName(vl_autoName,vl_idx)) { |
| v_EPTF_Vars[vl_myIdx].name := vl_autoName; |
| // register the variable name into the hashmap: |
| if (v_EPTF_Var_enableName2Id) { |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_Var_Hashmap_Name2Id,vl_autoName,vl_myIdx); |
| } |
| } else { |
| f_EPTF_Var_error(log2str("Auto-generated name ",vl_autoName," for subscriber EPTF_Var[",vl_myIdx,"] is not unique. Already defined by EPTF_Var[",vl_idx,"]: ", v_EPTF_Vars[vl_idx])); |
| //f_EPTF_Base_stop(); |
| } |
| } |
| if (v_EPTF_Vars[vl_myIdx].subsCanAdjust != pl_subscribeResp.subsCanAdjust) { |
| v_EPTF_Vars[vl_myIdx].subsCanAdjust := pl_subscribeResp.subsCanAdjust; |
| f_EPTF_Var_callSubsCanAdjustNotifyFns(vl_myIdx); |
| f_EPTF_Var_setSubsCanAdjustInAllSubscribers(vl_myIdx); |
| } |
| |
| // call response handler |
| if(vl_respHandler.handlerFn != null) { |
| vl_respHandler.handlerFn.apply(vl_myIdx,true,vl_respHandler.argList); // resubscribe is successful |
| } |
| |
| // disable blocking if it was requested: |
| if (pl_subscribeResp.blockingFlagIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_subscribeResp.blockingFlagIdx,true); |
| } |
| |
| // do not refresh for pull mode subscription: |
| if (not f_EPTF_Var_checkSubscriptionMode(vl_myIdx,pull)) { |
| f_EPTF_Var_registerRefresh(vl_myIdx,pl_subscribeResp.content); |
| } |
| if (vl_bufferedAdjust) { |
| f_EPTF_Var_adjustContent(vl_myIdx,vl_bufferedContent); |
| } |
| |
| return; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_GetRemoteContentResp |
| // |
| // Purpose: |
| // Handler for GetRemoteContentResp message. Returns false if content is invalid |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_GetRemoteContentResp(in EPTF_Var_Msg_GetRemoteContentResp pl_getRemoteContentResp) runs on EPTF_Var_CT { |
| if (pl_getRemoteContentResp.content == omit) { |
| if (pl_getRemoteContentResp.responseIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_getRemoteContentResp.responseIdx,false); |
| } |
| } else { |
| if (pl_getRemoteContentResp.responseIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_getRemoteContentResp.responseIdx,true); |
| v_EPTF_Var_getRemoteContentResultList[pl_getRemoteContentResp.responseIdx] := {{null,-1},pl_getRemoteContentResp.content,pl_getRemoteContentResp.subsCanAdjust} |
| if (ispresent(pl_getRemoteContentResp.provider)) { |
| v_EPTF_Var_getRemoteContentResultList[pl_getRemoteContentResp.responseIdx].provider := pl_getRemoteContentResp.provider; |
| } |
| } |
| } |
| // disable blocking if it was requested: |
| if (pl_getRemoteContentResp.blockingFlagIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_getRemoteContentResp.blockingFlagIdx,true); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_AdjustRemoteContentResp |
| // |
| // Purpose: |
| // Handler for AdjustRemoteContentResp message. Returns false if content is invalid |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_AdjustRemoteContentResp(in EPTF_Var_Msg_AdjustRemoteContentResp pl_adjustRemoteContentResp) runs on EPTF_Var_CT { |
| // call user handler: |
| if (pl_adjustRemoteContentResp.adjust.respHandlerId != -1) { |
| // find handler data in the stack: |
| var EPTF_Var_adjustContentResp_handler vl_respHandler; |
| if (f_EPTF_getEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_adjustRemoteContentResp.adjust.respHandlerId,vl_respHandler)) { |
| // call the user handler (cannot be null: for null the respHandlerId was set to -1): |
| var integer vl_myIdx := -1; // invalid |
| vl_respHandler.handlerFn.apply(vl_myIdx, pl_adjustRemoteContentResp.adjust.content, pl_adjustRemoteContentResp.result, vl_respHandler.argList); |
| // release the stack: |
| f_EPTF_deleteEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_adjustRemoteContentResp.adjust.respHandlerId); |
| } else { |
| // this is never called (just to remove the warning): |
| f_EPTF_Var_error("Callback function for AdjustRemoteContentResp handler not found. Database error!"); |
| //f_EPTF_Base_stop(); |
| } |
| } |
| // set the responseValue to the boolean pool: |
| if (pl_adjustRemoteContentResp.adjust.responseIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_adjustRemoteContentResp.adjust.responseIdx,pl_adjustRemoteContentResp.result); |
| } |
| |
| // disable blocking if it was requested: |
| if (pl_adjustRemoteContentResp.adjust.blockingFlagIdx != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,pl_adjustRemoteContentResp.adjust.blockingFlagIdx,true); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: as_EPTF_Var_handle_ByeAck |
| // |
| // Purpose: |
| // Handler for ByeAck message |
| /////////////////////////////////////////////////////////// |
| private altstep as_EPTF_Var_handle_ByeAck(timer t_wait) runs on EPTF_Var_CT { |
| var EPTF_Var_MgmtMsg vl_EPTF_Var_MgmtIf_msg; |
| var EPTF_Var_CT vl_EPTF_Var_MgmtIf_msg_sender; |
| [] EPTF_Var_MgmtIf.receive({byeAck:=?}) -> value vl_EPTF_Var_MgmtIf_msg sender vl_EPTF_Var_MgmtIf_msg_sender { |
| if (f_EPTF_Var_handle_ByeAck(vl_EPTF_Var_MgmtIf_msg_sender)) { |
| t_wait.stop; t_wait.start; |
| repeat; |
| } |
| } |
| [] t_wait.timeout { |
| f_EPTF_Var_warning("--VAR CLEANUP TIMEOUT-- Not all responses received for bye messages."); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: as_EPTF_Var_handle_Bye |
| // |
| // Purpose: |
| // Handler for Bye message |
| /////////////////////////////////////////////////////////// |
| private altstep as_EPTF_Var_handle_Bye() runs on EPTF_Var_CT { |
| var EPTF_Var_MgmtMsg vl_EPTF_Var_MgmtIf_msg; |
| var EPTF_Var_CT vl_EPTF_Var_MgmtIf_msg_sender; |
| [] EPTF_Var_MgmtIf.receive({bye:=?}) -> value vl_EPTF_Var_MgmtIf_msg sender vl_EPTF_Var_MgmtIf_msg_sender { |
| f_EPTF_Var_handle_Bye(vl_EPTF_Var_MgmtIf_msg_sender); |
| repeat; |
| } |
| } |
| |
| // REFRESH CONTENT |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_registerRefresh |
| // |
| // Purpose: |
| // Requests the library to register the content refresh of the EPTF_Var. |
| // (the content of the variable can be updated before calling this function) |
| // Also notifies all of its subscribers about the new value and calls postProcFns |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_registerRefresh(in integer pl_idx, in EPTF_Var_DirectContent pl_contentNew, in float pl_timeStamp := -1.0) runs on EPTF_Var_CT { |
| // set the new content into the current: |
| f_EPTF_Var_setContent(pl_idx,pl_contentNew); |
| |
| // updates the timeLine with the new value |
| f_EPTF_Var_updateTimeLine(pl_idx,pl_contentNew,pl_timeStamp); |
| |
| // call postProc functions: |
| f_EPTF_Var_callPostProcFns(pl_idx); |
| // update new value after postproc |
| f_EPTF_Var_content2direct(v_EPTF_Vars[pl_idx].content,pl_contentNew); |
| // notify subscribers: |
| f_EPTF_Var_notifyAllSubscribers(pl_idx,pl_contentNew); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_notifyAllSubscribers |
| // |
| // Purpose: |
| // Notifies all subscribers of the EPTF_Var pl_idx with the new content |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_notifyAllSubscribers(in integer pl_idx, in EPTF_Var_DirectContent pl_contentNew) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].subscribers); i:=i+1) { |
| f_EPTF_Var_notifySubscriber(v_EPTF_Vars[pl_idx].subscribers[i],pl_contentNew); |
| } |
| |
| if (v_EPTF_Var_refreshSubscribersPeriod<0.0) { |
| // instant update: |
| var float vl_timeStamp := f_EPTF_Base_getAbsTimeInSecs(f_EPTF_SchedulerComp_snapshotTime()); |
| for(var integer vl_idx:=f_EPTF_Var_getVarToUpdate(); vl_idx!=-1; vl_idx := f_EPTF_Var_getVarToUpdate()) { |
| // list is not empty, there are more vars to update |
| // refresh selected variable: |
| //f_EPTF_Var_refreshContent(vl_idx); |
| var EPTF_Var_DirectContent vl_contentNew; |
| f_EPTF_Var_callCalcFn(vl_idx,vl_contentNew); |
| f_EPTF_Var_registerRefresh(vl_idx,vl_contentNew,vl_timeStamp); |
| } |
| } |
| } |
| |
| // sets the refresh period for subscribers (local subscribers) |
| private function f_EPTF_Var_setRefreshSubscribersPeriod(in float pl_refreshSubscribersPeriod := tsp_EPTF_Var_refreshSubscribersPeriod) runs on EPTF_Var_CT { |
| v_EPTF_Var_refreshSubscribersPeriod := pl_refreshSubscribersPeriod; |
| if (v_EPTF_Var_refreshSubscribersPeriod>=0.0) { |
| t_EPTF_Var_refreshSubscribers.start(v_EPTF_Var_refreshSubscribersPeriod); |
| } else { |
| t_EPTF_Var_refreshSubscribers.stop; |
| } |
| } |
| |
| // handler of the refreshSubscribers timer |
| // updates all variables in the v_EPTF_Var_varsToUpdate database in order |
| private altstep as_EPTF_Var_refreshSubscribers() runs on EPTF_Var_CT { |
| [v_EPTF_Var_refreshSubscribersPeriod>=0.0 and sizeof(v_EPTF_Var_varsToUpdate)>1] t_EPTF_Var_refreshSubscribers.timeout { |
| t_EPTF_Var_refreshSubscribers.start(v_EPTF_Var_refreshSubscribersPeriod); |
| // select the first var in the list and update its content: |
| var float vl_timeStamp := f_EPTF_Base_getAbsTimeInSecs(f_EPTF_SchedulerComp_snapshotTime()); |
| for(var integer vl_idx:=f_EPTF_Var_getVarToUpdate(); |
| vl_idx!=-1; |
| vl_idx := f_EPTF_Var_getVarToUpdate()) { |
| // list is not empty, there are more vars to update |
| // refresh selected variable: |
| //f_EPTF_Var_refreshContent(vl_idx); |
| var EPTF_Var_DirectContent vl_contentNew; |
| f_EPTF_Var_callCalcFn(vl_idx,vl_contentNew); |
| f_EPTF_Var_registerRefresh(vl_idx,vl_contentNew,vl_timeStamp); |
| } |
| repeat; |
| } |
| } |
| |
| // inserts a new element into v_EPTF_Var_varsToUpdate |
| private function f_EPTF_Var_addVarToUpdate(in integer pl_idx) runs on EPTF_Var_CT { |
| // if the list was empty: |
| if (sizeof(v_EPTF_Var_varsToUpdate)<=1) { |
| // add the first element to the list, 0-th item is the headIdx |
| v_EPTF_Var_varsToUpdate := {1,pl_idx}; |
| return; |
| } |
| var integer vl_headIdx := v_EPTF_Var_varsToUpdate[0]; |
| for(var integer i:=sizeof(v_EPTF_Var_varsToUpdate)-1; i>0;i:=i-1) { |
| if (v_EPTF_Var_varsToUpdate[i]==pl_idx and vl_headIdx<=i) { |
| return; // already in the list |
| } |
| } |
| var integer vl_currentPos := sizeof(v_EPTF_Var_varsToUpdate); |
| for(var integer i:=sizeof(v_EPTF_Var_varsToUpdate)-1; i>0;i:=i-1) { |
| if (v_EPTF_Var_varsToUpdate[i]>pl_idx and vl_headIdx<=i) { |
| // move old item one position back: |
| v_EPTF_Var_varsToUpdate[vl_currentPos] := v_EPTF_Var_varsToUpdate[i]; |
| vl_currentPos := i; |
| } else { |
| // position found, insert new element there: |
| v_EPTF_Var_varsToUpdate[vl_currentPos] := pl_idx; |
| return; |
| } |
| } |
| // position found, insert new element to the first place: |
| v_EPTF_Var_varsToUpdate[vl_currentPos] := pl_idx; |
| } |
| |
| // removes the head element from v_EPTF_Var_varsToUpdate, returns its value |
| private function f_EPTF_Var_getVarToUpdate() runs on EPTF_Var_CT return integer { |
| if (sizeof(v_EPTF_Var_varsToUpdate)==0) { |
| // if empty: |
| v_EPTF_Var_varsToUpdate := {0}; // empty |
| return -1; |
| } |
| if (v_EPTF_Var_varsToUpdate[0]==0) { |
| // empty: |
| return -1; |
| } |
| var integer vl_headIdx := v_EPTF_Var_varsToUpdate[0]; |
| v_EPTF_Var_varsToUpdate[0] := vl_headIdx+1; |
| var integer vl_idx := v_EPTF_Var_varsToUpdate[vl_headIdx]; |
| // reset the structure automatically if last element is removed: |
| if (v_EPTF_Var_varsToUpdate[0]==sizeof(v_EPTF_Var_varsToUpdate)) { |
| v_EPTF_Var_varsToUpdate := {}; |
| } |
| return vl_idx; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_notifySubscriber |
| // |
| // Purpose: |
| // Notifies the pl_subscriberIdx-th subscriber of pl_idx about the new value of the content. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_notifySubscriber(in EPTF_Var_Subscriber pl_subscriber, in EPTF_Var_DirectContent pl_contentNew) runs on EPTF_Var_CT { |
| if(ischosen(pl_subscriber.local)) { |
| // subscriber is local |
| var integer vl_idx := pl_subscriber.local; |
| |
| f_EPTF_Var_addVarToUpdate(vl_idx); |
| return; |
| } |
| if(ischosen(pl_subscriber.remote)) { |
| // if buffered: do not notify |
| if (pl_subscriber.remote.subscriptionMode == sampled or pl_subscriber.remote.subscriptionMode == sampledAtSync or pl_subscriber.remote.subscriptionMode == timeLine) { |
| return; // nothing to do |
| } |
| f_EPTF_Var_send( |
| {refreshContent:={ |
| pl_subscriber.remote.varRef,pl_contentNew}}, |
| pl_subscriber.remote.varRef.compRef); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_checkRemoteSubscriber |
| // |
| // Purpose: |
| // Checks if the given remote variable is really a subscriber (needed by the handleAdjustContentNack function) |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_checkRemoteSubscriber(in integer pl_idx, in EPTF_Var_Ref pl_subscriberVar) runs on EPTF_Var_CT return boolean { |
| for (var integer i:=0; i<sizeof(v_EPTF_Vars[pl_idx].subscribers); i:=i+1) { |
| if (ischosen(v_EPTF_Vars[pl_idx].subscribers[i].remote)) { |
| if (v_EPTF_Vars[pl_idx].subscribers[i].remote.varRef==pl_subscriberVar) { |
| return true; |
| } |
| } |
| } |
| return false; |
| } |
| |
| // TIMELINE |
| |
| // SYNC BUFFER TIMER |
| |
| function f_EPTF_Var_syncTimeoutHandler( |
| in EPTF_ScheduledAction pl_action, in integer pl_eventIndex |
| ) runs on EPTF_Var_CT return boolean { |
| var integer vl_refreshRateId := pl_action.actionId[0]; |
| var float vl_syncInterval := v_syncInterval; |
| if (vl_refreshRateId>0) { |
| vl_syncInterval := int2float(v_syncBuffer[vl_refreshRateId].refreshRate)*v_minSyncInterval |
| } |
| f_EPTF_Var_handle_syncTimeout(vl_refreshRateId); |
| //action("Event rescheduled for vl_refreshRate: ", v_syncBuffer[vl_refreshRateId].refreshRate, " with period: ",vl_syncInterval); |
| //action("v_EPTF_Vars: ", v_EPTF_Vars); |
| if (f_EPTF_SchedulerComp_scheduleAction( |
| pl_when := pl_action.when+vl_syncInterval, |
| pl_actionHandler := pl_action.actionHandler, |
| pl_action := {vl_refreshRateId}, |
| pl_eventIndex := v_syncBuffer[vl_refreshRateId].eventIdx |
| )){/*remove the warning*/}; |
| return true; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_syncTimeout |
| // |
| // Purpose: |
| // Handler for sync timer |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_syncTimeout(in integer pl_refreshRateId := 0) runs on EPTF_Var_CT { |
| // call the syncCallback functions: |
| f_EPTF_Var_callSyncCallBackFns(c_EPTF_Var_syncBegin,pl_refreshRateId); |
| |
| // send timeLines |
| var EPTF_Var_TimeLineList vl_refreshTimeLineList; |
| var float vl_timestamp := f_EPTF_Base_getAbsTimeInSecs(f_EPTF_SchedulerComp_snapshotTime()); |
| for(var integer i:=0; i<sizeof(v_syncBuffer[pl_refreshRateId].syncBuffer); i:=i+1) { |
| if (v_syncBuffer[pl_refreshRateId].syncBuffer[i].remoteCompRef!=null) { |
| vl_refreshTimeLineList := {}; |
| for(var integer j:=0; j<sizeof(v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData); j:=j+1) { |
| var integer vl_varIdx := v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].localIdx; |
| if (ischosen(v_EPTF_Vars[vl_varIdx].provider.remote) |
| and v_EPTF_Vars[vl_varIdx].provider.remote.refreshRate == v_syncBuffer[pl_refreshRateId].refreshRate |
| and( (v_EPTF_Vars[vl_varIdx].provider.remote.subscriptionMode == sampled) or |
| (v_EPTF_Vars[vl_varIdx].provider.remote.subscriptionMode == sampledAtSync) or |
| (v_EPTF_Vars[vl_varIdx].provider.remote.subscriptionMode == timeLine) )) { |
| // if I am a buffered subscriber: timeLine is not sent for the provider's refreshRate! |
| // it was forwarded when the timeLine was received from the provider, |
| // since then it did not change |
| } else { |
| // find timeLine for the refreshRate: |
| var integer vl_refreshRateIdInTimeLineBuffer := -1; |
| for (var integer ii := 0; ii<sizeof(v_EPTF_Vars[vl_varIdx].timeLineBuffer); ii:=ii+1) { |
| if (v_EPTF_Vars[vl_varIdx].timeLineBuffer[ii].refreshRateId == pl_refreshRateId) { |
| vl_refreshRateIdInTimeLineBuffer := ii; |
| break; |
| } |
| } |
| if(vl_refreshRateIdInTimeLineBuffer!=-1) { |
| // there is timeline for this variable with this refreshRate |
| // only add to message if timeLine is not empty: |
| if (v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size>0) { |
| // if subscription mode of the variable is timeLine |
| if (v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].subscriptionMode == timeLine) { |
| vl_refreshTimeLineList[sizeof(vl_refreshTimeLineList)] := { |
| v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].remoteIdx, |
| v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine |
| } |
| } else if (v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].subscriptionMode == sampled) { |
| // sampled: send only the last element in the timeLine: |
| vl_refreshTimeLineList[sizeof(vl_refreshTimeLineList)] := { |
| v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].remoteIdx, |
| {1,{v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.timeLineData[v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size-1]}} |
| } |
| } |
| } |
| } |
| if (v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].subscriptionMode == sampledAtSync) { |
| // sampledAtSync: calcFn and prostProc-s are called for the variable and send only the current content: |
| var EPTF_Var_DirectContent vl_currentContent; |
| // f_EPTF_Var_refreshContent(vl_varIdx); |
| // f_EPTF_Var_getContent(vl_varIdx, vl_currentContent); |
| |
| if (f_EPTF_Var_checkSubscriptionMode(vl_varIdx,pull)) { |
| f_EPTF_Var_getContent(vl_varIdx, vl_currentContent); |
| } else { |
| // store current content: |
| var EPTF_Var_DirectContent vl_prevContent; |
| f_EPTF_Var_content2direct(v_EPTF_Vars[vl_varIdx].content,vl_prevContent);//f_EPTF_Var_getContent(vl_varIdx, vl_prevContent); |
| // call calcFn: |
| f_EPTF_Var_callCalcFn(vl_varIdx,vl_currentContent); |
| // update content for postProc functions: |
| f_EPTF_Var_setContent(vl_varIdx,vl_currentContent); |
| f_EPTF_Var_callPostProcFns(vl_varIdx); |
| // postProc may update the content, so reread current content: |
| f_EPTF_Var_content2direct(v_EPTF_Vars[vl_varIdx].content,vl_currentContent);//f_EPTF_Var_getContent(vl_varIdx, vl_currentContent); |
| // restore the original content: |
| f_EPTF_Var_setContent(vl_varIdx, vl_prevContent); |
| } |
| |
| // if (ischosen(v_EPTF_Vars[vl_varIdx].provider.local)) { |
| // f_EPTF_Var_callCalcFn(vl_varIdx,vl_currentContent); |
| // } else { |
| // f_EPTF_Var_getContent(vl_varIdx, vl_currentContent); |
| // } |
| if (v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].prevContent != vl_currentContent) { |
| vl_refreshTimeLineList[sizeof(vl_refreshTimeLineList)] := { |
| v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].remoteIdx, |
| {1,{{vl_timestamp,vl_currentContent}}} |
| } |
| // store current value for sampledAtSync |
| v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].prevContent := vl_currentContent; |
| } |
| } |
| } |
| } |
| // no 'if' needed: send empty message in case of no change |
| if (tsp_EPTF_Var_enableEmptyTimeLine or sizeof(vl_refreshTimeLineList)>0) { |
| f_EPTF_Var_send( |
| {refreshTimeLines := {v_syncBuffer[pl_refreshRateId].refreshRate, v_syncBuffer[pl_refreshRateId].syncBuffer[i].flushCounter, vl_refreshTimeLineList}}, |
| v_syncBuffer[pl_refreshRateId].syncBuffer[i].remoteCompRef |
| ); |
| // increase the counter: |
| v_syncBuffer[pl_refreshRateId].syncBuffer[i].flushCounter := v_syncBuffer[pl_refreshRateId].syncBuffer[i].flushCounter+1; |
| } |
| } |
| } |
| // reset timeLines: |
| for(var integer i:=0; i<sizeof(v_syncBuffer[pl_refreshRateId].syncBuffer); i:=i+1) { |
| if (v_syncBuffer[pl_refreshRateId].syncBuffer[i].remoteCompRef!=null) { |
| for(var integer j:=0; j<sizeof(v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData); j:=j+1) { |
| var integer vl_varIdx := v_syncBuffer[pl_refreshRateId].syncBuffer[i].compBufferData[j].localIdx; |
| if (ischosen(v_EPTF_Vars[vl_varIdx].provider.remote) |
| and v_EPTF_Vars[vl_varIdx].provider.remote.refreshRate == v_syncBuffer[pl_refreshRateId].refreshRate |
| and( (v_EPTF_Vars[vl_varIdx].provider.remote.subscriptionMode == sampled) or |
| (v_EPTF_Vars[vl_varIdx].provider.remote.subscriptionMode == sampledAtSync) or |
| (v_EPTF_Vars[vl_varIdx].provider.remote.subscriptionMode == timeLine) )) { |
| // if I am a buffered subscriber: timeLine is not reset! |
| } else { |
| // find timeLine for the refreshRate: |
| var integer vl_refreshRateIdInTimeLineBuffer := -1; |
| for (var integer ii := 0; ii<sizeof(v_EPTF_Vars[vl_varIdx].timeLineBuffer); ii:=ii+1) { |
| if (v_EPTF_Vars[vl_varIdx].timeLineBuffer[ii].refreshRateId == pl_refreshRateId) { |
| vl_refreshRateIdInTimeLineBuffer := ii; |
| break; |
| } |
| } |
| if(vl_refreshRateIdInTimeLineBuffer!=-1) { |
| // there is timeline for this variable with this refreshRate |
| // only reset timeLine if timeLine is not empty: |
| if (v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine.size>0) { |
| v_EPTF_Vars[vl_varIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine := {0,{}}; |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // call the syncCallback functions: |
| f_EPTF_Var_callSyncCallBackFns(c_EPTF_Var_syncEnd,pl_refreshRateId); |
| } |
| |
| //*************************************************************************************************** |
| // altsteps |
| //*************************************************************************************************** |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_lookupName |
| // |
| // Purpose: |
| // Returns the idx of the EPTF Variable with the given name |
| // returns -1 if not found |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_lookupName(in charstring pl_varName) runs on EPTF_Var_CT return integer { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars); i:=i+1) { |
| if (v_EPTF_Vars[i].name == pl_varName) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_lookupCompRef |
| // |
| // Purpose: |
| // Returns the idx of the EPTF Variable that refers to the given reference. |
| // -1 is retured if no variable found. |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_lookupCompRef(in EPTF_Var_ReferencedContent pl_compRef) runs on EPTF_Var_CT return integer { |
| //log("pl_compRef: ", pl_compRef); |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars); i:=i+1) { |
| //log("v_EPTF_Vars[i].content.reference: ",v_EPTF_Vars[i].content.reference); |
| if (ischosen(v_EPTF_Vars[i].content.reference) and |
| v_EPTF_Vars[i].content.reference == pl_compRef) { |
| return i; |
| } |
| } |
| return -1; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_Subscribe |
| // |
| // Purpose: |
| // Handles the received subscribe message |
| // is registers the new subscriber for the provider |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_Subscribe(in EPTF_Var_Msg_Subscribe pl_subscribe) runs on EPTF_Var_CT { |
| var EPTF_Var_Ref vl_subscriber := pl_subscribe.subscriber; |
| var charstring vl_providerVarName := pl_subscribe.providerVarName; |
| var EPTF_Var_SubscriptionMode vl_subscriptionMode := pl_subscribe.subscriptionMode; |
| var integer vl_refreshRate := pl_subscribe.refreshRate; |
| var integer vl_refreshRateId := -1; |
| var EPTF_Var_CT vl_remoteCompRef := vl_subscriber.compRef; |
| |
| var integer vl_compBufferIdx; |
| f_EPTF_Var_checkConnection(vl_remoteCompRef,vl_refreshRate,vl_refreshRateId,vl_compBufferIdx); |
| // newRefreshRate event is needed if vl_refreshRateId!=0 (not default), but not found in database (==-1) |
| var boolean vl_needNewRefreshRate := (vl_refreshRateId==-1 and vl_subscriptionMode != pull); |
| // if not connected: |
| if (vl_compBufferIdx==-1) { |
| f_EPTF_Var_registerConnection(vl_remoteCompRef,vl_refreshRate,vl_refreshRateId,vl_compBufferIdx); |
| } |
| if (vl_needNewRefreshRate) { |
| //action("Event scheduled for vl_refreshRate: ", vl_refreshRate, " with period: ",int2float(vl_refreshRate)*v_minSyncInterval); |
| if(f_EPTF_SchedulerComp_scheduleAction( |
| pl_when := f_EPTF_Base_getRelTimeInSecs()+int2float(vl_refreshRate)*v_minSyncInterval, |
| pl_actionHandler := refers(f_EPTF_Var_syncTimeoutHandler), |
| pl_action := {vl_refreshRateId}, |
| pl_eventIndex := v_syncBuffer[vl_refreshRateId].eventIdx |
| )) {/*remove the warning*/}; |
| } |
| |
| // generate auto-name: |
| var charstring vl_subscriberVarName := pl_subscribe.subscriberVarName; |
| if (vl_subscriberVarName == "") { |
| vl_subscriberVarName := f_EPTF_Base_selfName() & "." & vl_providerVarName; |
| } |
| |
| var integer vl_myIdx := f_EPTF_Var_getId(vl_providerVarName); |
| if (vl_myIdx<0) { |
| // send invalid resp |
| // send vl_providerVarName instead of vl_subscriberVarName: this is the name of the variable that is not found |
| vl_subscriberVarName := vl_providerVarName & " (subscribed name: " & vl_subscriberVarName & ")" |
| f_EPTF_Var_send({subscribeResp := {vl_subscriberVarName, vl_subscriber,{self,vl_myIdx}, 0.0, omit, empty, pl_subscribe.blockingFlagIdx, false}}, vl_remoteCompRef); |
| return; |
| } |
| |
| if (vl_subscriptionMode == sampled or vl_subscriptionMode == sampledAtSync or vl_subscriptionMode == timeLine) { |
| f_EPTF_Var_registerBufferedVar(vl_myIdx, vl_subscriber.idx, vl_subscriptionMode, vl_refreshRateId, vl_compBufferIdx); |
| } |
| |
| if (vl_subscriptionMode != pull) { |
| f_EPTF_Var_addRemoteSubscriber(vl_myIdx, {vl_subscriberVarName,vl_subscriber,vl_subscriptionMode, vl_refreshRateId}); |
| } |
| |
| var EPTF_TopProviderType vl_topProviderType; |
| f_EPTF_Var_getTopProviderType(vl_myIdx, vl_topProviderType); |
| var EPTF_Var_DirectContent vl_providerDirectContent := {unknownVal := {omit}}; // this is sent if subscription needs to be changed to pull mode |
| if (vl_subscriptionMode != pull and not (f_EPTF_Var_checkSubscriptionMode(vl_myIdx,pull) or f_EPTF_Var_checkLocalSubscriptionMode(vl_myIdx,pull))) { |
| // content is only sent if not pull mode subscription and I am not a pull mode subscriber and not pull mode local subscriber |
| f_EPTF_Var_content2direct(v_EPTF_Vars[vl_myIdx].content,vl_providerDirectContent); |
| //f_EPTF_Var_getContent(vl_myIdx, vl_providerDirectContent); |
| } |
| |
| var EPTF_Var_Ref vl_provider := {self,vl_myIdx}; |
| // if I am a pull subscriber, replace myself with my provider: |
| // TODO: replace myself always if I am a subscriber? |
| if (f_EPTF_Var_checkSubscriptionMode(vl_myIdx,pull)) { |
| vl_provider := v_EPTF_Vars[vl_myIdx].provider.remote.varRef; // replace myself with my provider |
| } |
| |
| f_EPTF_Var_send({subscribeResp := { |
| vl_subscriberVarName, |
| vl_subscriber, |
| vl_provider, |
| f_EPTF_Base_getAbsTimeInSecs(f_EPTF_SchedulerComp_snapshotTime()), |
| vl_providerDirectContent, |
| vl_topProviderType, |
| pl_subscribe.blockingFlagIdx, |
| v_EPTF_Vars[vl_myIdx].subsCanAdjust |
| }}, vl_remoteCompRef); |
| |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_registerBufferedVar |
| // |
| // Purpose: |
| // Adds the pl_idx variable to the compBuffer (if not already added) |
| // also initializes the timeLineBuffer of v_EPTF_Var[pl_idx] |
| // pl_remoteIdx is the index of the subscriber on the remote component, pl_subscriptionMode is the subscription mode |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_registerBufferedVar(in integer pl_idx, in integer pl_remoteIdx, in EPTF_Var_SubscriptionMode pl_subscriptionMode, in integer pl_refreshRateId, in integer pl_compBufferIdx) runs on EPTF_Var_CT { |
| var integer vl_syncBufferIdx; |
| if (f_EPTF_str2int_HashMap_Find(v_EPTF_Var_Hashmap_SyncBuffer,log2str(pl_idx,".",pl_remoteIdx,".",pl_refreshRateId,".",pl_compBufferIdx),vl_syncBufferIdx)) { |
| return; // already in the compBuffer |
| } |
| |
| |
| var integer vl_refreshRateId := pl_refreshRateId; |
| vl_syncBufferIdx := sizeof(v_syncBuffer[vl_refreshRateId].syncBuffer[pl_compBufferIdx].compBufferData); |
| v_syncBuffer[vl_refreshRateId].syncBuffer[pl_compBufferIdx].compBufferData[vl_syncBufferIdx] := { |
| localIdx := pl_idx, |
| remoteIdx := pl_remoteIdx, |
| subscriptionMode := pl_subscriptionMode, |
| prevContent := omit |
| } |
| f_EPTF_str2int_HashMap_Insert(v_EPTF_Var_Hashmap_SyncBuffer,log2str(pl_idx,".",pl_remoteIdx,".",pl_refreshRateId,".",pl_compBufferIdx),vl_syncBufferIdx); |
| |
| var integer vl_refreshRateIdInTimeLineBuffer := -1; |
| for (var integer i := 0; i<sizeof(v_EPTF_Vars[pl_idx].timeLineBuffer); i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].timeLineBuffer[i].refreshRateId == vl_refreshRateId) { |
| vl_refreshRateIdInTimeLineBuffer := i; |
| break; |
| } |
| } |
| if(vl_refreshRateIdInTimeLineBuffer==-1) { |
| vl_refreshRateIdInTimeLineBuffer := sizeof(v_EPTF_Vars[pl_idx].timeLineBuffer); |
| } |
| |
| if (sizeof(v_EPTF_Vars[pl_idx].timeLineBuffer) <= vl_refreshRateIdInTimeLineBuffer) { |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].refreshRateId := vl_refreshRateId; |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].bufferNum := 0; |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine := { |
| size := 0, |
| //It's always continuous. |
| timeLineData := {} |
| }; |
| } |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].bufferNum := v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].bufferNum + 1; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_deregisterBufferedVar |
| // |
| // Purpose: |
| // Removes the pl_idx variable from the compBuffer (if not already removed) |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_deregisterBufferedVar(in integer pl_idx, in integer pl_refreshRateId, in integer pl_compBufferIdx) runs on EPTF_Var_CT { |
| var integer vl_refreshRateId := pl_refreshRateId; |
| var integer vl_refreshRateIdInTimeLineBuffer := -1; |
| for (var integer i := 0; i<sizeof(v_EPTF_Vars[pl_idx].timeLineBuffer); i:=i+1) { |
| if (v_EPTF_Vars[pl_idx].timeLineBuffer[i].refreshRateId == vl_refreshRateId) { |
| vl_refreshRateIdInTimeLineBuffer := i; |
| break; |
| } |
| } |
| if(vl_refreshRateIdInTimeLineBuffer!=-1) { |
| // timeline exists for this refresh rate in this variable |
| v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].bufferNum := v_EPTF_Vars[pl_idx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].bufferNum - 1; |
| } |
| |
| var EPTF_Var_CompBufferData vl_old_EPTF_Var_CompBufferData := v_syncBuffer[vl_refreshRateId].syncBuffer[pl_compBufferIdx].compBufferData; |
| v_syncBuffer[vl_refreshRateId].syncBuffer[pl_compBufferIdx].compBufferData := {}; |
| for (var integer i:=0; i< sizeof(vl_old_EPTF_Var_CompBufferData); i:=i+1) { |
| if (vl_old_EPTF_Var_CompBufferData[i].localIdx != pl_idx) { |
| v_syncBuffer[vl_refreshRateId].syncBuffer[pl_compBufferIdx].compBufferData[sizeof(v_syncBuffer[vl_refreshRateId].syncBuffer[pl_compBufferIdx].compBufferData)] := vl_old_EPTF_Var_CompBufferData[i]; |
| } else { |
| var integer vl_remoteIdx := vl_old_EPTF_Var_CompBufferData[i].remoteIdx; |
| f_EPTF_str2int_HashMap_Erase(v_EPTF_Var_Hashmap_SyncBuffer,log2str(pl_idx,".",vl_remoteIdx,".",pl_refreshRateId,".",pl_compBufferIdx)); |
| } |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_Unsubscribe |
| // |
| // Purpose: |
| // Handler for Unsubscribe message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_Unsubscribe(in EPTF_Var_Msg_Unsubscribe pl_unsubscribe) runs on EPTF_Var_CT { |
| var EPTF_Var_Ref vl_subscriber := pl_unsubscribe.subscriber; |
| var EPTF_Var_Ref vl_provider := pl_unsubscribe.provider; |
| var EPTF_Var_SubscriptionMode vl_subscriptionMode := pl_unsubscribe.subscriptionMode; |
| var integer vl_refreshRate := pl_unsubscribe.refreshRate; |
| var integer vl_refreshRateId := -1; |
| |
| var EPTF_Var_CT vl_remoteCompRef := vl_subscriber.compRef; |
| |
| var integer vl_compBufferIdx; |
| f_EPTF_Var_checkConnection(vl_remoteCompRef,vl_refreshRate,vl_refreshRateId,vl_compBufferIdx); |
| // if not connected: |
| if (vl_compBufferIdx==-1) { |
| // this can never happen |
| f_EPTF_Var_error(log2str("SyncBuffer does not contain data for component ", vl_remoteCompRef)); |
| //f_EPTF_Base_stop(); |
| } |
| if (vl_subscriptionMode == sampled or vl_subscriptionMode == sampledAtSync or vl_subscriptionMode == timeLine) { |
| f_EPTF_Var_deregisterBufferedVar(vl_provider.idx, vl_refreshRateId, vl_compBufferIdx); |
| } |
| f_EPTF_Var_removeRemoteSubscriber(vl_provider.idx, vl_subscriber); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_RefreshContent |
| // |
| // Purpose: |
| // Handler for RefreshContent message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_RefreshContent(in EPTF_Var_Msg_RefreshContent pl_refreshContent) runs on EPTF_Var_CT { |
| var integer vl_myIdx := pl_refreshContent.subscriber.idx; |
| |
| if (ischosen(v_EPTF_Vars[vl_myIdx].content.invalid)) { |
| // this can never happen |
| v_EPTF_Vars[vl_myIdx].content := { direct := pl_refreshContent.content }; |
| return; |
| } |
| |
| // update current value |
| f_EPTF_Var_registerRefresh(vl_myIdx,pl_refreshContent.content); |
| return; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_AdjustContent |
| // |
| // Purpose: |
| // Handler for AdjustContent message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_AdjustContent(in EPTF_Var_Msg_AdjustContent pl_adjustContent) runs on EPTF_Var_CT { |
| var integer vl_myIdx := pl_adjustContent.provider.idx; |
| |
| if (vl_myIdx==-1) { |
| // FIXME: this adjust should not have been sent |
| f_EPTF_Var_error(log2str("Adjust request ignored: invalid adjust received: ", pl_adjustContent)); |
| return; |
| } |
| |
| if (ischosen(v_EPTF_Vars[vl_myIdx].provider.local)) { |
| f_EPTF_Var_error(log2str("Cannot adjust the content of the EPTF_Var[",vl_myIdx,"]. It has a local provider! ",v_EPTF_Vars[vl_myIdx]," EPTF_Var_Msg_AdjustContent message dropped.")); |
| //f_EPTF_Base_stop(); |
| } |
| if (ischosen(v_EPTF_Vars[vl_myIdx].provider.empty)) { |
| // I am a "parameter", adjust allowed after the guard fns accept the new value. |
| |
| // check if subsCanAdjust is true: |
| if(not v_EPTF_Vars[vl_myIdx].subsCanAdjust) { |
| // send adjustContentResp/failed to sender: |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_content2direct(v_EPTF_Vars[vl_myIdx].content,vl_currentContent); |
| //f_EPTF_Var_getContent(vl_myIdx,vl_currentContent); |
| f_EPTF_Var_send( |
| {adjustContentResp:={ false, // adjust failed |
| pl_adjustContent.subscribers,vl_currentContent,pl_adjustContent.respHandlerId |
| }}, |
| pl_adjustContent.subscribers.varList[pl_adjustContent.subscribers.lastIdx].compRef |
| ); |
| return; |
| } |
| |
| //call the guard fns: |
| var boolean vl_result := f_EPTF_Var_callGuardFns(vl_myIdx,pl_adjustContent.content); |
| if (not vl_result) { |
| // send adjustContentResp/failed to sender: |
| var EPTF_Var_DirectContent vl_currentContent; |
| f_EPTF_Var_content2direct(v_EPTF_Vars[vl_myIdx].content,vl_currentContent); |
| //f_EPTF_Var_getContent(vl_myIdx,vl_currentContent); |
| f_EPTF_Var_send( |
| {adjustContentResp:={ false, // adjust failed |
| pl_adjustContent.subscribers,vl_currentContent,pl_adjustContent.respHandlerId |
| }}, |
| pl_adjustContent.subscribers.varList[pl_adjustContent.subscribers.lastIdx].compRef |
| ); |
| } else { |
| f_EPTF_Var_send( |
| {adjustContentResp:={ true, // adjust successful |
| pl_adjustContent.subscribers,pl_adjustContent.content,pl_adjustContent.respHandlerId |
| }}, |
| pl_adjustContent.subscribers.varList[pl_adjustContent.subscribers.lastIdx].compRef |
| ); |
| // registerRefresh is called to notify subscribers: |
| f_EPTF_Var_registerRefresh(vl_myIdx,pl_adjustContent.content); |
| } |
| return; |
| } |
| if (ischosen(v_EPTF_Vars[vl_myIdx].provider.remote)) { |
| |
| if (v_EPTF_Vars[vl_myIdx].provider.remote.varRef.idx<0) { |
| // subscription is in progress. Have to wait for response to execute the actual adjust: |
| // just store the new value now: |
| |
| f_EPTF_Var_setContent(vl_myIdx, pl_adjustContent.content); |
| // flag this variable that adjust was buffered: |
| v_EPTF_Vars[vl_myIdx].provider.remote.varRef.idx := -2; |
| // refresh will be done when subscribeResp arrives |
| return; |
| } |
| |
| // this replaces sender information, so the response will not be sent to the subscriber who originally requested the adjust: |
| //f_EPTF_Var_adjustContent(vl_myIdx,pl_adjustContent.content); |
| |
| // forward adjust content for remote provider, but keep sender information: |
| var EPTF_Var_MessageRoute vl_route := pl_adjustContent.subscribers; |
| vl_route.lastIdx := vl_route.lastIdx + 1; |
| vl_route.varList[vl_route.lastIdx] := {self,vl_myIdx}; |
| f_EPTF_Var_send( |
| {adjustContent:={ |
| vl_route, |
| v_EPTF_Vars[vl_myIdx].provider.remote.varRef, |
| pl_adjustContent.content,pl_adjustContent.respHandlerId |
| }}, |
| v_EPTF_Vars[vl_myIdx].provider.remote.varRef.compRef |
| ); |
| } |
| return; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_AdjustContentResp |
| // |
| // Purpose: |
| // Handler for AdjustContentResp message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_AdjustContentResp(in EPTF_Var_Msg_AdjustContentResp pl_adjustContentResp) runs on EPTF_Var_CT { |
| var integer vl_lastIdx := pl_adjustContentResp.subscribers.lastIdx; |
| var integer vl_myIdx := pl_adjustContentResp.subscribers.varList[vl_lastIdx].idx; |
| |
| if (vl_lastIdx==0) { |
| // end of route reached |
| // the value of the content should not be changed, refreshContent will do it later |
| |
| // if (pl_adjustContentResp.result == false) { |
| // // for failed adjust content is only updated if it has changed: |
| // var EPTF_Var_DirectContent vl_currentContent; |
| // f_EPTF_Var_getContent(vl_myIdx,vl_currentContent); |
| // |
| // // if received value is different from current: |
| // if (vl_currentContent!=pl_adjustContentResp.content) { |
| // // update current value |
| // f_EPTF_Var_registerRefresh(vl_myIdx,pl_adjustContentResp.content); |
| // } |
| // // if received value is the same as the current, no refresh is |
| // // needed, because the original value was not changed, |
| // // this response is for a failed adjust |
| // // (failed adjusts cannot trigger refresh) |
| // } |
| |
| // call the user handler: |
| if (pl_adjustContentResp.respHandlerId != -1) { |
| // find handler data in the stack: |
| var EPTF_Var_adjustContentResp_handler vl_respHandler; |
| if (f_EPTF_getEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_adjustContentResp.respHandlerId,vl_respHandler)) { |
| // call the user handler (cannot be null: for null the respHandlerId was set to -1): |
| vl_respHandler.handlerFn.apply(vl_myIdx, pl_adjustContentResp.content, pl_adjustContentResp.result, vl_respHandler.argList); |
| // release the stack: |
| f_EPTF_deleteEPTF_Var_adjustContentResp_handler(adjustContentResp_handler_ParamStack,pl_adjustContentResp.respHandlerId); |
| } else { |
| // this is never called (just to remove the warning): |
| f_EPTF_Var_error("Callback function not found. Database error!"); |
| //f_EPTF_Base_stop(); |
| } |
| } |
| } else { |
| // Forward the message to the previous subscriber: |
| vl_lastIdx := vl_lastIdx-1; |
| //check if there the previous subscriber is still a subscriber (he might have unsubscribed): |
| var boolean vl_stillSubscribed := f_EPTF_Var_checkRemoteSubscriber(vl_myIdx,pl_adjustContentResp.subscribers.varList[vl_lastIdx]); |
| if (vl_stillSubscribed) { |
| f_EPTF_Var_send( |
| {adjustContentResp:={ pl_adjustContentResp.result, |
| {pl_adjustContentResp.subscribers.varList,vl_lastIdx}, |
| pl_adjustContentResp.content,pl_adjustContentResp.respHandlerId |
| }}, |
| pl_adjustContentResp.subscribers.varList[vl_lastIdx].compRef |
| ); |
| } else { |
| f_EPTF_Var_warning(log2str("Cannot forward adjustcontentNack to variable",pl_adjustContentResp.subscribers.varList[vl_lastIdx],". Not a subscriber of EPTF_Var[",vl_myIdx,"]")); |
| } |
| return; |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_GetRemoteContent |
| // |
| // Purpose: |
| // Handler for GetRemoteContent message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_GetRemoteContent(in EPTF_Var_Msg_GetRemoteContent pl_getRemoteContent, in EPTF_Var_CT pl_senderCompRef) runs on EPTF_Var_CT { |
| var integer vl_compBufferIdx; |
| var integer vl_refreshRateId := 0; |
| // if not connected: |
| if (not f_EPTF_Var_isConnected(pl_senderCompRef)) { |
| // use 0 for refreshRate and refreshRateId: default |
| f_EPTF_Var_registerConnection(pl_senderCompRef,vl_refreshRateId,vl_refreshRateId,vl_compBufferIdx); |
| } |
| |
| var integer vl_myIdx; |
| if (ischosen(pl_getRemoteContent.varId.name)) { |
| vl_myIdx := f_EPTF_Var_getId(pl_getRemoteContent.varId.name); |
| } else { |
| vl_myIdx := pl_getRemoteContent.varId.idx; |
| } |
| if (vl_myIdx<0) { |
| f_EPTF_Var_warning(log2str("EPTF_Var_Msg_GetRemoteContent is received for a nonexistent EPTF Variable: ", pl_getRemoteContent.varId)); |
| f_EPTF_Var_send({getRemoteContentResp := {omit, omit,omit,pl_getRemoteContent.blockingFlagIdx,pl_getRemoteContent.responseIdx}}, pl_senderCompRef); |
| return; |
| } |
| |
| // request original provider if getRemoteContent uses name |
| if (f_EPTF_Var_checkSubscriptionMode(vl_myIdx,pull) and ischosen(pl_getRemoteContent.varId.name)) { |
| v_EPTF_Vars[vl_myIdx].provider.remote.routeUpdateCounter := cg_EPTF_Var_routeUpdatePeriod; |
| } |
| |
| var EPTF_Var_DirectContent vl_providerDirectContent; |
| if (ischosen(v_EPTF_Vars[vl_myIdx].provider.local) and not f_EPTF_Var_checkLocalSubscriptionMode(vl_myIdx,pull)) { |
| // in case of pull, it will be updated in f_EPTF_Var_getContent |
| //f_EPTF_Var_refreshContent(vl_myIdx); without registerRefresh: |
| var EPTF_Var_DirectContent vl_prevContent; |
| f_EPTF_Var_content2direct(v_EPTF_Vars[vl_myIdx].content,vl_prevContent); |
| f_EPTF_Var_callCalcFn(vl_myIdx,vl_providerDirectContent); |
| if (vl_prevContent!=vl_providerDirectContent) { |
| f_EPTF_Var_setContent(vl_myIdx,vl_providerDirectContent); |
| f_EPTF_Var_updateTimeLine(vl_myIdx,vl_providerDirectContent); |
| f_EPTF_Var_callPostProcFns(vl_myIdx); |
| } |
| } else { |
| f_EPTF_Var_getContent(vl_myIdx, vl_providerDirectContent); |
| } |
| |
| var EPTF_Var_Msg_GetRemoteContentResp vl_getRemoteContentResp := { |
| omit, vl_providerDirectContent,v_EPTF_Vars[vl_myIdx].subsCanAdjust,pl_getRemoteContent.blockingFlagIdx,pl_getRemoteContent.responseIdx |
| } |
| // re-route pull subscription: |
| if (ischosen(pl_getRemoteContent.varId.name)) { |
| vl_getRemoteContentResp.provider := {self,vl_myIdx} |
| } |
| if (f_EPTF_Var_checkSubscriptionMode(vl_myIdx,pull) |
| and v_EPTF_Vars[vl_myIdx].provider.remote.varRef.idx != -1 |
| ) { |
| vl_getRemoteContentResp.provider := v_EPTF_Vars[vl_myIdx].provider.remote.varRef; // replace myself with my provider |
| } |
| f_EPTF_Var_send({getRemoteContentResp := vl_getRemoteContentResp}, pl_senderCompRef); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: as_EPTF_Var_handle_AdjustContentResp |
| // |
| // Purpose: |
| // Waits for a positive or negative response for an adjust to the given varibale with the given content, |
| // returns true if adjust successful, else false |
| /////////////////////////////////////////////////////////// |
| private altstep as_EPTF_Var_handle_AdjustContentResp(in integer pl_idx, in EPTF_Var_DirectContent pl_content, out boolean pl_result) runs on EPTF_Var_CT { |
| var EPTF_Var_MgmtMsg vl_EPTF_Var_MgmtIf_msg; |
| var EPTF_Var_CT vl_EPTF_Var_MgmtIf_msg_sender; |
| [] EPTF_Var_MgmtIf.receive({adjustContentResp:={?,{?,0},pl_content,?}}) -> value vl_EPTF_Var_MgmtIf_msg sender vl_EPTF_Var_MgmtIf_msg_sender { |
| pl_result := vl_EPTF_Var_MgmtIf_msg.adjustContentResp.result; |
| f_EPTF_Var_handle_AdjustContentResp(vl_EPTF_Var_MgmtIf_msg.adjustContentResp); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_adjustRemoteContentResp_handler |
| // |
| // Purpose: |
| // Handler function for adjustRemoteContent in f_EPTF_Var_handle_AdjustRemoteContent to send EPTF_Var_Msg_AdjustRemoteContentResp, |
| // pl_argList[0]: pl_senderCompRef converted to integer, |
| // pl_argList[1]: the respHandlerId of the user callback function |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_adjustRemoteContentResp_handler(in integer pl_idx, in EPTF_Var_DirectContent pl_content,in boolean pl_result, in EPTF_IntegerList pl_argList) runs on EPTF_Var_CT { |
| var EPTF_Var_CT pl_senderCompRef := f_EPTF_Var_downcast(f_EPTF_Base_downcast(pl_argList[0])); |
| if (pl_argList[1] != -1 or pl_argList[2] != -1) { |
| // if there is a handler or blocking |
| f_EPTF_Var_send({adjustRemoteContentResp := {{{idx:=pl_idx},pl_content,pl_argList[1],pl_argList[2],pl_argList[3]},pl_result}}, pl_senderCompRef); |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_AdjustRemoteContent |
| // |
| // Purpose: |
| // Handler function for AdjustRemoteContent message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_AdjustRemoteContent(in EPTF_Var_Msg_AdjustRemoteContent pl_adjustRemoteContent, in EPTF_Var_CT pl_senderCompRef) runs on EPTF_Var_CT { |
| var integer vl_compBufferIdx; |
| var integer vl_refreshRateId := 0; |
| // if not connected: |
| if (not f_EPTF_Var_isConnected(pl_senderCompRef)) { |
| // use 0 for refreshRate and refreshRateId: default |
| f_EPTF_Var_registerConnection(pl_senderCompRef,vl_refreshRateId,vl_refreshRateId,vl_compBufferIdx); |
| } |
| |
| var integer vl_myIdx; |
| if (ischosen(pl_adjustRemoteContent.varId.name)) { |
| vl_myIdx := f_EPTF_Var_getId(pl_adjustRemoteContent.varId.name); |
| } else { |
| vl_myIdx := pl_adjustRemoteContent.varId.idx; |
| } |
| if (vl_myIdx<0) { |
| f_EPTF_Var_warning(log2str("EPTF_Var_Msg_AdjustRemoteContent received for a nonexistent EPTF Variable: ", pl_adjustRemoteContent.varId)); |
| f_EPTF_Var_send({adjustRemoteContentResp := {pl_adjustRemoteContent,false}}, pl_senderCompRef); |
| return; |
| } |
| |
| // need to check topProviderType, so that f_EPTF_Var_adjustContent_Blocking would not fail: |
| var EPTF_TopProviderType vl_topProviderType; |
| f_EPTF_Var_getTopProviderType(vl_myIdx, vl_topProviderType); |
| if (vl_topProviderType == local) { |
| f_EPTF_Var_warning(log2str("EPTF_Var_Msg_AdjustRemoteContent received for an EPTF Variable with local top-provider: ", vl_myIdx)); |
| f_EPTF_Var_send({adjustRemoteContentResp := {pl_adjustRemoteContent,false}}, pl_senderCompRef); |
| return; |
| } |
| |
| // request original provider if adjustRemoteContent uses name |
| if (f_EPTF_Var_checkSubscriptionMode(vl_myIdx,pull) and ischosen(pl_adjustRemoteContent.varId.name)) { |
| v_EPTF_Vars[vl_myIdx].provider.remote.routeUpdateCounter := cg_EPTF_Var_routeUpdatePeriod; |
| } |
| f_EPTF_Var_adjustContent(vl_myIdx, pl_adjustRemoteContent.content, { refers(f_EPTF_Var_adjustRemoteContentResp_handler), |
| {f_EPTF_Base_upcast(pl_senderCompRef),pl_adjustRemoteContent.respHandlerId,pl_adjustRemoteContent.blockingFlagIdx,pl_adjustRemoteContent.responseIdx} }); |
| |
| // // blocks execution until response arrives: |
| // var boolean vl_result := f_EPTF_Var_adjustContent_Blocking(vl_myIdx, pl_adjustRemoteContent.content); |
| // |
| // if (vl_result) { |
| // f_EPTF_Var_send({adjustRemoteContentResp := {pl_adjustRemoteContent,true}}, pl_senderCompRef); |
| // } else { |
| // f_EPTF_Var_send({adjustRemoteContentResp := {pl_adjustRemoteContent,false}}, pl_senderCompRef); |
| // } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_SetSubsCanAdjust |
| // |
| // Purpose: |
| // Handler function for EPTF_Var_Msg_SetSubsCanAdjust message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_SetSubsCanAdjust(in EPTF_Var_Msg_SetSubsCanAdjust pl_setSubsCanAdjust) runs on EPTF_Var_CT { |
| var integer vl_myidx := pl_setSubsCanAdjust.subscriber.idx; |
| v_EPTF_Vars[vl_myidx].subsCanAdjust := pl_setSubsCanAdjust.subsCanAdjust; |
| f_EPTF_Var_callSubsCanAdjustNotifyFns(vl_myidx); |
| f_EPTF_Var_setSubsCanAdjustInAllSubscribers(vl_myidx); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_Hello |
| // |
| // Purpose: |
| // Handler function for Hello message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_Hello(in EPTF_Var_Msg_Hello pl_hello, in EPTF_Var_CT pl_EPTF_Var_MgmtIf_msg_sender) runs on EPTF_Var_CT { |
| |
| // register the connection |
| var integer vl_compBufferIdx; |
| var integer vl_refreshRateId := 0; |
| // if not connected register the connection: |
| if (not f_EPTF_Var_isConnected(pl_EPTF_Var_MgmtIf_msg_sender)) { |
| // use 0 for refreshRate and refreshRateId: default |
| f_EPTF_Var_registerConnection(pl_EPTF_Var_MgmtIf_msg_sender,vl_refreshRateId,vl_refreshRateId,vl_compBufferIdx); |
| } |
| |
| // send helloAck: |
| f_EPTF_Var_send({helloAck:={pl_hello.trId}},pl_EPTF_Var_MgmtIf_msg_sender); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_HelloAck |
| // |
| // Purpose: |
| // Handler function for HelloAck message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_HelloAck(in EPTF_Var_Msg_HelloAck pl_helloAck, in EPTF_Var_CT pl_EPTF_Var_MgmtIf_msg_sender) runs on EPTF_Var_CT { |
| var integer vl_trId := pl_helloAck.trId; |
| |
| // disable blocking if it was requested: |
| if (vl_trId != -1) { |
| f_EPTF_setValueboolean(v_booleanPool,vl_trId,true); |
| v_EPTF_Var_numPendingHellos := v_EPTF_Var_numPendingHellos - 1; |
| var integer vl_refreshRateId := 0; |
| var integer vl_compBufferIdx; |
| // if not connected: |
| if (not f_EPTF_Var_isConnected(pl_EPTF_Var_MgmtIf_msg_sender)) { |
| // only register the connection if the connection setup was successful |
| // use 0 for refreshRate and refreshRateId: default |
| f_EPTF_Var_registerConnection(pl_EPTF_Var_MgmtIf_msg_sender,vl_refreshRateId,vl_refreshRateId,vl_compBufferIdx); |
| } |
| } |
| |
| // call HelloAck response handler in case of nonblocking mode |
| var integer vl_idx := f_EPTF_Base_upcast(pl_EPTF_Var_MgmtIf_msg_sender); |
| if(isbound(v_EPTF_Var_nonBlockingEnabled[vl_idx]) and v_EPTF_Var_nonBlockingEnabled[vl_idx]){ |
| f_EPTF_Var_connectCallback(pl_EPTF_Var_MgmtIf_msg_sender); |
| v_EPTF_Var_nonBlockingEnabled[vl_idx] := false; |
| } |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_Bye |
| // |
| // Purpose: |
| // Handler function for Bye message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_Bye(in EPTF_Var_CT pl_EPTF_Var_MgmtIf_msg_sender) runs on EPTF_Var_CT { |
| for(var integer i:=0; i<sizeof(v_EPTF_Vars); i:=i+1) { |
| // remove all remote providers with compRef == sender: |
| if (ischosen(v_EPTF_Vars[i].provider.remote)) { |
| if (v_EPTF_Vars[i].provider.remote.varRef.compRef == pl_EPTF_Var_MgmtIf_msg_sender |
| or v_EPTF_Vars[i].provider.remote.compRef == pl_EPTF_Var_MgmtIf_msg_sender) { |
| v_EPTF_Vars[i].provider := {empty:={}}; |
| f_EPTF_Var_callUnsubscribeNotifyFns(i); |
| } |
| } |
| // remove all remote subscribers with compRef == sender: |
| var EPTF_Var_Subscribers vl_oldSubscribers := v_EPTF_Vars[i].subscribers; |
| var integer vl_last := sizeof(vl_oldSubscribers); |
| v_EPTF_Vars[i].subscribers := {}; |
| for (var integer j:=0; j<vl_last; j:=j+1) { |
| if (not (ischosen(vl_oldSubscribers[j].remote) and vl_oldSubscribers[j].remote.varRef.compRef == pl_EPTF_Var_MgmtIf_msg_sender) ) { |
| v_EPTF_Vars[i].subscribers[sizeof(v_EPTF_Vars[i].subscribers)] := vl_oldSubscribers[j] |
| } else { |
| // if remote subscriber is buffered: |
| if (vl_oldSubscribers[j].remote.subscriptionMode == sampled or vl_oldSubscribers[j].remote.subscriptionMode == sampledAtSync or vl_oldSubscribers[j].remote.subscriptionMode == timeLine) { |
| var integer vl_compBufferIdx; |
| var integer vl_refreshRate := v_syncBuffer[vl_oldSubscribers[j].remote.refreshRateId].refreshRate; |
| f_EPTF_Var_checkConnection(pl_EPTF_Var_MgmtIf_msg_sender,vl_refreshRate,vl_oldSubscribers[j].remote.refreshRateId,vl_compBufferIdx); |
| f_EPTF_Var_deregisterBufferedVar(i,vl_oldSubscribers[j].remote.refreshRateId,vl_compBufferIdx); |
| } |
| } |
| } |
| } |
| // send byeAck: |
| f_EPTF_Var_send({byeAck:={}},pl_EPTF_Var_MgmtIf_msg_sender); |
| |
| // remove connection from syncBuffer: |
| f_EPTF_Var_deregisterConnection(pl_EPTF_Var_MgmtIf_msg_sender); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_ByeAck |
| // |
| // Purpose: |
| // Handler function for Byeack message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_ByeAck(in EPTF_Var_CT pl_EPTF_Var_MgmtIf_msg_sender) runs on EPTF_Var_CT return boolean { |
| disconnect(self:EPTF_Var_MgmtIf,pl_EPTF_Var_MgmtIf_msg_sender:EPTF_Var_MgmtIf); |
| v_EPTF_Var_pendingByeNum := v_EPTF_Var_pendingByeNum - 1; |
| // remove the connection from the database |
| var boolean vl_result := f_EPTF_Var_deregisterConnection(pl_EPTF_Var_MgmtIf_msg_sender); |
| if (vl_result == false and v_EPTF_Var_pendingByeNum != 0) { |
| vl_result := true; // there are unanswered bye messages |
| f_EPTF_Var_debug("There are unanswered bye messages, cannot exit yet."); |
| } |
| return vl_result; |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_handle_RefreshTimeLines |
| // |
| // Purpose: |
| // Handler function for RefreshTimeLines message |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_handle_RefreshTimeLines(in EPTF_Var_Msg_RefreshTimeLines pl_refreshTimeLines) runs on EPTF_Var_CT { |
| var integer vl_myIdx; |
| var EPTF_Var_DirectContent vl_newContent; |
| var integer vl_refreshRateId := 0; |
| var integer vl_compBufferIdx; |
| f_EPTF_Var_checkConnection(null,pl_refreshTimeLines.refreshRate,vl_refreshRateId,vl_compBufferIdx); |
| if (vl_refreshRateId==-1) { |
| f_EPTF_Var_debug(%definitionId&": New refresh rate is registered: refresh rate is unknown: "&int2str(pl_refreshTimeLines.refreshRate)); |
| f_EPTF_Var_registerConnection( |
| pl_remoteCompRef := null, |
| pl_refreshRate := pl_refreshTimeLines.refreshRate, |
| pl_refreshRateId := vl_refreshRateId, |
| pl_compBufferIdx := vl_compBufferIdx |
| ); |
| //return; |
| } |
| var float vl_timeStamp := f_EPTF_Base_getAbsTimeInSecs(f_EPTF_SchedulerComp_snapshotTime()); |
| for(var integer i:=0; i<sizeof(pl_refreshTimeLines.timeLineList); i:=i+1) { |
| vl_myIdx := pl_refreshTimeLines.timeLineList[i].idx; |
| // find the timeline for this refreshRate in the variable |
| var integer vl_refreshRateIdInTimeLineBuffer := -1; |
| for (var integer ii := 0; ii<sizeof(v_EPTF_Vars[vl_myIdx].timeLineBuffer); ii:=ii+1) { |
| if (v_EPTF_Vars[vl_myIdx].timeLineBuffer[ii].refreshRateId == vl_refreshRateId) { |
| vl_refreshRateIdInTimeLineBuffer := ii; |
| continue; |
| } |
| // timeLines for different refreshRate are concatenated for the varible: |
| v_EPTF_Vars[vl_myIdx].timeLineBuffer[ii].timeLine.size := v_EPTF_Vars[vl_myIdx].timeLineBuffer[ii].timeLine.size + pl_refreshTimeLines.timeLineList[i].timeLine.size; |
| v_EPTF_Vars[vl_myIdx].timeLineBuffer[ii].timeLine.timeLineData := v_EPTF_Vars[vl_myIdx].timeLineBuffer[ii].timeLine.timeLineData & pl_refreshTimeLines.timeLineList[i].timeLine.timeLineData; |
| } |
| // set the new timeline for the current refresRate: |
| if(vl_refreshRateIdInTimeLineBuffer!=-1) { |
| // timeline exists for this refresh rate in this variable |
| // update the timeLine |
| v_EPTF_Vars[vl_myIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine := pl_refreshTimeLines.timeLineList[i].timeLine; |
| } else { |
| // if I am a timeline subscriber: |
| // FIXME: timeLine needed for sampled also because UIHandlerWidgetFunctions uses it? |
| //if (f_EPTF_Var_checkSubscriptionMode(vl_myIdx,timeLine)) { |
| vl_refreshRateIdInTimeLineBuffer := sizeof(v_EPTF_Vars[vl_myIdx].timeLineBuffer); |
| v_EPTF_Vars[vl_myIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].refreshRateId := vl_refreshRateId; |
| v_EPTF_Vars[vl_myIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].bufferNum := 0; |
| v_EPTF_Vars[vl_myIdx].timeLineBuffer[vl_refreshRateIdInTimeLineBuffer].timeLine := pl_refreshTimeLines.timeLineList[i].timeLine; |
| //} |
| } |
| |
| // new content is the last item in the timeLine: |
| vl_newContent := pl_refreshTimeLines.timeLineList[i].timeLine.timeLineData[pl_refreshTimeLines.timeLineList[i].timeLine.size-1].content; |
| // update current value |
| f_EPTF_Var_registerRefresh(vl_myIdx,vl_newContent,vl_timeStamp); |
| |
| // send timeLine to buffered subscribers with same refreshRate |
| for(var integer j:=0; j<sizeof(v_EPTF_Vars[vl_myIdx].subscribers); j:=j+1) { |
| if (ischosen(v_EPTF_Vars[vl_myIdx].subscribers[j].remote) and |
| v_EPTF_Vars[vl_myIdx].subscribers[j].remote.refreshRateId == vl_refreshRateId and |
| (v_EPTF_Vars[vl_myIdx].subscribers[j].remote.subscriptionMode == sampled or |
| v_EPTF_Vars[vl_myIdx].subscribers[j].remote.subscriptionMode == sampledAtSync or |
| v_EPTF_Vars[vl_myIdx].subscribers[j].remote.subscriptionMode == timeLine) ) { |
| if (pl_refreshTimeLines.timeLineList[i].timeLine.size>0) { |
| f_EPTF_Var_send( |
| {refreshTimeLines := { |
| pl_refreshTimeLines.refreshRate, pl_refreshTimeLines.flushCounter, |
| {{v_EPTF_Vars[vl_myIdx].subscribers[j].remote.varRef.idx,pl_refreshTimeLines.timeLineList[i].timeLine}} |
| }}, |
| v_EPTF_Vars[vl_myIdx].subscribers[j].remote.varRef.compRef |
| ); |
| } |
| } |
| |
| } |
| } |
| //action("After refresh: v_EPTF_Vars: ", v_EPTF_Vars); |
| // send timeLines to subscribers |
| //f_EPTF_Var_handle_syncTimeout(); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_mainHandler_MgmtIf |
| // |
| // Purpose: |
| // The main handler function of the EPTF_Var_MgmtIf. |
| // returns true if the repeat, false to exit from the main altsep |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_mainHandler_MgmtIf( |
| in EPTF_Var_MgmtMsg vl_EPTF_Var_MgmtIf_msg, |
| in EPTF_Var_CT vl_EPTF_Var_MgmtIf_msg_sender) runs on EPTF_Var_CT return boolean { |
| v_EPTF_Var_nofPendingMsgs := v_EPTF_Var_nofPendingMsgs - 1; |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.subscribe)) { |
| f_EPTF_Var_handle_Subscribe(vl_EPTF_Var_MgmtIf_msg.subscribe); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.isPresentRemote)) { |
| f_EPTF_Var_handle_IsPresentRemote(vl_EPTF_Var_MgmtIf_msg.isPresentRemote,vl_EPTF_Var_MgmtIf_msg_sender); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.isPresentRemoteResp)) { |
| f_EPTF_Var_handle_IsPresentRemoteResp(vl_EPTF_Var_MgmtIf_msg.isPresentRemoteResp); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.subscribeResp)) { |
| f_EPTF_Var_handle_SubscribeResp(vl_EPTF_Var_MgmtIf_msg.subscribeResp, vl_EPTF_Var_MgmtIf_msg_sender); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.unsubscribe)) { |
| f_EPTF_Var_handle_Unsubscribe(vl_EPTF_Var_MgmtIf_msg.unsubscribe); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.refreshContent)) { |
| f_EPTF_Var_handle_RefreshContent(vl_EPTF_Var_MgmtIf_msg.refreshContent); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.adjustContent)) { |
| f_EPTF_Var_handle_AdjustContent(vl_EPTF_Var_MgmtIf_msg.adjustContent); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.adjustContentResp)) { |
| f_EPTF_Var_handle_AdjustContentResp(vl_EPTF_Var_MgmtIf_msg.adjustContentResp); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.getRemoteContent)) { |
| f_EPTF_Var_handle_GetRemoteContent(vl_EPTF_Var_MgmtIf_msg.getRemoteContent, vl_EPTF_Var_MgmtIf_msg_sender); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.adjustRemoteContent)) { |
| f_EPTF_Var_handle_AdjustRemoteContent(vl_EPTF_Var_MgmtIf_msg.adjustRemoteContent, vl_EPTF_Var_MgmtIf_msg_sender); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.adjustRemoteContentResp)) { |
| f_EPTF_Var_handle_AdjustRemoteContentResp(vl_EPTF_Var_MgmtIf_msg.adjustRemoteContentResp); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.hello)) { |
| f_EPTF_Var_handle_Hello(vl_EPTF_Var_MgmtIf_msg.hello, vl_EPTF_Var_MgmtIf_msg_sender); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.helloAck)) { |
| f_EPTF_Var_handle_HelloAck(vl_EPTF_Var_MgmtIf_msg.helloAck, vl_EPTF_Var_MgmtIf_msg_sender); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.bye)) { |
| f_EPTF_Var_handle_Bye(vl_EPTF_Var_MgmtIf_msg_sender); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.byeAck)) { |
| if(not f_EPTF_Var_handle_ByeAck(vl_EPTF_Var_MgmtIf_msg_sender)) { |
| f_EPTF_Var_debug(log2str(%definitionId, ": all peers disconnected.")); |
| } |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.refreshTimeLines)) { |
| f_EPTF_Var_handle_RefreshTimeLines(vl_EPTF_Var_MgmtIf_msg.refreshTimeLines); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.getRemoteContentResp)) { |
| f_EPTF_Var_handle_GetRemoteContentResp(vl_EPTF_Var_MgmtIf_msg.getRemoteContentResp); |
| return true; |
| } |
| if (ischosen(vl_EPTF_Var_MgmtIf_msg.setSubsCanAdjust)) { |
| f_EPTF_Var_handle_SetSubsCanAdjust(vl_EPTF_Var_MgmtIf_msg.setSubsCanAdjust); |
| return true; |
| } |
| |
| f_EPTF_Var_error(log2str("Unexpected message received from ",vl_EPTF_Var_MgmtIf_msg_sender,": ",vl_EPTF_Var_MgmtIf_msg)); |
| return false; |
| } |
| |
| |
| /////////////////////////////////////////////////////////// |
| // Function: as_EPTF_Var_mainHandler_MgmtIf |
| // |
| // Purpose: |
| // The main handler of the EPTF_Var_MgmtIf. |
| /////////////////////////////////////////////////////////// |
| private altstep as_EPTF_Var_mainHandler_MgmtIf() runs on EPTF_Var_CT { |
| var EPTF_Var_MgmtMsg vl_EPTF_Var_MgmtIf_msg; |
| var EPTF_Var_CT vl_EPTF_Var_MgmtIf_msg_sender; |
| [] EPTF_Var_MgmtIf.receive(?) -> value vl_EPTF_Var_MgmtIf_msg sender vl_EPTF_Var_MgmtIf_msg_sender { |
| if (f_EPTF_Var_mainHandler_MgmtIf(vl_EPTF_Var_MgmtIf_msg,vl_EPTF_Var_MgmtIf_msg_sender)) {repeat;} |
| } |
| [] as_EPTF_Var_refreshSubscribers(); |
| [] as_EPTF_Var_Msg_Buffer_Handler(); |
| } |
| |
| group Logging { |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_error |
| // |
| // Purpose: |
| // Function to log an error from Variable feature. |
| // |
| // Parameters: |
| // - pl_message - *in* *charstring* - the message to log |
| // |
| // Return Value: |
| // - |
| // |
| // Errors & assertions: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_error(in charstring pl_message) |
| runs on EPTF_Var_CT |
| { |
| f_EPTF_Logging_error(true, tsp_EPTF_Var_loggingComponentMask&": "&pl_message); |
| f_EPTF_Base_stopAll(); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_warning |
| // |
| // Purpose: |
| // Function to log a warning from Variable feature. |
| // |
| // Parameters: |
| // - pl_message - *in* *charstring* - the message to log |
| // |
| // Return Value: |
| // - |
| // |
| // Errors & assertions: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_warning(in @lazy charstring pl_message) |
| runs on EPTF_Var_CT |
| { |
| f_EPTF_Logging_warningV2(pl_message, v_Var_loggingMaskId, {c_EPTF_Var_loggingClassIdx_Warning}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_debug |
| // |
| // Purpose: |
| // Function to log a debug message from Var feature. |
| // |
| // Parameters: |
| // - pl_message - *in* *charstring* - the message to log |
| // |
| // Return Value: |
| // - |
| // |
| // Errors & assertions: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_debug(in @lazy charstring pl_message) |
| runs on EPTF_Var_CT |
| { |
| f_EPTF_Logging_debugV2(pl_message, v_Var_loggingMaskId, {c_EPTF_Var_loggingClassIdx_Debug}); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_debugEnabled |
| // |
| // Purpose: |
| // Function to check if debug is enabled for Variable |
| // |
| // Parameters: |
| // - |
| // |
| // Return Value: |
| // *boolean* - true if debug enalbed |
| // |
| // Errors & assertions: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_debugEnabled() |
| runs on EPTF_Var_CT |
| return boolean |
| { |
| return f_EPTF_Logging_isEnabled(v_Var_loggingMaskId, c_EPTF_Var_loggingClassIdx_Debug); |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_enableDebug |
| // |
| // Purpose: |
| // Function enables debug logging for Variable |
| // |
| // Parameters: |
| // - |
| // |
| // Return Value: |
| // - |
| // |
| // Errors & assertions: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| public function f_EPTF_Var_enableDebug() |
| runs on EPTF_Var_CT |
| { |
| f_EPTF_Logging_enableLocalMask(v_Var_loggingMaskId, c_EPTF_Var_loggingClassIdx_Debug) |
| } |
| |
| /////////////////////////////////////////////////////////// |
| // Function: f_EPTF_Var_disableDebug |
| // |
| // Purpose: |
| // Function disables debug logging for Variable |
| // |
| // Parameters: |
| // - |
| // |
| // Return Value: |
| // - |
| // |
| // Errors & assertions: |
| // - |
| // |
| // Detailed Comments: |
| // - |
| // |
| /////////////////////////////////////////////////////////// |
| private function f_EPTF_Var_disableDebug() |
| runs on EPTF_Var_CT |
| { |
| f_EPTF_Logging_disableLocalMask(v_Var_loggingMaskId, c_EPTF_Var_loggingClassIdx_Debug) |
| } |
| } // group Logging |
| |
| } // group Private |
| |
| } // end of module |