blob: a5d6375bcff925d3708e3b47452bc88b569c1b01 [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_DataSourceClient_Functions
//
// Purpose:
// This module contains the implementation of EPTF_CLL_DataSource functions.
//
// Module depends on:
// <EPTF_CLL_Base_Functions>
// <EPTF_CLL_Variable_Functions>
// <EPTF_CLL_DataSource_Definitions>
// <EPTF_CLL_HashMapStr2Int_Functions>
// <EPTF_CLL_HashMap_Functions>
// <EPTF_CLL_Semaphore_Functions>
// <EPTF_CLL_Variable_Definitions>
//
// Module Parameters:
// tsp_debug_EPTF_DataSource_Functions - boolean - enable/disable debug logs
//
// Current Owner:
// Jozsef Gyurusi (ethjgi)
//
// Last Review Date:
// 2011-02-03
//
// Detailed Comments:
// This module contains the interface functions for the EPTF_CLL_DataSource.
//
// Public functions:
// <f_EPTF_DataSourceClient_init_CT>
// <f_EPTF_DataSourceClient_connectToServer>
// <f_EPTF_DataSourceClient_registerData>
// <f_EPTF_DataSourceClient_registerDataValue>
// <f_EPTF_DataSourceClient_registerSetDataValue>
// <f_EPTF_DataSourceClient_registerCondition>
// <f_EPTF_DataSourceClient_sendReady>
// <f_EPTF_DataSourceClient_getData>
// <f_EPTF_DataSourceClient_getData_nonBlocking>
// <f_EPTF_DataSourceClient_getDataValue>
// <f_EPTF_DataSourceClient_getDataValue_nonBlocking>
// <f_EPTF_DataSourceClient_setDataValue>
// <f_EPTF_DataSourceClient_setDataValue_nonBlocking>
// <f_EPTF_DataSourceClient_checkData>
// <f_EPTF_DataSourceClient_enableUpdate>
// <f_EPTF_DataSourceClient_disableUpdate>
// <f_EPTF_DataSourceClient_getCondition> - to be implemented
// <f_EPTF_DataSourceClient_getCondition_nonBlocking>
// <f_EPTF_DataSourceClient_extractParams>
//
// All other functions in this module are private!
//
///////////////////////////////////////////////////////////////
module EPTF_CLL_DataSourceClient_Functions {
import from EPTF_CLL_Logging_Definitions all;
import from EPTF_CLL_Logging_Functions all;
import from EPTF_CLL_Common_Definitions all;
import from EPTF_CLL_Base_Functions all;
import from EPTF_CLL_Variable_Functions all;
import from EPTF_CLL_DataSource_Definitions all;
import from EPTF_CLL_DataSource_Functions all;
import from EPTF_CLL_HashMapStr2Int_Functions all;
import from EPTF_CLL_HashMap_Functions all;
import from EPTF_CLL_Semaphore_Functions all;
import from EPTF_CLL_Variable_Definitions all;
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_init_CT
//
// Purpose:
// Init function for DataSourceClient_CT
//
// Parameters:
// *in charstring pl_selfName* - the name of the component
// *in* <EPTF_DataSource_CT> *pl_sourceCompRef* - the
// main DataSource component (server).
// If it is null, no connection is made, the function
// <f_EPTF_DataSourceClient_connectToServer> should be called
// later.
//
// Return Value:
// -
//
// Detailed Comments:
// Has to be called before any other DataSourceClient
// function is used
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_init_CT(in charstring pl_selfName, in EPTF_DataSource_CT pl_sourceCompRef)
runs on EPTF_DataSourceClient_CT {
if (v_EPTF_DataSourceClient_initialized) {
return;
}
f_EPTF_Base_init_CT(pl_selfName);
f_EPTF_Logging_init_CT(pl_selfName);
f_EPTF_Var_init_CT(pl_selfName);
f_EPTF_HashMap_init_CT(pl_selfName);
f_EPTF_Semaphore_init_CT(pl_selfName);
v_EPTF_DataSourceClient_connected := false;
f_EPTF_DataSourceClient_connectToServer(pl_sourceCompRef);
v_EPTF_DataSourceClient_initialized := true;
v_DataSourceClient_handler := activate(as_EPTF_DataSourceClient_EventHandler());
f_EPTF_Base_registerCleanup(refers(f_EPTF_DataSourceClient_cleanup_CT));
v_fcb_EPTF_DataSourceClient_dataHandler_List := {};
v_fcb_EPTF_DataSourceClient_dataValueHandler_List := {};
v_fcb_EPTF_DataSourceClient_setDataValueHandler_List := {};
v_EPTF_DataSourceClient_dataHandlerHash := f_EPTF_str2int_HashMap_New(c_EPTF_DataSourceClient_dataHandlerHashName);
v_fcb_EPTF_DataSourceClient_conditionHandler_List := {};
v_EPTF_DataSourceClient_dataValueHash := f_EPTF_str2int_HashMap_New(c_EPTF_DataSourceClient_dataValueHashName);
v_EPTF_DataSourceClient_dataValue_List := {};
v_EPTF_DataSourceClient_Msg_List := {};
v_EPTF_DataSourceClient_GetDataHandler_DB := {};
v_EPTF_DataSourceClient_GetDataValueHandler_DB := {};
v_EPTF_DataSourceClient_pendingGetDataHash := f_EPTF_str2int_HashMap_New(c_EPTF_DataSourceClient_pendingGetDataHashName);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_connectToServer
//
// Purpose:
// Connects to the specified DataSource component
//
// Parameters:
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef
// to connect to. If it is null, no connection is made.
//
// Return Value:
// -
//
// Detailed Comments:
// If this function is called only once with non-null argument,
// the <f_EPTF_DataSourceClient_registerData> can be called
// without specifying the *pl_sourceCompRef* argument.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_connectToServer(in EPTF_DataSource_CT pl_sourceCompRef) runs on EPTF_DataSourceClient_CT {
if (pl_sourceCompRef!=null) {
connect(pl_sourceCompRef:EPTF_DataSourceIf,self:EPTF_DataSourceClientIf);
v_EPTF_DataSourceClient_connected := true;
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_registerData
//
// Purpose:
// Registers a data handler into the DataSource_CT
//
// Parameters:
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in <fcb_EPTF_DataSourceClient_dataHandler> pl_dataHandler* - this function is called
// when a data is requested for the given dataSource and ptcName
// The function should return the name of the EPTF Variable that contains the value
// of the requested data.
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef
// to register the data into. If not specified the data is registered to the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// -
//
// Detailed Comments:
// Only one handler can be registered for the same pl_source and pl_ptcName,
// but it processes all dataElements and its parameters.
// The function might create the variable, or just return
// its name if it already existed before.
// The registered function can be called by calling <f_EPTF_DataSource_getData>
// on the component pl_sourceCompRef with the pl_source and pl_ptcName arguments registered here.
// Compare with <f_EPTF_DataSourceClient_registerDataValue>.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_registerData(
in charstring pl_source,
in charstring pl_ptcName := "",
in fcb_EPTF_DataSourceClient_dataHandler pl_dataHandler,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT {
if(not v_EPTF_DataSourceClient_connected) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot register handler fn ",pl_dataHandler,
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " into pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource"));
return;
}
var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
vl_handlerId := sizeof(v_fcb_EPTF_DataSourceClient_dataHandler_List);
v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId] := pl_dataHandler;
f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId);
} else {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot register handler fn ",pl_dataHandler,
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName,": Handler already registered"));
return;
}
f_EPTF_DataSourceClient_registerSource(pl_source,pl_ptcName,pl_sourceCompRef);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_registerDataValue
//
// Purpose:
// Registers a dataValue handler into the DataSource_CT
//
// Parameters:
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in <fcb_EPTF_DataSourceClient_dataValueHandler> pl_dataValueHandler* - this function is called
// when a data value is requested for the given dataSource and ptcName
// The function should return the value of the requested data.
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef
// to register the data into. If not specified the data is registered to the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// -
//
// Detailed Comments:
// Only one value-handler can be registered for the same pl_source and pl_ptcName,
// but it processes all dataElements and its parameters.
//
// The registered function can be called by calling <f_EPTF_DataSource_getDataValue>
// on the component pl_sourceCompRef with the pl_source and pl_ptcName arguments registered here.
//
// Note, that if no dataValue-handler was specified, getData handlers are checked
// if they can return the variable name for the requested data. If they can, the value
// contained in the variable will be returned.
// If there is no such variable, the condition handlers are checked. If there is a condition,
// its value will be retured.
// This means that getDataValue can be used for dataElements with getDataHandler only or request the value
// of conditions.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_registerDataValue(
in charstring pl_source,
in charstring pl_ptcName := "",
in fcb_EPTF_DataSourceClient_dataValueHandler pl_dataValueHandler,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT {
if(not v_EPTF_DataSourceClient_connected) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot register value-handler fn ",pl_dataValueHandler,
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " into pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource"));
return;
}
// data value handler names will be prefixed with "DVH_", uses same hashTable
var charstring vl_handlerIdStr := "DVH_"&pl_source&"@"&pl_ptcName;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
vl_handlerId := sizeof(v_fcb_EPTF_DataSourceClient_dataValueHandler_List);
v_fcb_EPTF_DataSourceClient_dataValueHandler_List[vl_handlerId] := pl_dataValueHandler;
f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId);
} else {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot register value-handler fn ",pl_dataValueHandler,
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName,": Value-handler already registered"));
return;
}
f_EPTF_DataSourceClient_registerSource(pl_source,pl_ptcName,pl_sourceCompRef);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_registerSetDataValue
//
// Purpose:
// Registers a setDataValue handler into the DataSource_CT
//
// Parameters:
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in <fcb_EPTF_DataSourceClient_setDataValueHandler> pl_setDataValueHandler* - this function is called
// when a set data value is requested for the given dataSource and ptcName
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef
// to register the data into. If not specified the data is registered to the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// -
//
// Detailed Comments:
// Only one setDataValue handler can be registered for the same pl_source and pl_ptcName,
// but it processes all dataElements and its parameters.
//
// The registered function can be called by calling <f_EPTF_DataSource_setDataValue>
// on the component pl_sourceCompRef with the pl_source and pl_ptcName arguments registered here.
//
// Note, that if there is a getData handler but no setDataValue handler for the given data,
// the value of the variable returned by the getData handler will be set to the requested value.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_registerSetDataValue(
in charstring pl_source,
in charstring pl_ptcName := "",
in fcb_EPTF_DataSourceClient_setDataValueHandler pl_setDataValueHandler,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT {
if(not v_EPTF_DataSourceClient_connected) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot register set-value-handler fn ",pl_setDataValueHandler,
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " into pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource"));
return;
}
// set data value handler names will be prefixed with "SDVH_", uses same hashTable
var charstring vl_handlerIdStr := "SDVH_"&pl_source&"@"&pl_ptcName;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
vl_handlerId := sizeof(v_fcb_EPTF_DataSourceClient_setDataValueHandler_List);
v_fcb_EPTF_DataSourceClient_setDataValueHandler_List[vl_handlerId] := pl_setDataValueHandler;
f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId);
} else {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot register value-handler fn ",pl_setDataValueHandler,
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName,": Set-Value-handler already registered"));
return;
}
f_EPTF_DataSourceClient_registerSource(pl_source,pl_ptcName,pl_sourceCompRef);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_registerCondition
//
// Purpose:
// Registers a condition handler into the DataSource_CT
//
// Parameters:
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in <fcb_EPTF_DataSourceClient_conditionHandler> pl_conditionHandler* - this function is called
// when a condition value is requested for the given dataSource, ptcName and method
// *in charstring pl_method* - the name of the method that corresponds to this condition handler
// (dataSource+ptcName should be a unigue id of the location of the condition) and
// (dataSource+ptcName+method should be a unigue id of the condition). Default: "" which means
// that log2str(pl_conditionHandler) is used for the method.
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef
// to register the data into. If not specified the data is registered to the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// -
//
// Detailed Comments:
// Only one handler can be registered for the same pl_source, pl_ptcName and pl_method,
// but it processes all parameters.
// The registered function can be called by calling <f_EPTF_DataSource_getCondition>
// on the component pl_sourceCompRef with the pl_source,pl_ptcName and pl_method arguments registered here.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_registerCondition(
in charstring pl_source,
in charstring pl_ptcName := "",
in fcb_EPTF_DataSourceClient_conditionHandler pl_conditionHandler,
in charstring pl_method := "",
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT {
if(not v_EPTF_DataSourceClient_connected) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot register condition handler fn ",pl_conditionHandler,
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " pl_method: ",pl_method, " into pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource"));
return;
}
if (pl_method=="") {
pl_method := log2str(pl_conditionHandler);
}
var charstring vl_handlerIdStr := pl_source&"@"&pl_ptcName&"/"&pl_method;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
vl_handlerId := sizeof(v_fcb_EPTF_DataSourceClient_conditionHandler_List);
v_fcb_EPTF_DataSourceClient_conditionHandler_List[vl_handlerId] := pl_conditionHandler;
f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId);
} else {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot register condition handler fn ",pl_conditionHandler,
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName," pl_method: ",pl_method,": Handler already registered"));
return;
}
f_EPTF_DataSourceClient_registerSource(pl_source,pl_ptcName,pl_sourceCompRef);
}
private function f_EPTF_DataSourceClient_registerSource(
in charstring pl_source,
in charstring pl_ptcName := "",
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT {
// send registerData if it was not already sent:
var charstring vl_handlerIdStr := "Registered:"&pl_source&"@"&pl_ptcName;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId);
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{registerData:={pl_source,pl_ptcName}},pl_sourceCompRef);
}
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_sendReady
//
// Purpose:
// Notifies the DataSource_CT that the client is ready to receive data requests
//
// Parameters:
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data)
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef
// If not specified the data is sent to the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// -
//
// Detailed Comments:
// Notifies the DataSource_CT that the client is ready to receive data requests.
// When a client becomes ready on the DataSource component, the callback functions
// registered by <f_EPTF_DataSource_registerReadyCallback> are called.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_sendReady(
in charstring pl_source,
in charstring pl_ptcName,
in EPTF_DataSource_CT pl_sourceCompRef := null)
runs on EPTF_DataSourceClient_CT {
if(not v_EPTF_DataSourceClient_connected) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot send Ready ",
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " to pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource"));
return;
}
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{clientReady:={pl_source, pl_ptcName}}, pl_sourceCompRef);
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_getData
//
// Purpose:
// To get the value of a given data
//
// Parameters:
// *out charstring pl_dataVarName* - this is the name of the variable
// that stores the values of the data on the local component
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in charstring pl_element* - the type of data
// *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {})
// The parameters are sorted lexicographically according to the paramNames
// *in* <EPTF_Var_SubscriptionMode> - pl_subscriptionMode - subscription mode: sampled or timeLine: buffered; realtime: non-buffered
// Default: tsp_EPTF_DataSource_subscriptionMode
// *in integer* - pl_refreshRate - the refresh rate for the subscription.
// default: tsp_EPTF_DataSource_refreshRate
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef to get the value from
// If not specified the data is requested from the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// integer - 0 if OK, nonzero in case of failure to show that the pl_dataVarName is not valid
//
// Detailed Comments:
// This function will make a request for the given data source and return the name of the
// variable that contains the value of the data.
//
// How it works:
// Sends a request to the main DataSource_CT component
// to request the EPTF Variable name for the given dataSource.
// It will automatically subscribe to the source variable.
// The subscription is done directly to the source PTC, there is no subscription
// performed by the DataSource_CT
//
// In case of error, the pl_dataVarName argument may contain a charstring with an error message.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_getData(
out charstring pl_dataVarName,
in charstring pl_source,
in charstring pl_ptcName := "",
in charstring pl_element,
in EPTF_DataSource_Params pl_params := {},
in EPTF_Var_SubscriptionMode pl_subscriptionMode := tsp_EPTF_DataSource_subscriptionMode,
in integer pl_refreshRate := tsp_EPTF_DataSource_refreshRate,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT return integer {
if(not v_EPTF_DataSourceClient_connected) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot get data ",
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " pl_element: ",pl_element," pl_params: ",pl_params, " from pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource"));
pl_dataVarName := "";
return -99;
}
f_EPTF_DataSource_sortParams(pl_params);
pl_dataVarName := "";
var integer vl_localDataVarId;
var EPTF_Var_CT vl_ownerCompRef;
var charstring vl_remoteDataVarName;
// check if already subscribed:
var charstring vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params);
var integer vl_dataValueId;
var integer vl_errorCode;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) {
if (vl_dataValueId==-1) {
// PTC name is not given, but should be specified
pl_dataVarName := "";
return 1;
}
vl_localDataVarId := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].localDataVarId;
pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId);
// check if var exists: it is needed because checkData does not create it, but stores it in the hashMap
// if var is not subscribed, subscribe is needed => no error if variable is not found
if(f_EPTF_Var_checkSubscriptionMode(vl_localDataVarId,pl_subscriptionMode)) {
return 0;
}
vl_remoteDataVarName := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].remoteDataVarName;
vl_ownerCompRef := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].ownerCompRef;
vl_errorCode := 0;
} else {
var integer vl_transactionId := f_EPTF_Semaphore_new();
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{getData:={
transactionId := vl_transactionId,
dataSource := pl_source,
ptcName := pl_ptcName,
dataElement := pl_element,
params := pl_params
}}, pl_sourceCompRef);
//wait for the result:
if (f_EPTF_Semaphore_waitForUnlock(vl_transactionId,tsp_EPTF_DataSourceClient_maxWaitTime)) {
// max wait time expired before response received:
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Communication error: No response received for getData message: ",vl_transactionId));
pl_dataVarName := "";
return -1;
}
// copy the values from the message database because it might be possible that they will be overwritten because
// the semaphore is released and there is a blocking statement before they are used:
vl_ownerCompRef := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValue.ownerCompRef;
vl_remoteDataVarName := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValue.dataVarName;
vl_errorCode := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValue.errorCode;
//set the variable name
// this will always be true if errorCode == 0:
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) {
vl_localDataVarId := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].localDataVarId;
pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId);
if(f_EPTF_Var_checkSubscriptionMode(vl_localDataVarId,pl_subscriptionMode)) {
return 0;
}
}
}
//subscribe to the source variable:
// if returned error code is 0 (no error) subscibe to the provider data variable:
if (vl_errorCode==0) {
// The presence of the source variable is not checked. It was done on the main dataSource component.
// If error code is 0, it will be there
f_EPTF_Var_resubscribeRemote(
vl_ownerCompRef,
vl_remoteDataVarName,
pl_subscriptionMode,
vl_localDataVarId,
pl_dataVarName,
pl_refreshRate
);
} else {
f_EPTF_DataSourceClient_warning(vl_remoteDataVarName); // warning message is received in the dataVarName
}
return vl_errorCode;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_getData_nonBlocking
//
// Purpose:
// To get the value of a given data in non-blocking way.
// The specified handler is called when the response arrives.
//
// Parameters:
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in charstring pl_element* - the type of data
// *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {})
// The parameters are sorted lexicographically according to the paramNames
// *in* <EPTF_DataSource_GetDataHandler> - pl_getDataHandler - the handler function (with user arguments) to call
// when response is received
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef to get the value from
// If not specified the data is requested from the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// integer - 0 if request is OK, nonzero if request is invalid. In both cases the handler will be called.
//
// Detailed Comments:
// Sends a request to the main DataSource_CT component
// to request the EPTF Variable name for the given dataSource.
// The given handler function is called when the response is available.
// A local variable is created which stores the current value of the dataSource,
// but this variable is not subscribed to the data owner.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_getData_nonBlocking(
in charstring pl_source,
in charstring pl_ptcName := "",
in charstring pl_element,
in EPTF_DataSource_Params pl_params := {},
in EPTF_DataSource_GetDataHandler pl_getDataHandler := cg_EPTF_DataSource_GetDataHandler_null,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_errorCode;
if(not v_EPTF_DataSourceClient_connected) {
vl_errorCode := -99;
var charstring vl_errorMsg := log2str(%definitionId&": Cannot get data ",
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " pl_element: ",pl_element," pl_params: ",pl_params, " from pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource");
f_EPTF_DataSourceClient_warning(vl_errorMsg);
// call handler:
if (pl_getDataHandler.getDataHandler!=null) {
pl_getDataHandler.getDataHandler.apply(
//request parameters:
pl_source := pl_source,
pl_ptcName := pl_ptcName, // response may fill this if it was ""
pl_element := pl_element,
pl_params := pl_params,
// reponse parameters:
pl_errorCode := vl_errorCode, // error code in the response
pl_remoteDataVarName := vl_errorMsg, // var name on the remote component. In case errorCode!=0: it contains the error message
pl_ownerCompRef := null, // reference to the remote component
pl_localDataVarId := -1, // var id on the local component (contains the current value, not subscribed to remote!)
pl_dataValue := {charstringVal:=vl_errorMsg}, // the value of the data
// user data
pl_userData := pl_getDataHandler.userData // user specific data given at the request
);
}
return vl_errorCode;
}
f_EPTF_DataSource_sortParams(pl_params);
// check if already subscribed:
var charstring vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params);
var integer vl_dataValueId;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) {
var EPTF_Var_CT vl_ownerCompRef;
var charstring vl_remoteDataVarName; // for nonzero error code it contains the error message
var integer vl_localDataVarId;
var EPTF_Var_DirectContent vl_dataValue;
if (vl_dataValueId==-1) {
// PTC name is not given, but should be specified
vl_errorCode := 1;
vl_remoteDataVarName := log2str(%definitionId&": Cannot get source component for dataSource ",pl_source, " and ptcName ",pl_ptcName,
": PTC name is not given, but should be specified since more than one PTC exist with the same source.");
vl_ownerCompRef := null;
vl_localDataVarId := -1;
vl_dataValue := {unknownVal:={omit}};
} else {
// pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId);
vl_errorCode := 0;
vl_remoteDataVarName := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].remoteDataVarName;
vl_ownerCompRef := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].ownerCompRef;
vl_localDataVarId := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].localDataVarId;
vl_dataValue := {unknownVal:={omit}};
if(vl_localDataVarId!=-1) {
f_EPTF_Var_getContent(vl_localDataVarId,vl_dataValue);
}
}
// call handler:
if (pl_getDataHandler.getDataHandler!=null) {
pl_getDataHandler.getDataHandler.apply(
//request parameters:
pl_source := pl_source,
pl_ptcName := pl_ptcName, // response may fill this if it was ""
pl_element := pl_element,
pl_params := pl_params,
// reponse parameters:
pl_errorCode := vl_errorCode, // error code in the response
pl_remoteDataVarName := vl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message
pl_ownerCompRef := vl_ownerCompRef, // reference to the remote component
pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!)
pl_dataValue := vl_dataValue, // the value of the data
// user data
pl_userData := pl_getDataHandler.userData // user specific data given at the request
);
}
return vl_errorCode;
} else {
//recalculate vl_dataValueIdStr with given PTCName:
vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params);
var integer vl_transactionId;
// check if there is a pending request:
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_pendingGetDataHash,vl_dataValueIdStr,vl_transactionId)) {
v_EPTF_DataSourceClient_GetDataHandler_DB[vl_transactionId] := v_EPTF_DataSourceClient_GetDataHandler_DB[vl_transactionId] & {pl_getDataHandler};
} else {
vl_transactionId := f_EPTF_Semaphore_new();
v_EPTF_DataSourceClient_GetDataHandler_DB[vl_transactionId] := {pl_getDataHandler};
//f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_pendingGetDataHash,vl_dataValueIdStr,vl_transactionId);
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{getData:={
transactionId := vl_transactionId,
dataSource := pl_source,
ptcName := pl_ptcName,
dataElement := pl_element,
params := pl_params
}}, pl_sourceCompRef);
}
vl_errorCode := 0;
}
return vl_errorCode;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_getDataValue
//
// Purpose:
// To get the value of a given data
//
// Parameters:
// *out* <EPTF_Var_DirectContent> *pl_dataValue* - this is the value of the data requested
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in charstring pl_element* - the type of data
// *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {})
// The parameters are sorted lexicographically according to the paramNames
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef to get the value from
// If not specified the data is requested from the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// integer - 0 if OK, nonzero in case of failure to show that the pl_dataVarName is not valid
//
// Detailed Comments:
// This function will make a request for the given data source and return the value of the data.
//
// How it works:
// The request is forwarded to the appropriate DataSourceClient which registered
// the source and ptc name. On the client the handler function registered by
// <f_EPTF_DataSourceClient_registerData> for the given pl_source and pl_ptcName is called.
// The pl_params are passed to it as additional arguments.
// The handler function returns a <EPTF_Var_DirectContent> value which is set in the pl_dataValue
// argument. The value will be returned by this function
// together with the error code returned by the handler function.
//
// In case of error, the pl_dataValue argument may contain a charstring with an error message.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_getDataValue(
out EPTF_Var_DirectContent pl_dataValue,
in charstring pl_source,
in charstring pl_ptcName := "",
in charstring pl_element,
in EPTF_DataSource_Params pl_params := {},
in EPTF_DataSource_Filter pl_filter := c_EPTF_DataSource_Filter_empty,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_errorCode;
if(not v_EPTF_DataSourceClient_connected) {
vl_errorCode := -99;
var charstring vl_errorMsg := log2str(%definitionId&": Cannot get data value ",
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " pl_element: ",pl_element," pl_params: ",pl_params, " from pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource");
f_EPTF_DataSourceClient_warning(vl_errorMsg);
pl_dataValue := {charstringVal := vl_errorMsg};
return vl_errorCode;
}
f_EPTF_DataSource_sortParams(pl_params);
var integer vl_transactionId := f_EPTF_Semaphore_new();
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{getDataValue:={
transactionId := vl_transactionId,
dataSource := pl_source,
ptcName := pl_ptcName,
dataElement := pl_element,
params := pl_params,
filter := pl_filter
}}, pl_sourceCompRef);
//wait for the result:
if (f_EPTF_Semaphore_waitForUnlock(vl_transactionId,tsp_EPTF_DataSourceClient_maxWaitTime)) {
// max wait time expired before response received:
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Communication error: No response received for getDataValue message: ",vl_transactionId));
pl_dataValue := {charstringVal := log2str(%definitionId&": Communication error: No response received for getDataValue message: ",vl_transactionId)};
return -1;
}
// copy the values from the message database because it might be possible that they will be overwritten because
// the semaphore is released and there is a blocking statement before they are used:
//vl_ownerCompRef := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValue.ownerCompRef;
pl_dataValue := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValueResponse.dataValue;
vl_errorCode := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValueResponse.errorCode;
return vl_errorCode;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_getDataValue_nonBlocking
//
// Purpose:
// To get the value of a given data in non-blocking way.
// The specified handler is called when the response arrives.
//
// Parameters:
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in charstring pl_element* - the type of data
// *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {})
// The parameters are sorted lexicographically according to the paramNames
// *in* <EPTF_DataSource_GetDataValueHandler> - pl_getDataValueHandler - the handler function (with user arguments) to call
// when response is received
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef to get the value from
// If not specified the data is requested from the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// integer - 0 if request is OK, nonzero in case of invalid request
//
// Detailed Comments:
// This function will make a request for the given data source and return the value of the data.
//
// How it works:
// The request is forwarded to the appropriate DataSourceClient which registered
// the source and ptc name. On the client the handler function registered by
// <f_EPTF_DataSourceClient_registerDataValue> for the given pl_source and pl_ptcName is called.
// The pl_params are passed to it as additional arguments.
// The handler function returns a value which is set in its pl_dataValue
// argument and an error code set in the pl_errorCode argument. These parameters are passed to the
// handler function given in pl_getDataValueHandler.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_getDataValue_nonBlocking(
in charstring pl_source,
in charstring pl_ptcName := "",
in charstring pl_element,
in EPTF_DataSource_Params pl_params := {},
in EPTF_DataSource_Filter pl_filter := c_EPTF_DataSource_Filter_empty,
in EPTF_DataSource_GetDataValueHandler pl_getDataValueHandler := cg_EPTF_DataSource_GetDataValueHandler_null,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_errorCode;
if(not v_EPTF_DataSourceClient_connected) {
vl_errorCode := -99;
var charstring vl_errorMsg := log2str(%definitionId&": Cannot get data value ",
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " pl_element: ",pl_element," pl_params: ",pl_params, " from pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource");
f_EPTF_DataSourceClient_warning(vl_errorMsg);
// call handler:
if (pl_getDataValueHandler.getDataValueHandler!=null) {
pl_getDataValueHandler.getDataValueHandler.apply(
// reponse parameters:
pl_errorCode := vl_errorCode, // error code in the response
pl_dataValue := {charstringVal:=vl_errorMsg}, // the value of the data
// user data
pl_userData := pl_getDataValueHandler.userData // user specific data given at the request
);
}
return vl_errorCode;
}
f_EPTF_DataSource_sortParams(pl_params);
var integer vl_transactionId := f_EPTF_Semaphore_new();
v_EPTF_DataSourceClient_GetDataValueHandler_DB[vl_transactionId] := pl_getDataValueHandler;
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{getDataValue:={
transactionId := vl_transactionId,
dataSource := pl_source,
ptcName := pl_ptcName,
dataElement := pl_element,
params := pl_params,
filter := pl_filter
}}, pl_sourceCompRef);
vl_errorCode := 0;
return vl_errorCode;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_setDataValue
//
// Purpose:
// To set the value of a given data
//
// Parameters:
// *inout* <EPTF_Var_DirectContent> *pl_dataValue* - this is the value of the data to be set
// after call, it will return the changed value that might be different after the function call
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in charstring pl_element* - the type of data
// *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {})
// The parameters are sorted lexicographically according to the paramNames
// *in* <EPTF_CharstringList> *pl_indexList* - in case of list-type values the elements of this parameter
// are the indexes in the list-type data for which the values should be set
// For elementary type values this argument is not used
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef to set the value on.
// If not specified the data is requested from the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// integer - 0 if OK, nonzero in case of failure to show that changing of the value was unsuccessful
//
// Detailed Comments:
// This function will make a request for the given data source and return the new value of the data.
//
// How it works:
// The request is forwarded to the appropriate DataSourceClient which registered
// the source and ptc name. On the client the handler function registered by
// <f_EPTF_DataSourceClient_registerSetDataValue> for the given pl_source and pl_ptcName is called.
// The pl_params are passed to it as additional arguments.
// The handler function returns a value which is set in the pl_dataValue
// argument and returns an error code to show if the change was successful or not.
// This function will return these values in its pl_dataValue argument and the return value.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_setDataValue(
inout EPTF_Var_DirectContent pl_dataValue,
in charstring pl_source,
in charstring pl_ptcName := "",
in charstring pl_element,
in EPTF_DataSource_Params pl_params := {},
in EPTF_IntegerList pl_indexList := {},
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_errorCode;
if(not v_EPTF_DataSourceClient_connected) {
vl_errorCode := -99;
var charstring vl_errorMsg := log2str(%definitionId&": Cannot set data value to ",pl_dataValue,
" for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " pl_element: ",pl_element," pl_params: ",pl_params, " from pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource");
f_EPTF_DataSourceClient_warning(vl_errorMsg);
pl_dataValue := {charstringVal := vl_errorMsg};
return vl_errorCode;
}
f_EPTF_DataSource_sortParams(pl_params);
var integer vl_transactionId := f_EPTF_Semaphore_new();
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{setDataValue:={
transactionId := vl_transactionId,
dataSource := pl_source,
ptcName := pl_ptcName,
dataElement := pl_element,
params := pl_params,
dataValue := pl_dataValue,
indexList := pl_indexList
}}, pl_sourceCompRef);
//wait for the result:
if (f_EPTF_Semaphore_waitForUnlock(vl_transactionId,tsp_EPTF_DataSourceClient_maxWaitTime)) {
// max wait time expired before response received:
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Communication error: No response received for setDataValue message: ",vl_transactionId));
pl_dataValue := {charstringVal := log2str(%definitionId&": Communication error: No response received for setDataValue message: ",vl_transactionId)};
return -1;
}
// copy the values from the message database because it might be possible that they will be overwritten because
// the semaphore is released and there is a blocking statement before they are used:
//vl_ownerCompRef := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValue.ownerCompRef;
pl_dataValue := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValueResponse.dataValue;
vl_errorCode := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValueResponse.errorCode;
return vl_errorCode;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_setDataValue_nonBlocking
//
// Purpose:
// To set the value of a given data in non-blocking way.
// The specified handler is called when the response arrives.
//
// Parameters:
// *in* <EPTF_Var_DirectContent> *pl_dataValue* - this is the value of the data requested
// after call, it will return the changed value that might be different
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in charstring pl_element* - the type of data
// *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {})
// The parameters are sorted lexicographically according to the paramNames
// *in* <EPTF_CharstringList> *pl_indexList* - in case of list-type values the elements of this parameter
// are the indexes in the list-type data for which the values should be set
// For elementary type values this argument is not used
// *in* <EPTF_DataSource_GetDataValueHandler> - pl_getDataValueHandler - the handler function (with user arguments) to call
// when response is received
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef to set the value on
// If not specified the data is modified on the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// integer - 0 if request is OK, nonzero in case of failure to show that the request is not valid
//
// Detailed Comments:
// This function will make a request for the given data source and return the value of the changed data.
//
// How it works:
// The request is forwarded to the appropriate DataSourceClient which registered
// the source and ptc name. On the client the handler function registered by
// <f_EPTF_DataSourceClient_registerSetDataValue> for the given pl_source and pl_ptcName is called.
// The pl_params are passed to it as additional arguments.
// The handler function returns the new value which is set in the pl_dataVarName
// argument together with the error code.
// These values are passed to the handler given in the pl_getDataValueHandler parameter.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_setDataValue_nonBlocking(
in EPTF_Var_DirectContent pl_dataValue,
in charstring pl_source,
in charstring pl_ptcName := "",
in charstring pl_element,
in EPTF_DataSource_Params pl_params := {},
in EPTF_IntegerList pl_indexList := {},
in EPTF_DataSource_GetDataValueHandler pl_getDataValueHandler := cg_EPTF_DataSource_GetDataValueHandler_null,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_errorCode;
if(not v_EPTF_DataSourceClient_connected) {
vl_errorCode := -99;
var charstring vl_errorMsg := log2str(%definitionId&": Cannot set data value ",pl_dataValue,
" for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " pl_element: ",pl_element," pl_params: ",pl_params, " from pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource");
f_EPTF_DataSourceClient_warning(vl_errorMsg);
// call handler:
if (pl_getDataValueHandler.getDataValueHandler!=null) {
pl_getDataValueHandler.getDataValueHandler.apply(
// reponse parameters:
pl_errorCode := vl_errorCode, // error code in the response
pl_dataValue := {charstringVal:=vl_errorMsg}, // the value of the data
// user data
pl_userData := pl_getDataValueHandler.userData // user specific data given at the request
);
}
return vl_errorCode;
}
f_EPTF_DataSource_sortParams(pl_params);
var integer vl_transactionId := f_EPTF_Semaphore_new();
v_EPTF_DataSourceClient_GetDataValueHandler_DB[vl_transactionId] := pl_getDataValueHandler;
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{setDataValue:={
transactionId := vl_transactionId,
dataSource := pl_source,
ptcName := pl_ptcName,
dataElement := pl_element,
params := pl_params,
dataValue := pl_dataValue,
indexList := pl_indexList
}}, pl_sourceCompRef);
vl_errorCode := 0;
return vl_errorCode;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_checkData
//
// Purpose:
// To check if the value of a given data exists. Returns the variable name
// of the dataSource.
//
// Parameters:
// *out charstring pl_dataVarName* - this is the name of the variable
// that stores the values of the data on the local component
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in charstring pl_element* - the type of data
// *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {})
// The parameters are sorted lexicographically according to the paramNames
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef to get the value from
// If not specified the data is requested from the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// integer - 0 if OK, nonzero if pl_dataVarName is not valid
//
// Detailed Comments:
// This function is almost the same as <f_EPTF_DataSourceClient_getData>, but
// does not subscribe to the provider variable and does not check the subscription.
// It only checks if the source variable is there on the source component.
// The returned variable might not exist even if the error code is zero.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_checkData(
out charstring pl_dataVarName,
in charstring pl_source,
in charstring pl_ptcName := "",
in charstring pl_element,
in EPTF_DataSource_Params pl_params := {},
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT return integer {
if(not v_EPTF_DataSourceClient_connected) {
return -99; // not connected
}
f_EPTF_DataSource_sortParams(pl_params);
pl_dataVarName := "";
// check if already subscribed:
var charstring vl_dataValueIdStr := pl_source&"@"&pl_ptcName&"."&pl_element&":"&log2str(pl_params);
var integer vl_dataValueId;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) {
if (vl_dataValueId==-1) {
// PTC name is not given, but should be specified
pl_dataVarName := "";
return 1;
}
var integer vl_localDataVarId := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].localDataVarId;
pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId);
return 0;
}
pl_dataVarName := "";
var integer vl_transactionId := f_EPTF_Semaphore_new();
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{getData:={
transactionId := vl_transactionId,
dataSource := pl_source,
ptcName := pl_ptcName,
dataElement := pl_element,
params := pl_params
}}, pl_sourceCompRef);
//wait for the result:
if (f_EPTF_Semaphore_waitForUnlock(vl_transactionId,tsp_EPTF_DataSourceClient_maxWaitTime)) {
// max wait time expired before response received:
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Communication error: No response received for getData message: ",vl_transactionId));
pl_dataVarName := "";
return -1;
}
// copy the values from the message database because it might be possible that they will be overwritten because
// the semaphore is released and there is a blocking statement before they are used:
var integer vl_errorCode := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValue.errorCode;
//var EPTF_DataSourceClient_CT vl_ownerCompRef := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValue.ownerCompRef;
var charstring vl_remoteDataVarName := v_EPTF_DataSourceClient_Msg_List[vl_transactionId].dataValue.dataVarName;
// this will always be true if errorCode == 0:
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) {
var integer vl_localDataVarId := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].localDataVarId;
pl_dataVarName := f_EPTF_Var_getName(vl_localDataVarId);
}
return vl_errorCode;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_enableUpdate
//
// Purpose:
// Enables updating of the data source variable, i.e.
// it subscribes the local variable to the source
//
// Parameters:
// *in charstring pl_localDataVarName* - this is the name of the local variable
// that stores the values of the data on the local component
//
// Return Value:
// integer - 0 if OK, nonzero if pl_localDataVarName is not valid
//
// Detailed Comments:
// This function can be called after a <f_EPTF_DataSourceClient_getData_nonBlocking>
// to subscribe the local datasource variable to the source variable, since that function does not do it.
// To cancel the update call <f_EPTF_DataSourceClient_disableUpdate>
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_enableUpdate(
in charstring pl_localDataVarName,
in EPTF_Var_SubscriptionMode pl_subscriptionMode := tsp_EPTF_DataSource_subscriptionMode,
in integer pl_refreshRate := tsp_EPTF_DataSource_refreshRate
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_dataValueId := f_EPTF_DataSourceClient_getDataValueId(pl_localDataVarName);
if (vl_dataValueId==-1) {
return 1; //error;
}
var integer vl_localDataVarId := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].localDataVarId;
if(f_EPTF_Var_checkSubscriptionMode(vl_localDataVarId,pl_subscriptionMode)) {
return 0; // already subscribed
}
var charstring vl_remoteDataVarName := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].remoteDataVarName;
var EPTF_Var_CT vl_ownerCompRef := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].ownerCompRef;
f_EPTF_Var_resubscribeRemote(
vl_ownerCompRef,
vl_remoteDataVarName,
pl_subscriptionMode,
vl_localDataVarId,
pl_localDataVarName,
pl_refreshRate
);
return 0;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_disableUpdate
//
// Purpose:
// Disabled updating of the data source variable, i.e.
// it unsubscribes the local variable from the source
//
// Parameters:
// *in charstring pl_localDataVarName* - this is the name of the local variable
// that stores the values of the data on the local component
//
// Return Value:
// integer - 0 if OK, nonzero if pl_localDataVarName is not valid
//
// Detailed Comments:
// This function can be called after a <f_EPTF_DataSourceClient_enableUpdate>
// to unsubscribe the local dataSource variable from the source variable.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_disableUpdate(
in charstring pl_localDataVarName
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_dataValueId := f_EPTF_DataSourceClient_getDataValueId(pl_localDataVarName);
if (vl_dataValueId==-1) {
return 1; //error;
}
var integer vl_localDataVarId := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].localDataVarId;
f_EPTF_Var_unsubscribe(vl_localDataVarId);
return 0;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_getDataValueId
//
// Purpose:
// Returns the ID of the data value
//
// Parameters:
// *in charstring pl_localDataVarName* - this is the name of the local variable
// that stores the values of the data on the local component
//
// Return Value:
// integer - the ID of the data value if OK, -1 if pl_dataVarName is not valid
//
// Detailed Comments:
// This function returns a unique ID for a datasource
// based on the local variable name that stores its value
// To get the local variable name for a datasource use <f_EPTF_DataSourceClient_checkData>
// or <f_EPTF_DataSourceClient_getData>.
///////////////////////////////////////////////////////////
private function f_EPTF_DataSourceClient_getDataValueId(
in charstring pl_localDataVarName
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_dataValueId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataValueHash,pl_localDataVarName,vl_dataValueId)) {
vl_dataValueId := -1;
}
return vl_dataValueId;
}
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_getCondition_nonBlocking
//
// Purpose:
// To get the value of a given condition in non-blocking way.
// The specified handler is called when the response arrives.
//
// Parameters:
// *in charstring pl_source* - the name of the dataSource 'feature'
// *in charstring pl_ptcName* - the name of the PTC
// (dataSource+ptcName should be a unigue id of the data). Default: "" (i.e. PTC name is ignored)
// *in charstring pl_method* - the type of condition
// *in* <EPTF_DataSource_Params> *pl_params* - additional parameters (default: {})
// The parameters are sorted lexicographically according to the paramNames
// *in* <EPTF_DataSource_GetConditionHandler> - pl_getConditionHandler - the handler function (with user arguments) to call
// when response is received
// *in <EPTF_DataSource_CT> pl_sourceCompRef* - the DataSource_CT componentRef to get the value from
// If not specified the data is requested from the only one
// DataSource component which is connected (= for which the <f_EPTF_DataSourceClient_connectToServer> was called)
//
// Return Value:
// integer - 0 if OK, nonzero if dataSource is not available. In both cases the handler will be called.
//
// Detailed Comments:
// Sends a request to the main DataSource_CT component
// to request the condition value from the given dataSource.
// The given handler function is called when the response is available.
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_getCondition_nonBlocking(
in charstring pl_source,
in charstring pl_ptcName := "",
in charstring pl_method,
in EPTF_DataSource_Params pl_params := {},
in EPTF_DataSource_GetConditionHandler pl_getConditionHandler := cg_EPTF_DataSource_GetDataHandler_null,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT return integer {
var integer vl_errorCode;
if(not v_EPTF_DataSourceClient_connected) {
vl_errorCode := -99;
var charstring vl_remoteDataVarName := log2str(%definitionId&": Cannot get condition ",
"for pl_source: ",pl_source," pl_ptcName: ",pl_ptcName, " pl_method: ",pl_method," pl_params: ",pl_params, " from pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource");
f_EPTF_DataSourceClient_warning(vl_remoteDataVarName);
// call handler:
if (pl_getConditionHandler.getDataHandler!=null) {
pl_getConditionHandler.getDataHandler.apply(
//request parameters:
pl_source := pl_source,
pl_ptcName := pl_ptcName, // response may fill this if it was ""
pl_element := pl_method,
pl_params := pl_params,
// reponse parameters:
pl_errorCode := vl_errorCode, // error code in the response
pl_remoteDataVarName := vl_remoteDataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message
pl_ownerCompRef := null, // reference to the remote component
pl_localDataVarId := -1, // var id on the local component (contains the current value, not subscribed to remote!)
pl_dataValue := {unknownVal:={omit}}, // the value of the data
// user data
pl_userData := pl_getConditionHandler.userData // user specific data given at the request
);
}
return vl_errorCode;
}
var integer vl_transactionId := f_EPTF_Semaphore_new();
v_EPTF_DataSourceClient_GetDataHandler_DB[vl_transactionId] := {pl_getConditionHandler};
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{getCondition:={
transactionId := vl_transactionId,
dataSource := pl_source,
ptcName := pl_ptcName,
method := pl_method,
params := pl_params
}}, pl_sourceCompRef);
vl_errorCode := 0;
return vl_errorCode;
}
////////////////////////////////////////////////////////////////////////////////
// Private functions:
////////////////////////////////////////////////////////////////////////////////
private function f_EPTF_DataSourceClient_cleanup_CT() runs on EPTF_DataSourceClient_CT {
if (not v_EPTF_DataSourceClient_initialized) {
return;
}
v_EPTF_DataSourceClient_initialized := false;
//disconnect(pl_sourceCompRef:EPTF_DataSourceIf,self:EPTF_DataSourceClientIf);
deactivate(v_DataSourceClient_handler);
v_DataSourceClient_handler := null;
if (v_EPTF_DataSourceClient_dataHandlerHash!=-1) {
v_EPTF_DataSourceClient_dataHandlerHash := -1;
f_EPTF_str2int_HashMap_Delete(c_EPTF_DataSourceClient_dataHandlerHashName);
}
if (v_EPTF_DataSourceClient_dataValueHash!=-1) {
v_EPTF_DataSourceClient_dataValueHash := -1;
f_EPTF_str2int_HashMap_Delete(c_EPTF_DataSourceClient_dataValueHashName);
}
if (v_EPTF_DataSourceClient_pendingGetDataHash!=-1) {
v_EPTF_DataSourceClient_pendingGetDataHash := -1;
f_EPTF_str2int_HashMap_Delete(c_EPTF_DataSourceClient_pendingGetDataHashName);
}
}
private function f_EPTF_DataSourceClient_handleGetData(
in EPTF_DataSource_Msg_GetData pl_getData,
in EPTF_DataSource_CT pl_sourceCompRef
) runs on EPTF_DataSourceClient_CT {
// find handler:
var charstring vl_handlerIdStr := pl_getData.dataSource&"@"&pl_getData.ptcName;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
// send errorCode to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{dataValue:={
pl_getData.transactionId,
pl_getData.dataSource,
pl_getData.ptcName,
pl_getData.dataElement,
pl_getData.params,
"Handler not registered",
{unknownVal:={omit}},
1,
self // it is the same as the sender of the message
}},pl_sourceCompRef);
return;
}
// calling handler: v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId]
var charstring vl_dataVarName;
var integer vl_errorCode := v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId].apply(
vl_dataVarName,
pl_getData.dataSource,
pl_getData.ptcName,
pl_getData.dataElement,
pl_getData.params
);
if (not isbound(vl_dataVarName)) {
vl_dataVarName := "";
}
var EPTF_Var_DirectContent vl_currentContent := {unknownVal:={omit}};
if (vl_errorCode==0) {
var integer vl_varIdx := f_EPTF_Var_getId(vl_dataVarName);
if (vl_varIdx==-1) {
// source variable does not exist:
// send errorCode to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{dataValue:={
pl_getData.transactionId,
pl_getData.dataSource,
pl_getData.ptcName,
pl_getData.dataElement,
pl_getData.params,
log2str("Source Variable ",vl_dataVarName," not found"),
{unknownVal:={omit}},
2,
self // it is the same as the sender of the message
}},pl_sourceCompRef);
return;
} else {
f_EPTF_Var_getContent(vl_varIdx,vl_currentContent);
}
}
// send vl_dataVarName to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{dataValue:={
pl_getData.transactionId,
pl_getData.dataSource,
pl_getData.ptcName,
pl_getData.dataElement,
pl_getData.params,
vl_dataVarName,
vl_currentContent,
vl_errorCode,
self // it is the same as the sender of the message
}},pl_sourceCompRef);
}
private function f_EPTF_DataSourceClient_getErrMsg4Get(
in EPTF_DataSource_Msg_GetDataValue pl_getDataValue,
in charstring pl_errMsg
) runs on EPTF_DataSourceClient_CT
return charstring {
return
log2str("f_EPTF_DataSourceClient_handleGetDataValue: Invalid iterator or externalData or parameter: ",
"\nSource: ", pl_getDataValue.dataSource,
"\nPTC : ", pl_getDataValue.ptcName ,
"\nElement Name : " , pl_getDataValue.dataElement,
"\nParams: " , pl_getDataValue.params)&"\nReason: "&pl_errMsg;
}
private function f_EPTF_DataSourceClient_getErrMsg4Set(
in EPTF_DataSource_Msg_SetDataValue pl_setDataValue,
in charstring pl_errMsg
) runs on EPTF_DataSourceClient_CT
return charstring {
return
log2str("f_EPTF_DataSourceClient_handleSetDataValue: Invalid iterator or externalData or parameter: ",
"\nSource: ", pl_setDataValue.dataSource,
"\nPTC : ", pl_setDataValue.ptcName ,
"\nElement Name : " , pl_setDataValue.dataElement,
"\nParams: " , pl_setDataValue.params,
"\nValue to Set: ", pl_setDataValue.dataValue,
"\nIndex List: ", pl_setDataValue.indexList)&"\nReason: "&pl_errMsg;
}
private function f_EPTF_DataSourceClient_handleBuiltInElements(
out EPTF_DataSource_Msg_DataValueResponse pl_dataValueResponse,
in EPTF_DataSource_Msg_GetDataValue pl_getDataValue
) runs on EPTF_DataSourceClient_CT {
var EPTF_DataSource_Msg_DataValueResponse vl_dataValueResponse := {
pl_getDataValue.transactionId,
{unknownVal:={omit}},
-54321
}
var charstring vl_dataElement := pl_getDataValue.dataElement;
select( vl_dataElement )
{
case(c_EPTF_DataSource_dataElement_sizeOf) {
vl_dataValueResponse.errorCode := 0;
var charstring vl_source;
var charstring vl_ptcName;
var charstring vl_element;
var EPTF_DataSource_Params vl_params;
vl_dataValueResponse.errorCode := f_EPTF_DataSource_getRequestPartsFromParams(
pl_getDataValue.params,
vl_source,
vl_ptcName,
vl_element,
vl_params
);
if (vl_dataValueResponse.errorCode == 0) {
var EPTF_DataSource_Msg_GetDataValue vl_getDataValue := {
pl_getDataValue.transactionId,
vl_source,
vl_ptcName,
vl_element,
vl_params
}
var EPTF_DataSource_Msg_DataValueResponse vl_dataValueResponseForOriginalRequest;
f_EPTF_DataSourceClient_handleClientElements(
vl_dataValueResponseForOriginalRequest,
vl_getDataValue
);
var EPTF_Var_DirectContent vl_dataValue := vl_dataValueResponseForOriginalRequest.dataValue;
if (vl_dataValueResponseForOriginalRequest.errorCode == 0) {
var integer vl_size := f_EPTF_DataSource_getSizeOfDataValue(vl_dataValue);
vl_dataValueResponse.dataValue := {intVal := vl_size};
} else {
// could not get the element
vl_dataValueResponse.errorCode := vl_dataValueResponseForOriginalRequest.errorCode;
var charstring vl_msg := "Could not determine the size of the dataelement";
if (ischosen(vl_dataValue.charstringVal)) {
vl_msg := vl_msg & ": " & vl_dataValue.charstringVal;
}
vl_dataValueResponse.dataValue := {charstringVal := vl_msg};
}
} else {
// wrong params
var charstring vl_msg := "Could not determine the size of the dataelement, invalid parameters: " & log2str(pl_getDataValue.params);
vl_dataValueResponse.dataValue := {charstringVal := vl_msg};
}
}
case(c_EPTF_DataSource_dataElement_isWritable) {
vl_dataValueResponse.errorCode := 0;
// TODO check if element is writable
vl_dataValueResponse.dataValue := {boolVal := false};
var charstring vl_source;
var charstring vl_ptcName;
var charstring vl_element;
var EPTF_DataSource_Params vl_params;
vl_dataValueResponse.errorCode := f_EPTF_DataSource_getRequestPartsFromParams(
pl_getDataValue.params,
vl_source,
vl_ptcName,
vl_element,
vl_params
);
if (vl_dataValueResponse.errorCode == 0) {
var charstring vl_handlerIdStr := vl_source&"@"&vl_ptcName;
var charstring vl_dataValueHandlerIdStr := "DVH_"&vl_handlerIdStr;
var integer vl_handlerId;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash, vl_dataValueHandlerIdStr, vl_handlerId)) {
vl_dataValueResponse.errorCode := v_fcb_EPTF_DataSourceClient_dataValueHandler_List[vl_handlerId].apply(
vl_dataValueResponse.dataValue,
vl_source,
pl_getDataValue.ptcName,
c_EPTF_DataSource_dataElement_isWritable, //pl_getDataValue.dataElement
pl_getDataValue.params
);
}
// try to find getData handler:
if (vl_dataValueResponse.errorCode != 0 and f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
// calling handler: v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId]
var charstring vl_dataVarName;
vl_dataValueResponse.errorCode := v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId].apply(
vl_dataVarName,
vl_source,
vl_ptcName,
vl_element,
vl_params
);
if (not isbound(vl_dataVarName)) {
vl_dataVarName := "";
}
if (vl_dataValueResponse.errorCode==0) {
// read value from the variable:
var integer vl_varIdx := f_EPTF_Var_getId(vl_dataVarName);
if (vl_varIdx==-1) {
// source variable does not exist:
// set error message and error code:
vl_dataValueResponse.dataValue := {charstringVal := log2str("Source Variable ",vl_dataVarName," not found")};
vl_dataValueResponse.errorCode := 2; // error code
} else {
// get current value from the variable:
vl_dataValueResponse.dataValue := {boolVal := f_EPTF_Var_getSubsCanAdjust(vl_varIdx)};
}
} else {
// append current error messages together:
if (not isbound(vl_dataVarName)) {
vl_dataVarName := "";
}
if (isbound(vl_dataValueResponse.dataValue) and ischosen(vl_dataValueResponse.dataValue.charstringVal)) {
if (vl_dataVarName=="") {
vl_dataVarName := vl_dataValueResponse.dataValue.charstringVal;
} else {
vl_dataVarName := vl_dataValueResponse.dataValue.charstringVal&" or "&vl_dataVarName;
}
} else if (vl_dataVarName == "") {
vl_dataVarName := "Unknown error";
}
vl_dataValueResponse.dataValue := {charstringVal := vl_dataVarName};
}
}
} else {
// wrong params
var charstring vl_msg := "Could not determine whether the dataelement is writable, invalid parameters: " & log2str(pl_getDataValue.params);
vl_dataValueResponse.dataValue := {charstringVal := vl_msg};
}
}
case else {
// TODO error handling?
vl_dataValueResponse.dataValue := {charstringVal := "Unknown error"};
vl_dataValueResponse.errorCode := -10;
}
}
pl_dataValueResponse := vl_dataValueResponse;
}
private function f_EPTF_DataSourceClient_handleClientElements(
out EPTF_DataSource_Msg_DataValueResponse pl_dataValueResponse,
in EPTF_DataSource_Msg_GetDataValue pl_getDataValue
) runs on EPTF_DataSourceClient_CT {
var EPTF_DataSource_Msg_DataValueResponse vl_dataValueResponse := {
pl_getDataValue.transactionId,
{unknownVal:={omit}},
-54321
}
// find handler:
var charstring vl_handlerIdStr := pl_getDataValue.dataSource&"@"&pl_getDataValue.ptcName;
var charstring vl_valueHandlerIdStr := "DVH_"&vl_handlerIdStr;
var integer vl_handlerId := -1;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_valueHandlerIdStr,vl_handlerId)) {
// calling handler: v_fcb_EPTF_DataSourceClient_dataValueHandler_List[vl_handlerId]
vl_dataValueResponse.errorCode := v_fcb_EPTF_DataSourceClient_dataValueHandler_List[vl_handlerId].apply(
vl_dataValueResponse.dataValue,
pl_getDataValue.dataSource,
pl_getDataValue.ptcName,
pl_getDataValue.dataElement,
pl_getDataValue.params
);
}
if (vl_dataValueResponse.errorCode != 0) {
// try to find condition handler:
vl_handlerIdStr := pl_getDataValue.dataSource&"@"&pl_getDataValue.ptcName&"/"&pl_getDataValue.dataElement;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
// calling handler: v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId]
var boolean vl_conditionValue;
vl_dataValueResponse.errorCode := v_fcb_EPTF_DataSourceClient_conditionHandler_List[vl_handlerId].apply(
vl_conditionValue,
pl_getDataValue.dataSource,
pl_getDataValue.ptcName,
pl_getDataValue.dataElement,
pl_getDataValue.params
);
if (not isbound(vl_conditionValue)) {
vl_conditionValue := false;
}
if (vl_dataValueResponse.errorCode==0) {
vl_dataValueResponse.dataValue := {boolVal := vl_conditionValue};
} else {
var charstring vl_errorMsg := log2str("Invalid parameters for condition: ", pl_getDataValue.dataElement);
// append error messages together:
if (isbound(vl_dataValueResponse.dataValue) and ischosen(vl_dataValueResponse.dataValue.charstringVal)) {
vl_errorMsg := vl_dataValueResponse.dataValue.charstringVal&" or "&vl_errorMsg;
}
vl_dataValueResponse.dataValue := {charstringVal := vl_errorMsg};
}
}
}
if (vl_dataValueResponse.errorCode != 0) {
// try to find getData handler:
vl_handlerIdStr := pl_getDataValue.dataSource&"@"&pl_getDataValue.ptcName;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
// calling handler: v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId]
var charstring vl_dataVarName;
vl_dataValueResponse.errorCode := v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId].apply(
vl_dataVarName,
pl_getDataValue.dataSource,
pl_getDataValue.ptcName,
pl_getDataValue.dataElement,
pl_getDataValue.params
);
if (not isbound(vl_dataVarName)) {
vl_dataVarName := "";
}
if (vl_dataValueResponse.errorCode==0) {
// read value from the variable:
var integer vl_varIdx := f_EPTF_Var_getId(vl_dataVarName);
if (vl_varIdx==-1) {
// source variable does not exist:
// set error message and error code:
vl_dataValueResponse.dataValue := {charstringVal := log2str("Source Variable ",vl_dataVarName," not found")};
vl_dataValueResponse.errorCode := 2; // error code
} else {
// get current value from the variable:
f_EPTF_Var_getContent(vl_varIdx,vl_dataValueResponse.dataValue);
}
} else {
// append current error messages together:
if (not isbound(vl_dataVarName)) {
vl_dataVarName := "";
}
if (isbound(vl_dataValueResponse.dataValue) and ischosen(vl_dataValueResponse.dataValue.charstringVal)) {
if (vl_dataVarName=="") {
vl_dataVarName := vl_dataValueResponse.dataValue.charstringVal;
} else {
vl_dataVarName := vl_dataValueResponse.dataValue.charstringVal&" or "&vl_dataVarName;
}
} else if (vl_dataVarName == "") {
vl_dataVarName := "Unknown error";
}
vl_dataValueResponse.dataValue := {charstringVal := vl_dataVarName};
}
}
}
// if error code is the default (= getData, value handler and condition handler was not found):
if (vl_dataValueResponse.errorCode == -54321) {
// set errorCode to the DataSource_CT:
vl_dataValueResponse.dataValue := {charstringVal := "Handler not registered"};
vl_dataValueResponse.errorCode := 1; // error code
}
if (vl_dataValueResponse.errorCode!=0) {
if(not isbound(vl_dataValueResponse.dataValue)) {
vl_dataValueResponse.dataValue := {charstringVal:=f_EPTF_DataSourceClient_getErrMsg4Get(pl_getDataValue, "Unknown error")};
} else {
if (ischosen(vl_dataValueResponse.dataValue.charstringVal)){
vl_dataValueResponse.dataValue := {charstringVal:=f_EPTF_DataSourceClient_getErrMsg4Get(pl_getDataValue, vl_dataValueResponse.dataValue.charstringVal)};
} else {
vl_dataValueResponse.dataValue := {charstringVal:=f_EPTF_DataSourceClient_getErrMsg4Get(pl_getDataValue, log2str(vl_dataValueResponse.dataValue))};
}
}
}
pl_dataValueResponse := vl_dataValueResponse;
}
private function f_EPTF_DataSourceClient_handleGetDataValue(
in EPTF_DataSource_Msg_GetDataValue pl_getDataValue,
in EPTF_DataSource_CT pl_sourceCompRef
) runs on EPTF_DataSourceClient_CT {
var EPTF_DataSource_Msg_DataValueResponse vl_dataValueResponse;
if (pl_getDataValue.dataSource == "DataSource") {
f_EPTF_DataSourceClient_handleBuiltInElements(
vl_dataValueResponse,
pl_getDataValue
)
} else {
f_EPTF_DataSourceClient_handleClientElements(
vl_dataValueResponse,
pl_getDataValue
)
}
if (ispresent(pl_getDataValue.filter) and ispresent(pl_getDataValue.filter.rangeFilter)) {
f_EPTF_DataSourceClient_applyRangeFilter(vl_dataValueResponse, pl_getDataValue.filter.rangeFilter);
}
// send response to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{dataValueResponse:=vl_dataValueResponse},pl_sourceCompRef);
}
private function f_EPTF_DataSourceClient_applyRangeFilter(
inout EPTF_DataSource_Msg_DataValueResponse pl_dataValueResponse,
in EPTF_DataSource_RangeFilter pl_rangeFilter
) {
if (ischosen(pl_dataValueResponse.dataValue.integerlistVal)) {
var EPTF_IntegerList vl_list := pl_dataValueResponse.dataValue.integerlistVal;
// find the first index
var integer vl_from;
if (ispresent(pl_rangeFilter.offset)) {
vl_from := pl_rangeFilter.offset;
if (vl_from < 0) {
vl_from := 0;
} else if (vl_from >= sizeof(vl_list)) {
pl_dataValueResponse.dataValue.integerlistVal := {};
return;
}
} else {
vl_from := 0;
}
// find the number of elements
var integer vl_count;
if (ispresent(pl_rangeFilter.count) and pl_rangeFilter.count >= 0 and vl_from + pl_rangeFilter.count < sizeof(vl_list)) {
vl_count := pl_rangeFilter.count;
} else {
vl_count := sizeof(vl_list) - vl_from;
}
pl_dataValueResponse.dataValue.integerlistVal := substr(vl_list, vl_from, vl_count);
} else if (ischosen(pl_dataValueResponse.dataValue.charstringlistVal)) {
var EPTF_CharstringList vl_list := pl_dataValueResponse.dataValue.charstringlistVal;
// find the first index
var integer vl_from;
if (ispresent(pl_rangeFilter.offset)) {
vl_from := pl_rangeFilter.offset;
if (vl_from < 0) {
vl_from := 0;
} else if (vl_from >= sizeof(vl_list)) {
pl_dataValueResponse.dataValue.charstringlistVal := {};
return;
}
} else {
vl_from := 0;
}
// find the number of elements
var integer vl_count;
if (ispresent(pl_rangeFilter.count) and pl_rangeFilter.count >= 0 and vl_from + pl_rangeFilter.count < sizeof(vl_list)) {
vl_count := pl_rangeFilter.count;
} else {
vl_count := sizeof(vl_list) - vl_from;
}
pl_dataValueResponse.dataValue.charstringlistVal := substr(vl_list, vl_from, vl_count);
} else if (ischosen(pl_dataValueResponse.dataValue.floatlistVal)) {
var EPTF_FloatList vl_list := pl_dataValueResponse.dataValue.floatlistVal;
// find the first index
var integer vl_from;
if (ispresent(pl_rangeFilter.offset)) {
vl_from := pl_rangeFilter.offset;
if (vl_from < 0) {
vl_from := 0;
} else if (vl_from >= sizeof(vl_list)) {
pl_dataValueResponse.dataValue.floatlistVal := {};
return;
}
} else {
vl_from := 0;
}
// find the number of elements
var integer vl_count;
if (ispresent(pl_rangeFilter.count) and pl_rangeFilter.count >= 0 and vl_from + pl_rangeFilter.count < sizeof(vl_list)) {
vl_count := pl_rangeFilter.count;
} else {
vl_count := sizeof(vl_list) - vl_from;
}
pl_dataValueResponse.dataValue.floatlistVal := substr(vl_list, vl_from, vl_count);
} else {
// we do not filter single elements
}
}
private function f_EPTF_DataSourceClient_handleSetDataValue(
in EPTF_DataSource_Msg_SetDataValue pl_setDataValue,
in EPTF_DataSource_CT pl_sourceCompRef
) runs on EPTF_DataSourceClient_CT {
var EPTF_DataSource_Msg_DataValueResponse vl_dataValueResponse := {
pl_setDataValue.transactionId,
pl_setDataValue.dataValue,
-54321
}
// find handler:
var charstring vl_handlerIdStr := pl_setDataValue.dataSource&"@"&pl_setDataValue.ptcName;
var charstring vl_valueHandlerIdStr := "SDVH_"&vl_handlerIdStr;
var integer vl_handlerId := -1;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_valueHandlerIdStr,vl_handlerId)) {
// calling handler: v_fcb_EPTF_DataSourceClient_setDataValueHandler_List[vl_handlerId]
vl_dataValueResponse.errorCode := v_fcb_EPTF_DataSourceClient_setDataValueHandler_List[vl_handlerId].apply(
vl_dataValueResponse.dataValue,
pl_setDataValue.dataSource,
pl_setDataValue.ptcName,
pl_setDataValue.dataElement,
pl_setDataValue.params,
pl_setDataValue.indexList
);
}
if (vl_dataValueResponse.errorCode < 0) {
// try to find getData handler:
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
// calling handler: v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId]
var charstring vl_dataVarName;
vl_dataValueResponse.errorCode := v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId].apply(
vl_dataVarName,
pl_setDataValue.dataSource,
pl_setDataValue.ptcName,
pl_setDataValue.dataElement,
pl_setDataValue.params
);
if (not isbound(vl_dataVarName)) {
vl_dataVarName := "";
}
if (vl_dataValueResponse.errorCode==0) {
// set value to the variable:
var integer vl_varIdx := f_EPTF_Var_getId(vl_dataVarName);
if (vl_varIdx==-1) {
// source variable does not exist:
// set error message and error code:
vl_dataValueResponse.dataValue := {charstringVal := log2str("Source Variable ",vl_dataVarName," not found")};
vl_dataValueResponse.errorCode := 2; // error code
} else {
// set current value to variable:
vl_dataValueResponse.dataValue := pl_setDataValue.dataValue; // restore original value
var EPTF_Var_DirectContent vl_valueToSet := vl_dataValueResponse.dataValue; //value to set variable (if the var is list different value is set and send)
if (pl_setDataValue.indexList != {}) {
//get current content
var EPTF_Var_DirectContent vl_listContent;
f_EPTF_Var_getContent(vl_varIdx, vl_listContent);
//update list by new values in elements listed in indexList
vl_dataValueResponse.errorCode := f_EPTF_DataSourceClient_setListValue (
pl_indexList := pl_setDataValue.indexList,
pl_newValue := pl_setDataValue.dataValue,
pl_listContent := vl_listContent
);
if (vl_dataValueResponse.errorCode != 0) {
vl_dataValueResponse.dataValue := {charstringVal := log2str("Error in using indexList: ", pl_setDataValue.indexList, ". New value to be set ", pl_setDataValue.dataValue,
" is inconsistent with the indexList or the current value of the data")};
} else {
vl_valueToSet := vl_listContent;
}
}
if (vl_dataValueResponse.errorCode == 0) {
if(false == f_EPTF_Var_adjustContent_Blocking(vl_varIdx, vl_valueToSet)) {
// source variable is read-only
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot set data ",pl_setDataValue,
": Source Variable ",vl_dataVarName," is read-only or value is not allowed"));
// set error message and error code:
vl_dataValueResponse.dataValue := {charstringVal := log2str("Source Variable ",vl_dataVarName," is read-only or value is not allowed")};
vl_dataValueResponse.errorCode := 3; // error code
}
}
}
} else {
if (vl_dataVarName=="") {
vl_dataVarName := "Unknown error";
}
vl_dataValueResponse.dataValue := {charstringVal := vl_dataVarName};
}
} else {
// if error code is the default (= getData and value handler was not found):
if (vl_dataValueResponse.errorCode == -54321) {
// set errorCode to the DataSource_CT:
vl_dataValueResponse.dataValue := {charstringVal := "Handler not registered"};
vl_dataValueResponse.errorCode := 1; // error code
}
}
}
if (vl_dataValueResponse.errorCode!=0) {
if(not isbound(vl_dataValueResponse.dataValue)) {
vl_dataValueResponse.dataValue := {charstringVal:=f_EPTF_DataSourceClient_getErrMsg4Set(pl_setDataValue, "Unknown error")};
} else {
if (ischosen(vl_dataValueResponse.dataValue.charstringVal)){
vl_dataValueResponse.dataValue := {charstringVal:=f_EPTF_DataSourceClient_getErrMsg4Set(pl_setDataValue, vl_dataValueResponse.dataValue.charstringVal)};
} else {
vl_dataValueResponse.dataValue := {charstringVal:=f_EPTF_DataSourceClient_getErrMsg4Set(pl_setDataValue, log2str(vl_dataValueResponse.dataValue))};
}
}
}
// send response to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{dataValueResponse:=vl_dataValueResponse},pl_sourceCompRef);
}
private function f_EPTF_DataSourceClient_setListValue (
in EPTF_IntegerList pl_indexList,
in EPTF_Var_DirectContent pl_newValue,
inout EPTF_Var_DirectContent pl_listContent
) runs on EPTF_DataSourceClient_CT
return integer {
//check if indexes are not negative
for (var integer vl_i := 0; vl_i < sizeof(pl_indexList); vl_i := vl_i + 1) {
if (pl_indexList[vl_i] < 0) {
return 10;
}
}
//handle integerList
if (ischosen(pl_listContent.integerlistVal) and ischosen(pl_newValue.integerlistVal)) {
if (sizeof(pl_indexList) != sizeof(pl_newValue.integerlistVal)) {
return 11;
}
for (var integer vl_i := 0; vl_i < sizeof(pl_indexList); vl_i := vl_i + 1) {
var integer vl_index := pl_indexList[vl_i];
if (sizeof(pl_listContent.integerlistVal) <= vl_index) {
return 12;
}
pl_listContent.integerlistVal[vl_index] := pl_newValue.integerlistVal[vl_i];
}
return 0;
}
//handle charstringList
if (ischosen(pl_listContent.charstringlistVal) and ischosen(pl_newValue.charstringlistVal)) {
if (sizeof(pl_indexList) != sizeof(pl_newValue.charstringlistVal)) {
return 11;
}
for (var integer vl_i := 0; vl_i < sizeof(pl_indexList); vl_i := vl_i + 1) {
var integer vl_index := pl_indexList[vl_i];
if (sizeof(pl_listContent.charstringlistVal) <= vl_index) {
return 12;
}
pl_listContent.charstringlistVal[vl_index] := pl_newValue.charstringlistVal[vl_i];
}
return 0;
}
//handle floatList
if (ischosen(pl_listContent.floatlistVal) and ischosen(pl_newValue.floatlistVal)) {
if (sizeof(pl_indexList) != sizeof(pl_newValue.floatlistVal)) {
return 11;
}
for (var integer vl_i := 0; vl_i < sizeof(pl_indexList); vl_i := vl_i + 1) {
var integer vl_index := pl_indexList[vl_i];
if (sizeof(pl_listContent.floatlistVal) <= vl_index) {
return 12;
}
pl_listContent.floatlistVal[vl_index] := pl_newValue.floatlistVal[vl_i];
}
return 0;
}
return 13;
}
private function f_EPTF_DataSourceClient_handleGetList(
in EPTF_DataSource_Msg_List pl_getList,
in EPTF_DataSource_CT pl_sourceCompRef
) runs on EPTF_DataSourceClient_CT {
var EPTF_DataSource_Msg_List vl_valueList := {};
for(var integer i:=0; i<sizeof(pl_getList); i:=i+1) {
if (ischosen(pl_getList[i].getData)) {
// find handler:
var charstring vl_handlerIdStr := pl_getList[i].getData.dataSource&"@"&pl_getList[i].getData.ptcName;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot handle data ",pl_getList[i].getData,
": Handler not registered"));
// send errorCode to the DataSource_CT:
vl_valueList[i].dataValue := {
pl_getList[i].getData.transactionId,
pl_getList[i].getData.dataSource,
pl_getList[i].getData.ptcName,
pl_getList[i].getData.dataElement,
pl_getList[i].getData.params,
"Handler not registered",
{unknownVal:={omit}},
1,
self // it is the same as the sender of the message
}
continue;
}
// calling handler: v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId]
var charstring vl_dataVarName;
var integer vl_errorCode := v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId].apply(
vl_dataVarName,
pl_getList[i].getData.dataSource,
pl_getList[i].getData.ptcName,
pl_getList[i].getData.dataElement,
pl_getList[i].getData.params
);
if (not isbound(vl_dataVarName)) {
vl_dataVarName := "";
}
var EPTF_Var_DirectContent vl_currentContent := {unknownVal:={omit}};
if (vl_errorCode==0) {
var integer vl_varIdx := f_EPTF_Var_getId(vl_dataVarName);
if (vl_varIdx==-1) {
// source variable does not exist:
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot handle data ",pl_getList[i].getData,
": Source Variable ",vl_dataVarName," not found"));
// send errorCode to the DataSource_CT:
vl_valueList[i].dataValue := {
pl_getList[i].getData.transactionId,
pl_getList[i].getData.dataSource,
pl_getList[i].getData.ptcName,
pl_getList[i].getData.dataElement,
pl_getList[i].getData.params,
log2str("Source Variable ",vl_dataVarName," not found"),
{unknownVal:={omit}},
2,
self // it is the same as the sender of the message
}
continue;
} else {
f_EPTF_Var_getContent(vl_varIdx,vl_currentContent);
}
}
// send vl_dataVarName to the DataSource_CT:
vl_valueList[i].dataValue := {
pl_getList[i].getData.transactionId,
pl_getList[i].getData.dataSource,
pl_getList[i].getData.ptcName,
pl_getList[i].getData.dataElement,
pl_getList[i].getData.params,
vl_dataVarName,
vl_currentContent,
vl_errorCode,
self // it is the same as the sender of the message
}
} else if (ischosen(pl_getList[i].getCondition)) {
// find handler:
var charstring vl_handlerIdStr := pl_getList[i].getCondition.dataSource&"@"&pl_getList[i].getCondition.ptcName&"/"&pl_getList[i].getCondition.method;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot handle condition ",pl_getList[i].getCondition,
": Handler not registered"));
// send error code to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{conditionValue:={
pl_getList[i].getCondition.transactionId,
pl_getList[i].getCondition.dataSource,
pl_getList[i].getCondition.ptcName,
pl_getList[i].getCondition.method,
pl_getList[i].getCondition.params,
false,
1
}},pl_sourceCompRef);
return;
}
// calling handler: v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId]
var boolean vl_conditionValue;
var integer vl_errorCode := v_fcb_EPTF_DataSourceClient_conditionHandler_List[vl_handlerId].apply(
vl_conditionValue,
pl_getList[i].getCondition.dataSource,
pl_getList[i].getCondition.ptcName,
pl_getList[i].getCondition.method,
pl_getList[i].getCondition.params
);
if (not isbound(vl_conditionValue)) {
vl_conditionValue := false;
}
// send vl_dataVarName to the DataSource_CT:
vl_valueList[i].conditionValue := {
pl_getList[i].getCondition.transactionId,
pl_getList[i].getCondition.dataSource,
pl_getList[i].getCondition.ptcName,
pl_getList[i].getCondition.method,
pl_getList[i].getCondition.params,
vl_conditionValue,
vl_errorCode
}
}
}
// send valueList to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{valueList:=vl_valueList},pl_sourceCompRef);
}
private function f_EPTF_DataSourceClient_handleGetCondition(
in EPTF_DataSource_Msg_GetCondition pl_getCondition,
in EPTF_DataSource_CT pl_sourceCompRef
) runs on EPTF_DataSourceClient_CT {
// find handler:
var charstring vl_handlerIdStr := pl_getCondition.dataSource&"@"&pl_getCondition.ptcName&"/"&pl_getCondition.method;
var integer vl_handlerId := -1;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataHandlerHash,vl_handlerIdStr,vl_handlerId)) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot handle condition ",pl_getCondition,
": Handler not registered"));
// send error code to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{conditionValue:={
pl_getCondition.transactionId,
pl_getCondition.dataSource,
pl_getCondition.ptcName,
pl_getCondition.method,
pl_getCondition.params,
false,
1
}},pl_sourceCompRef);
return;
}
// calling handler: v_fcb_EPTF_DataSourceClient_dataHandler_List[vl_handlerId]
var boolean vl_conditionValue;
var integer vl_errorCode := v_fcb_EPTF_DataSourceClient_conditionHandler_List[vl_handlerId].apply(
vl_conditionValue,
pl_getCondition.dataSource,
pl_getCondition.ptcName,
pl_getCondition.method,
pl_getCondition.params
);
if (not isbound(vl_conditionValue)) {
vl_conditionValue := false;
}
// send vl_conditionValue to the DataSource_CT:
f_EPTF_DataSourceClient_sendMsg(EPTF_DataSource_Msg:{conditionValue:={
pl_getCondition.transactionId,
pl_getCondition.dataSource,
pl_getCondition.ptcName,
pl_getCondition.method,
pl_getCondition.params,
vl_conditionValue,
vl_errorCode
}},pl_sourceCompRef);
}
private function f_EPTF_DataSourceClient_handleDataValue(
in EPTF_DataSource_Msg_DataValue pl_dataValue,
in EPTF_DataSource_CT pl_sourceCompRef
) runs on EPTF_DataSourceClient_CT {
var integer vl_localDataVarId := -1;
v_EPTF_DataSourceClient_Msg_List[pl_dataValue.transactionId] := {dataValue := pl_dataValue};
// if returned error code is non-0, update the error message:
if (pl_dataValue.errorCode!=0) {
if (not ischosen(pl_dataValue.dataValue.charstringVal)) {
if (ispresent(pl_dataValue.dataVarName) and pl_dataValue.dataVarName != "") {
pl_dataValue.dataValue := {charstringVal := pl_dataValue.dataVarName}; // error message was not present => set it to the string value of provided value
} else {
pl_dataValue.dataValue := {charstringVal := "Error info: "&ttcn2string(pl_dataValue.dataValue)}; // error message was not present => set it to the string value of provided value
//append general text:
pl_dataValue.dataValue.charstringVal := log2str(%definitionId&": Invalid iterator or externalData or parameter: ",
"\nSource: ",pl_dataValue.dataSource,
"\nPTC : ",pl_dataValue.ptcName ,
"\nElement Name : " ,pl_dataValue.dataElement,
"\nParams: " , pl_dataValue.params)&
"\nReason: "&pl_dataValue.dataValue.charstringVal;
}
}
f_EPTF_DataSourceClient_warning(pl_dataValue.dataValue.charstringVal&"\nError code: "&int2str(pl_dataValue.errorCode));
}
// store the returned varname in a hashmap:
var charstring vl_dataValueIdStr := pl_dataValue.dataSource&"@"&pl_dataValue.ptcName&
"."&pl_dataValue.dataElement&":"&log2str(pl_dataValue.params);
if(pl_dataValue.errorCode==0 and ispresent(pl_dataValue.dataVarName)) {
var charstring vl_dataValueIdStr_noPTCName := pl_dataValue.dataSource&"@."&pl_dataValue.dataElement&":"&log2str(pl_dataValue.params);
var integer vl_dataValueId;
if (not f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr,vl_dataValueId)) {
var charstring vl_remoteDataVarName := pl_dataValue.dataVarName;
var charstring vl_localVarName := "EPTF_DataSourceClient_"&vl_remoteDataVarName&"."&vl_dataValueIdStr;
//create local variable with the value in the message:
vl_localDataVarId := f_EPTF_Var_newVar(vl_localVarName,pl_dataValue.dataValue);
vl_dataValueId := sizeof(v_EPTF_DataSourceClient_dataValue_List);
// store new datasource data:
v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId] := {
pl_dataValue.dataVarName,
pl_dataValue.ownerCompRef,
vl_localDataVarId
};
// to be able to search by vl_dataValueIdStr:
f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr,vl_dataValueId);
// to be able to search by vl_localVarName:
f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_dataValueHash,vl_localVarName,vl_dataValueId);
// to be able to search by vl_dataValueIdStr_noPTCName:
f_EPTF_str2int_HashMap_Insert(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr_noPTCName,vl_dataValueId);
} else {
vl_localDataVarId := v_EPTF_DataSourceClient_dataValue_List[vl_dataValueId].localDataVarId;
// Update hashMap entry for NoPTCName:
// Only insert with noPTCName if it was not already added.
// Otherwise insert invalid data to sign that the PTC name should be specified
var integer vl_noPTCCheck := -1;
if (f_EPTF_str2int_HashMap_Find(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr_noPTCName,vl_noPTCCheck)) {
// if valid entry found:
if (vl_noPTCCheck!=-1) {
//if it differs from the one with PTC name, then replace it with an invalid item (==more than one PTCName has the same source)
if (vl_noPTCCheck!=vl_dataValueId) {
f_EPTF_str2int_HashMap_Update(v_EPTF_DataSourceClient_dataValueHash,vl_dataValueIdStr_noPTCName,-1);
}
}
}// else: not possible: entry with PTC name is always there
}
}
// call handler if it was given:
if (isbound(v_EPTF_DataSourceClient_GetDataHandler_DB[pl_dataValue.transactionId])
and (0<sizeof(v_EPTF_DataSourceClient_GetDataHandler_DB[pl_dataValue.transactionId]))) {
for(var integer i:=0; i<sizeof(v_EPTF_DataSourceClient_GetDataHandler_DB[pl_dataValue.transactionId]); i:=i+1) {
if (v_EPTF_DataSourceClient_GetDataHandler_DB[pl_dataValue.transactionId][i].getDataHandler != null) {
if (not ispresent(pl_dataValue.dataVarName)) {
pl_dataValue.dataVarName := "";
}
v_EPTF_DataSourceClient_GetDataHandler_DB[pl_dataValue.transactionId][i].getDataHandler.apply(
//request parameters:
pl_source := pl_dataValue.dataSource,
pl_ptcName := pl_dataValue.ptcName, // response may fill this if it was ""
pl_element := pl_dataValue.dataElement,
pl_params := pl_dataValue.params,
// reponse parameters:
pl_errorCode := pl_dataValue.errorCode, // error code in the response
pl_remoteDataVarName := pl_dataValue.dataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message
pl_ownerCompRef := pl_dataValue.ownerCompRef, // reference to the remote component
pl_localDataVarId := vl_localDataVarId, // var id on the local component (contains the current value, not subscribed to remote!)
pl_dataValue := pl_dataValue.dataValue, // the value of the data
// user data
pl_userData := v_EPTF_DataSourceClient_GetDataHandler_DB[pl_dataValue.transactionId][i].userData // user specific data given at the request
);
}
}
v_EPTF_DataSourceClient_GetDataHandler_DB[pl_dataValue.transactionId] := {};
//FIXME: this should be enabled for getData_nonBlocking:
//f_EPTF_str2int_HashMap_Erase(v_EPTF_DataSourceClient_pendingGetDataHash,vl_dataValueIdStr);
f_EPTF_Semaphore_delete(pl_dataValue.transactionId);
} else {
if (f_EPTF_Semaphore_isLocked(pl_dataValue.transactionId)) {
f_EPTF_Semaphore_unlock(pl_dataValue.transactionId);
}
}
}
private function f_EPTF_DataSourceClient_handleDataValueResponse(
in EPTF_DataSource_Msg_DataValueResponse pl_dataValueResponse,
in EPTF_DataSource_CT pl_sourceCompRef
) runs on EPTF_DataSourceClient_CT {
var integer vl_localDataVarId := -1;
v_EPTF_DataSourceClient_Msg_List[pl_dataValueResponse.transactionId] := {dataValueResponse := pl_dataValueResponse};
// if returned error code is non-0, update the error message:
if (pl_dataValueResponse.errorCode!=0) {
if (not ischosen(pl_dataValueResponse.dataValue.charstringVal)) {
pl_dataValueResponse.dataValue := {charstringVal := "Error info: "&ttcn2string(pl_dataValueResponse.dataValue)}; // error message was not present => set it to the string value of provided value
}
f_EPTF_DataSourceClient_warning(pl_dataValueResponse.dataValue.charstringVal&"\nError code: "&int2str(pl_dataValueResponse.errorCode));
}
// call handler if it was given:
if (isbound(v_EPTF_DataSourceClient_GetDataValueHandler_DB[pl_dataValueResponse.transactionId])) {
if (v_EPTF_DataSourceClient_GetDataValueHandler_DB[pl_dataValueResponse.transactionId].getDataValueHandler != null) {
v_EPTF_DataSourceClient_GetDataValueHandler_DB[pl_dataValueResponse.transactionId].getDataValueHandler.apply(
// reponse parameters:
pl_errorCode := pl_dataValueResponse.errorCode, // error code in the response
pl_dataValue := pl_dataValueResponse.dataValue, // the value of the data
// user data
pl_userData := v_EPTF_DataSourceClient_GetDataValueHandler_DB[pl_dataValueResponse.transactionId].userData // user specific data given at the request
);
}
v_EPTF_DataSourceClient_GetDataValueHandler_DB[pl_dataValueResponse.transactionId] := {};
f_EPTF_Semaphore_delete(pl_dataValueResponse.transactionId);
} else {
if (f_EPTF_Semaphore_isLocked(pl_dataValueResponse.transactionId)) {
f_EPTF_Semaphore_unlock(pl_dataValueResponse.transactionId);
}
}
}
private function f_EPTF_DataSourceClient_handleConditionValue(
in EPTF_DataSource_Msg_ConditionValue pl_conditionValue,
in EPTF_DataSource_CT pl_sourceCompRef
) runs on EPTF_DataSourceClient_CT {
var integer vl_localDataVarId := -1;
v_EPTF_DataSourceClient_Msg_List[pl_conditionValue.transactionId] := {conditionValue := pl_conditionValue};
//no dataVarName in EPTF_DataSource_Msg_ConditionValue -> warning is not logged
// if (pl_conditionValue.errorCode==0) {
// //nothing to do
// } else {
// f_EPTF_DataSourceClient_warning(pl_conditionValue.dataVarName); // warning message is received in the dataVarName
// }
// call handler if it was given:
if (isbound(v_EPTF_DataSourceClient_GetDataHandler_DB[pl_conditionValue.transactionId])
and (0<sizeof(v_EPTF_DataSourceClient_GetDataHandler_DB[pl_conditionValue.transactionId]))) {
for(var integer i:=0; i<sizeof(v_EPTF_DataSourceClient_GetDataHandler_DB[pl_conditionValue.transactionId]); i:=i+1) {
if(v_EPTF_DataSourceClient_GetDataHandler_DB[pl_conditionValue.transactionId][i].getDataHandler != null) {
v_EPTF_DataSourceClient_GetDataHandler_DB[pl_conditionValue.transactionId][i].getDataHandler.apply(
//request parameters:
pl_source := pl_conditionValue.dataSource,
pl_ptcName := pl_conditionValue.ptcName, // response may fill this if it was ""
pl_element := pl_conditionValue.method,
pl_params := pl_conditionValue.params,
// reponse parameters:
pl_errorCode := pl_conditionValue.errorCode, // error code in the response
pl_remoteDataVarName := "",//pl_conditionValue.dataVarName, // var name on the remote component. In case errorCode!=0: it contains the error message
pl_ownerCompRef := null,//pl_conditionValue.ownerCompRef, // reference to the remote component
pl_localDataVarId := -1, // var id on the local component (contains the current value, not subscribed to remote!)
pl_dataValue := {boolVal := pl_conditionValue.conditionValue}, // the value of the data
// user data
pl_userData := v_EPTF_DataSourceClient_GetDataHandler_DB[pl_conditionValue.transactionId][i].userData // user specific data given at the request
);
}
}
v_EPTF_DataSourceClient_GetDataHandler_DB[pl_conditionValue.transactionId] := {};
f_EPTF_Semaphore_delete(pl_conditionValue.transactionId);
} else {
f_EPTF_Semaphore_unlock(pl_conditionValue.transactionId);
}
}
private function f_EPTF_DataSourceClient_sendMsg(
in EPTF_DataSource_Msg pl_msg,
in EPTF_DataSource_CT pl_sourceCompRef := null
) runs on EPTF_DataSourceClient_CT {
if(not v_EPTF_DataSourceClient_connected) {
f_EPTF_DataSourceClient_warning(log2str(%definitionId&": Cannot send message ",
"for pl_msg: ",pl_msg," to "," pl_sourceCompRef: ",pl_sourceCompRef,": Not connected to DataSource"));
return;
}
if (pl_sourceCompRef==null) {
EPTF_DataSourceClientIf.send(pl_msg);
} else {
EPTF_DataSourceClientIf.send(pl_msg) to pl_sourceCompRef;
}
}
private altstep as_EPTF_DataSourceClient_EventHandler() runs on EPTF_DataSourceClient_CT {
var EPTF_DataSource_CT vl_sourceCompRef;
var EPTF_DataSource_Msg vl_msg;
[] EPTF_DataSourceClientIf.receive(EPTF_DataSource_Msg:?) -> value vl_msg sender vl_sourceCompRef {
if (ischosen(vl_msg.getData)) {
f_EPTF_DataSourceClient_handleGetData(vl_msg.getData,vl_sourceCompRef);
} else if (ischosen(vl_msg.getDataValue)) {
f_EPTF_DataSourceClient_handleGetDataValue(vl_msg.getDataValue,vl_sourceCompRef);
} else if (ischosen(vl_msg.setDataValue)) {
f_EPTF_DataSourceClient_handleSetDataValue(vl_msg.setDataValue,vl_sourceCompRef);
} else if (ischosen(vl_msg.getList)) {
f_EPTF_DataSourceClient_handleGetList(vl_msg.getList,vl_sourceCompRef);
} else if (ischosen(vl_msg.getCondition)) {
f_EPTF_DataSourceClient_handleGetCondition(vl_msg.getCondition,vl_sourceCompRef);
} else if (ischosen(vl_msg.dataValue)) {
f_EPTF_DataSourceClient_handleDataValue(vl_msg.dataValue,vl_sourceCompRef);
} else if (ischosen(vl_msg.dataValueResponse)) {
f_EPTF_DataSourceClient_handleDataValueResponse(vl_msg.dataValueResponse,vl_sourceCompRef);
} else if (ischosen(vl_msg.conditionValue)) {
f_EPTF_DataSourceClient_handleConditionValue(vl_msg.conditionValue,vl_sourceCompRef);
}
repeat;
}
}
private function f_EPTF_DataSourceClient_error(in charstring pl_msg)
runs on EPTF_Logging_CT{
f_EPTF_Logging_error(true, pl_msg);
}
private function f_EPTF_DataSourceClient_warning(in charstring pl_msg)
runs on EPTF_Logging_CT{
f_EPTF_Logging_warning(true, pl_msg);
}
// private function f_EPTF_DataSourceClient_debug(in charstring pl_msg)
// runs on EPTF_Logging_CT{
// f_EPTF_Logging_debug(true,"Debug: "&pl_msg);
// }
///////////////////////////////////////////////////////////
// Function: f_EPTF_DataSourceClient_extractParams
//
// Purpose:
// Extracts the needed parameters from the params.
// It returns "" for values of params that are not found.
//
// Parameters:
// *in* <EPTF_DataSource_Params> *pl_params* - the actual parameters
// *in* <EPTF_CharstringList> *pl_needed* - the parameters needed
// *in* <EPTF_CharstringList> *pl_result* - the value of the needed parameters
//
// Return Value:
// integer - 0 if OK, nonzero in case of failure to show that
// unexpected parameter was specified
//
// Detailed Comments:
// Can be called in the dataElement handler or DScheckParams function
// Similar function without return value: <f_EPTF_DataSource_extractParams>
// This function also prints out a warning message when an
// unexpected parameter is specified
///////////////////////////////////////////////////////////
public function f_EPTF_DataSourceClient_extractParams(
in charstring pl_element,
in EPTF_DataSource_Params pl_params,
in EPTF_CharstringList pl_needed,
out EPTF_CharstringList pl_result)
runs on EPTF_Logging_CT
return integer{
pl_result := {};
for(var integer j := 0; j < sizeof(pl_needed); j := j + 1){
pl_result[j] := "";
}
for(var integer i := 0; i < sizeof(pl_params); i:= i + 1){
var boolean vl_found := false;
for(var integer j := 0; j < sizeof(pl_needed); j := j + 1){
if(pl_params[i].paramName == pl_needed[j]){
pl_result[j] := pl_params[i].paramValue;
vl_found := true;
break;
}
}
if(not vl_found){
f_EPTF_DataSourceClient_warning("Invalid parameter: "&pl_params[i].paramName&" for element "&pl_element&". Acceptable parameters: "&log2str(pl_needed));
return -1;
}
}
return 0
}
} // module EPTF_CLL_DataSource_ClientFunctions