bacnetmstp: Add array support and the ability to create BACnet enums

This reworks the data handling portion of bacnetmstp.  Instead of just
handling a single data element returned from a device, we can handle
more, as in the case of BACnet arrays.

Added the ability to create BACnet enum data elements.  This is needed
in order to set binary value objects.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
Jon Trulson 2016-06-10 11:40:55 -06:00
parent 8fb7907a4e
commit f03696b7a5
2 changed files with 170 additions and 76 deletions

View File

@ -57,7 +57,7 @@ BACNETMSTP::BACNETMSTP()
memset(m_rxBuffer, 0, MAX_MPDU); memset(m_rxBuffer, 0, MAX_MPDU);
m_returnedValue = {0}; m_returnedValue.clear();
m_targetAddress = {0}; m_targetAddress = {0};
m_invokeID = 0; m_invokeID = 0;
m_errorDetected = false; m_errorDetected = false;
@ -165,6 +165,15 @@ void BACNETMSTP::handlerReadPropertyAck(uint8_t* service_request,
int len = 0; int len = 0;
BACNET_READ_PROPERTY_DATA data; BACNET_READ_PROPERTY_DATA data;
// clear our stored data
instance()->m_returnedValue.clear();
BACNET_APPLICATION_DATA_VALUE value;
memset((void *)&value, 0, sizeof(value));
uint8_t *application_data = 0;
int application_data_len = 0;
if (address_match(&(instance()->m_targetAddress), src) && if (address_match(&(instance()->m_targetAddress), src) &&
(service_data->invoke_id == instance()->m_invokeID)) (service_data->invoke_id == instance()->m_invokeID))
{ {
@ -173,19 +182,49 @@ void BACNETMSTP::handlerReadPropertyAck(uint8_t* service_request,
len = rp_ack_decode_service_request(service_request, service_len, len = rp_ack_decode_service_request(service_request, service_len,
&data); &data);
// FIXME: we don't currently handle arrays (len < service_len)
// store any delivered data elements
if (len > 0) if (len > 0)
{ {
bacapp_decode_application_data(data.application_data, application_data_len = data.application_data_len;
data.application_data_len, application_data = data.application_data;
&(instance()->m_returnedValue));
} while (true)
else {
{ len = bacapp_decode_application_data(application_data,
// shouldn't happen? application_data_len,
cerr << __FUNCTION__ << ": decode app data failed" << endl; &value);
if (len > 0)
{
// store a copy
instance()->m_returnedValue.push_back(value);
if (len < application_data_len)
{
// there is more data
application_data += len;
application_data_len -= len;
}
else
{
// we are done
break;
}
}
else
{
// shouldn't happen?
cerr << __FUNCTION__ << ": decode app data failed" << endl;
break;
}
}
} }
} }
if (instance()->m_debugging)
cerr << __FUNCTION__ << ": STORED "
<< instance()->m_returnedValue.size()
<< " data elements." << endl;
} }
void BACNETMSTP::handlerWritePropertyAck(BACNET_ADDRESS* src, void BACNETMSTP::handlerWritePropertyAck(BACNET_ADDRESS* src,
@ -553,7 +592,7 @@ bool BACNETMSTP::readProperty(uint32_t targetDeviceInstanceID,
m_command.readPropArgs.objType = objType; m_command.readPropArgs.objType = objType;
m_command.readPropArgs.objInstance = objInstance; m_command.readPropArgs.objInstance = objInstance;
m_command.readPropArgs.objProperty = objProperty; m_command.readPropArgs.objProperty = objProperty;
m_command.readPropArgs.arrayIndex = arrayIndex; // not implemented in the ack handler! m_command.readPropArgs.arrayIndex = arrayIndex;
if (m_debugging) if (m_debugging)
cerr << __FUNCTION__ << ": calling dispatchRequest()..." << endl; cerr << __FUNCTION__ << ": calling dispatchRequest()..." << endl;
@ -591,7 +630,7 @@ bool BACNETMSTP::writeProperty(uint32_t targetDeviceInstanceID,
m_command.writePropArgs.objProperty = objProperty; m_command.writePropArgs.objProperty = objProperty;
m_command.writePropArgs.propValue = propValue; m_command.writePropArgs.propValue = propValue;
m_command.writePropArgs.propPriority = propPriority; m_command.writePropArgs.propPriority = propPriority;
m_command.writePropArgs.arrayIndex = arrayIndex; // not implemented! m_command.writePropArgs.arrayIndex = arrayIndex;
if (m_debugging) if (m_debugging)
cerr << __FUNCTION__ << ": calling dispatchRequest()..." << endl; cerr << __FUNCTION__ << ": calling dispatchRequest()..." << endl;
@ -605,158 +644,163 @@ bool BACNETMSTP::writeProperty(uint32_t targetDeviceInstanceID,
return error; return error;
} }
BACNET_APPLICATION_DATA_VALUE BACNETMSTP::getData() BACNET_APPLICATION_DATA_VALUE BACNETMSTP::getData(int index)
{ {
return m_returnedValue; return m_returnedValue.at(index);
} }
uint8_t BACNETMSTP::getDataType() int BACNETMSTP::getDataNumElements()
{ {
return m_returnedValue.tag; return m_returnedValue.size();
} }
float BACNETMSTP::getDataTypeReal() uint8_t BACNETMSTP::getDataType(int index)
{ {
if (getDataType() == BACNET_APPLICATION_TAG_REAL) return m_returnedValue.at(index).tag;
return m_returnedValue.type.Real; }
float BACNETMSTP::getDataTypeReal(int index)
{
if (getDataType(index) == BACNET_APPLICATION_TAG_REAL)
return m_returnedValue.at(index).type.Real;
else else
{ {
if (m_debugging) if (m_debugging)
cerr << __FUNCTION__ << ": Not of Real type, trying to convert..." << endl; cerr << __FUNCTION__ << ": Not of Real type, trying to convert..." << endl;
// try to convert or throw // try to convert or throw
switch (getDataType()) switch (getDataType(index))
{ {
case BACNET_APPLICATION_TAG_BOOLEAN: case BACNET_APPLICATION_TAG_BOOLEAN:
return (getDataTypeBoolean() ? 1.0 : 0.0); return (getDataTypeBoolean(index) ? 1.0 : 0.0);
case BACNET_APPLICATION_TAG_UNSIGNED_INT: case BACNET_APPLICATION_TAG_UNSIGNED_INT:
return float(getDataTypeUnsignedInt()); return float(getDataTypeUnsignedInt(index));
case BACNET_APPLICATION_TAG_SIGNED_INT: case BACNET_APPLICATION_TAG_SIGNED_INT:
return float(getDataTypeSignedInt()); return float(getDataTypeSignedInt(index));
default: default:
throw std::invalid_argument(std::string(__FUNCTION__) throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type (" + ": data type ("
+ std::to_string(int(getDataType())) + std::to_string(int(getDataType(index)))
+ ") is not convertible to Real"); + ") is not convertible to Real");
} }
} }
} }
bool BACNETMSTP::getDataTypeBoolean() bool BACNETMSTP::getDataTypeBoolean(int index)
{ {
if (getDataType() == BACNET_APPLICATION_TAG_BOOLEAN) if (getDataType(index) == BACNET_APPLICATION_TAG_BOOLEAN)
return ((m_returnedValue.type.Boolean) ? true : false); return ((m_returnedValue.at(index).type.Boolean) ? true : false);
else else
throw std::invalid_argument(std::string(__FUNCTION__) throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type (" + ": data type ("
+ std::to_string(int(getDataType())) + std::to_string(int(getDataType(index)))
+ ") is not convertible to Bool"); + ") is not convertible to Bool");
} }
unsigned int BACNETMSTP::getDataTypeUnsignedInt() unsigned int BACNETMSTP::getDataTypeUnsignedInt(int index)
{ {
if (getDataType() == BACNET_APPLICATION_TAG_UNSIGNED_INT) if (getDataType(index) == BACNET_APPLICATION_TAG_UNSIGNED_INT)
return m_returnedValue.type.Unsigned_Int; return m_returnedValue.at(index).type.Unsigned_Int;
else else
throw std::invalid_argument(std::string(__FUNCTION__) throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type (" + ": data type ("
+ std::to_string(int(getDataType())) + std::to_string(int(getDataType(index)))
+ ") is not convertible to UnsignedInt"); + ") is not convertible to UnsignedInt");
} }
int BACNETMSTP::getDataTypeSignedInt() int BACNETMSTP::getDataTypeSignedInt(int index)
{ {
if (getDataType() == BACNET_APPLICATION_TAG_SIGNED_INT) if (getDataType(index) == BACNET_APPLICATION_TAG_SIGNED_INT)
return m_returnedValue.type.Signed_Int; return m_returnedValue.at(index).type.Signed_Int;
else else
throw std::invalid_argument(std::string(__FUNCTION__) throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type (" + ": data type ("
+ std::to_string(int(getDataType())) + std::to_string(int(getDataType(index)))
+ ") is not convertible to SignedInt"); + ") is not convertible to SignedInt");
} }
#if defined(BACAPP_DOUBLE) #if defined(BACAPP_DOUBLE)
double BACNETMSTP::getDataTypeDouble() double BACNETMSTP::getDataTypeDouble(int index)
{ {
if (getDataType() == BACNET_APPLICATION_TAG_DOUBLE) if (getDataType() == BACNET_APPLICATION_TAG_DOUBLE)
return m_returnedValue.type.Double; return m_returnedValue.at(index).type.Double;
else else
{ {
if (m_debugging) if (m_debugging)
cerr << __FUNCTION__ << ": Not of Double type, trying to convert..." << endl; cerr << __FUNCTION__ << ": Not of Double type, trying to convert..." << endl;
// try to convert or throw // try to convert or throw
switch (getDataType()) switch (getDataType(index))
{ {
case BACNET_APPLICATION_TAG_REAL: case BACNET_APPLICATION_TAG_REAL:
return double(getDataTypeReal()); return double(getDataTypeReal(index));
case BACNET_APPLICATION_TAG_BOOLEAN: case BACNET_APPLICATION_TAG_BOOLEAN:
return (getDataTypeBoolean() ? 1.0 : 0.0); return (getDataTypeBoolean(index) ? 1.0 : 0.0);
case BACNET_APPLICATION_TAG_UNSIGNED_INT: case BACNET_APPLICATION_TAG_UNSIGNED_INT:
return double(getDataTypeUnsignedInt()); return double(getDataTypeUnsignedInt(index));
case BACNET_APPLICATION_TAG_SIGNED_INT: case BACNET_APPLICATION_TAG_SIGNED_INT:
return double(getDataTypeSignedInt()); return double(getDataTypeSignedInt(index));
default: default:
throw std::invalid_argument(std::string(__FUNCTION__) throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type (" + ": data type ("
+ std::to_string(int(getDataType())) + std::to_string(int(getDataType(index)))
+ ") is not convertible to Double"); + ") is not convertible to Double");
} }
} }
} }
#endif // BACAPP_DOUBLE #endif // BACAPP_DOUBLE
unsigned int BACNETMSTP::getDataTypeEnum() unsigned int BACNETMSTP::getDataTypeEnum(int index)
{ {
if (getDataType() == BACNET_APPLICATION_TAG_ENUMERATED) if (getDataType(index) == BACNET_APPLICATION_TAG_ENUMERATED)
return m_returnedValue.type.Enumerated; return m_returnedValue.at(index).type.Enumerated;
else else
throw std::invalid_argument(std::string(__FUNCTION__) throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type (" + ": data type ("
+ std::to_string(int(getDataType())) + std::to_string(int(getDataType(index)))
+ ") is not convertible to Enum"); + ") is not convertible to Enum");
} }
std::string BACNETMSTP::getDataTypeString() std::string BACNETMSTP::getDataTypeString(int index)
{ {
string retval; string retval;
// Here, we can try to accomodate all the types // Here, we can try to accomodate all the types
switch(getDataType()) switch(getDataType(index))
{ {
case BACNET_APPLICATION_TAG_REAL: case BACNET_APPLICATION_TAG_REAL:
retval = std::to_string(getDataTypeReal()); retval = std::to_string(getDataTypeReal(index));
break; break;
#if defined(BACAPP_DOUBLE) #if defined(BACAPP_DOUBLE)
case BACNET_APPLICATION_TAG_DOUBLE: case BACNET_APPLICATION_TAG_DOUBLE:
retval = std::to_string(getDataTypeDouble()); retval = std::to_string(getDataTypeDouble(index));
break; break;
#endif // BACAPP_DOUBLE #endif // BACAPP_DOUBLE
case BACNET_APPLICATION_TAG_UNSIGNED_INT: case BACNET_APPLICATION_TAG_UNSIGNED_INT:
retval = std::to_string(getDataTypeUnsignedInt()); retval = std::to_string(getDataTypeUnsignedInt(index));
break; break;
case BACNET_APPLICATION_TAG_SIGNED_INT: case BACNET_APPLICATION_TAG_SIGNED_INT:
retval = std::to_string(getDataTypeSignedInt()); retval = std::to_string(getDataTypeSignedInt(index));
break; break;
case BACNET_APPLICATION_TAG_BOOLEAN: case BACNET_APPLICATION_TAG_BOOLEAN:
retval = (getDataTypeBoolean() ? string("true") : string("false")); retval = (getDataTypeBoolean(index) ? string("true") : string("false"));
break; break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING: case BACNET_APPLICATION_TAG_CHARACTER_STRING:
retval = string(characterstring_value(&m_returnedValue.type.Character_String), retval = string(characterstring_value(&m_returnedValue.at(index).type.Character_String),
characterstring_length(&m_returnedValue.type.Character_String)); characterstring_length(&m_returnedValue.at(index).type.Character_String));
break; break;
case BACNET_APPLICATION_TAG_OCTET_STRING: case BACNET_APPLICATION_TAG_OCTET_STRING:
{ {
string tmpstr((char *)octetstring_value(&m_returnedValue.type.Octet_String), string tmpstr((char *)octetstring_value(&m_returnedValue.at(index).type.Octet_String),
octetstring_length(&m_returnedValue.type.Octet_String)); octetstring_length(&m_returnedValue.at(index).type.Octet_String));
retval = string2HexString(tmpstr); retval = string2HexString(tmpstr);
} }
@ -764,11 +808,12 @@ std::string BACNETMSTP::getDataTypeString()
case BACNET_APPLICATION_TAG_BIT_STRING: case BACNET_APPLICATION_TAG_BIT_STRING:
{ {
int len = bitstring_bits_used(&m_returnedValue.type.Bit_String); int len = bitstring_bits_used(&m_returnedValue.at(index).type.Bit_String);
for (int i=0; i<len; i++) for (int i=0; i<len; i++)
{ {
if (bitstring_bit(&m_returnedValue.type.Bit_String, uint8_t(i))) if (bitstring_bit(&m_returnedValue.at(index).type.Bit_String,
uint8_t(i)))
retval += "1"; retval += "1";
else else
retval += "0"; retval += "0";
@ -783,7 +828,7 @@ std::string BACNETMSTP::getDataTypeString()
default: default:
throw std::invalid_argument(std::string(__FUNCTION__) throw std::invalid_argument(std::string(__FUNCTION__)
+ ": data type (" + ": data type ("
+ std::to_string(int(getDataType())) + std::to_string(int(getDataType(index)))
+ ") is not convertible to String"); + ") is not convertible to String");
break; break;
} }
@ -860,6 +905,17 @@ BACNET_APPLICATION_DATA_VALUE BACNETMSTP::createDataString(string value)
return data; return data;
} }
BACNET_APPLICATION_DATA_VALUE BACNETMSTP::createDataEnum(uint32_t value)
{
BACNET_APPLICATION_DATA_VALUE data;
memset(&data, 0, sizeof(BACNET_APPLICATION_DATA_VALUE));
data.tag = BACNET_APPLICATION_TAG_ENUMERATED;
data.type.Enumerated = value;
return data;
}
string BACNETMSTP::string2HexString(string input) string BACNETMSTP::string2HexString(string input)
{ {

View File

@ -24,6 +24,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <vector>
// we only support a BACnet RS-485 MS/TP datalink // we only support a BACnet RS-485 MS/TP datalink
#define BACDL_MSTP 1 #define BACDL_MSTP 1
@ -185,8 +186,7 @@ namespace upm {
* instance you wish to access. It should be one of the * instance you wish to access. It should be one of the
* BACNET_PROPERTY_ID values. * BACNET_PROPERTY_ID values.
* @param arrayIndex This specifies the index number of an array * @param arrayIndex This specifies the index number of an array
* property. This is not currently supported. Until it is, leave * property. The default is BACNET_ARRAY_ALL.
* the default at BACNET_ARRAY_ALL.
* @return true if an error occurred, false otherwise. * @return true if an error occurred, false otherwise.
*/ */
bool readProperty(uint32_t targetDeviceInstanceID, bool readProperty(uint32_t targetDeviceInstanceID,
@ -225,8 +225,7 @@ namespace upm {
* information in the bacnet-stack documentation as to whether * information in the bacnet-stack documentation as to whether
* this is even supported. * this is even supported.
* @param arrayIndex This specifies the index number of an array * @param arrayIndex This specifies the index number of an array
* property. This is not currently supported. Until it is, leave * property. The default is BACNET_ARRAY_ALL.
* the default at BACNET_ARRAY_ALL.
* @return true if an error occurred, false otherwise. * @return true if an error occurred, false otherwise.
*/ */
bool writeProperty(uint32_t targetDeviceInstanceID, bool writeProperty(uint32_t targetDeviceInstanceID,
@ -242,19 +241,32 @@ namespace upm {
* to return a BACNET_APPLICATION_DATA_VALUE structure containing * to return a BACNET_APPLICATION_DATA_VALUE structure containing
* the returned data. * the returned data.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return a BACNET_APPLICATION_DATA_VALUE structure containing * @return a BACNET_APPLICATION_DATA_VALUE structure containing
* the returned data. * the returned data.
*/ */
BACNET_APPLICATION_DATA_VALUE getData(); BACNET_APPLICATION_DATA_VALUE getData(int index=0);
/**
* After a successful readProperty request, this method can be
* used to return the number of data elements returned. This will
* usually be 1, unless reading an array.
*
* @return The number of data elements received.
*/
int getDataNumElements();
/** /**
* After a successful readProperty request, this method can be * After a successful readProperty request, this method can be
* used to return the BACnet data type of the returned data. It * used to return the BACnet data type of the returned data. It
* will be one of the BACNET_APPLICATION_TAG_* values. * will be one of the BACNET_APPLICATION_TAG_* values.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A BACNET_APPLICATION_TAG_* value * @return A BACNET_APPLICATION_TAG_* value
*/ */
uint8_t getDataType(); uint8_t getDataType(int index=0);
/** /**
* After a successful readProperty request, this method can be * After a successful readProperty request, this method can be
@ -263,9 +275,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_REAL, and the value returned cannot be * BACNET_APPLICATION_TAG_REAL, and the value returned cannot be
* safely converted, an exception is thrown. * safely converted, an exception is thrown.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A floating point value representing the returned data * @return A floating point value representing the returned data
*/ */
float getDataTypeReal(); float getDataTypeReal(int index=0);
/** /**
* After a successful readProperty request, this method can be * After a successful readProperty request, this method can be
@ -274,9 +288,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_BOOLEAN, and the value returned cannot * BACNET_APPLICATION_TAG_BOOLEAN, and the value returned cannot
* be safely converted, an exception is thrown. * be safely converted, an exception is thrown.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A boolean value representing the returned data * @return A boolean value representing the returned data
*/ */
bool getDataTypeBoolean(); bool getDataTypeBoolean(int index=0);
/** /**
* After a successful readProperty request, this method can be * After a successful readProperty request, this method can be
@ -285,9 +301,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_UNSIGNED_INT, and the value returned * BACNET_APPLICATION_TAG_UNSIGNED_INT, and the value returned
* cannot be safely converted, an exception is thrown. * cannot be safely converted, an exception is thrown.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return An unsigned int value representing the returned data * @return An unsigned int value representing the returned data
*/ */
unsigned int getDataTypeUnsignedInt(); unsigned int getDataTypeUnsignedInt(int index=0);
/** /**
* After a successful readProperty request, this method can be * After a successful readProperty request, this method can be
@ -296,9 +314,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_SIGNED_INT, and the value returned * BACNET_APPLICATION_TAG_SIGNED_INT, and the value returned
* cannot be safely converted, an exception is thrown. * cannot be safely converted, an exception is thrown.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A signed int value representing the returned data * @return A signed int value representing the returned data
*/ */
int getDataTypeSignedInt(); int getDataTypeSignedInt(int index=0);
/** /**
* After a successful readProperty request, this method can be * After a successful readProperty request, this method can be
@ -308,9 +328,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_CHARACTER_STRING, and the value returned * BACNET_APPLICATION_TAG_CHARACTER_STRING, and the value returned
* cannot be safely converted, an exception is thrown. * cannot be safely converted, an exception is thrown.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A string value representing the returned data * @return A string value representing the returned data
*/ */
std::string getDataTypeString(); std::string getDataTypeString(int index=0);
/** /**
* After a successful readProperty request, this method can be * After a successful readProperty request, this method can be
@ -318,9 +340,11 @@ namespace upm {
* enumeration. If the data type (getDataType()) is not a * enumeration. If the data type (getDataType()) is not a
* BACNET_APPLICATION_TAG_ENUMERATED an exception is thrown. * BACNET_APPLICATION_TAG_ENUMERATED an exception is thrown.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return An unsigned int representing a BACnet enumerant * @return An unsigned int representing a BACnet enumerant
*/ */
unsigned int getDataTypeEnum(); unsigned int getDataTypeEnum(int index=0);
#if defined(BACAPP_DOUBLE) #if defined(BACAPP_DOUBLE)
/** /**
@ -330,9 +354,11 @@ namespace upm {
* BACNET_APPLICATION_TAG_DOUBLE, and the value returned cannot be * BACNET_APPLICATION_TAG_DOUBLE, and the value returned cannot be
* safely converted, an exception is thrown. * safely converted, an exception is thrown.
* *
* @param index into the list of returned data. 0 (first) is the
* default.
* @return A double floating point value representing the returned data * @return A double floating point value representing the returned data
*/ */
double getDataTypeDouble(); double getDataTypeDouble(int index=0);
#endif // BACAPP_DOUBLE #endif // BACAPP_DOUBLE
/** /**
@ -392,6 +418,18 @@ namespace upm {
*/ */
BACNET_APPLICATION_DATA_VALUE createDataString(std::string value); BACNET_APPLICATION_DATA_VALUE createDataString(std::string value);
/**
* This method is used to create and return an initialized
* BACNET_APPLICATION_DATA_VALUE containing an enumeration. A
* pointer to this returned structure can then be used with
* writeProperty().
*
* @param value The BACnet enumeration to initialize the
* structure to.
* @return An initialized structure containing the value
*/
BACNET_APPLICATION_DATA_VALUE createDataEnum(uint32_t value);
/** /**
* Return an enumration of the last error type to occur. The * Return an enumration of the last error type to occur. The
* value returned will be one of the BACERR_TYPE_T values. * value returned will be one of the BACERR_TYPE_T values.
@ -664,7 +702,7 @@ namespace upm {
std::string m_upmErrorString; std::string m_upmErrorString;
// our returned data from readProperty() // our returned data from readProperty()
BACNET_APPLICATION_DATA_VALUE m_returnedValue; std::vector<BACNET_APPLICATION_DATA_VALUE> m_returnedValue;
// current bound target address of dispatched service request // current bound target address of dispatched service request
// (read/write prop, etc) // (read/write prop, etc)