blob: 83fa1e46c09f8e1fb5390e783971d980bd137cdb [file] [log] [blame]
///////////////////////////////////////////////////////////////////////////////
// //
// 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