Added write access handler data reference parameter

pull/345/head
Kevin Jhang 4 years ago
parent 407ee9048f
commit 4a7982ae69

@ -2034,7 +2034,7 @@ namespace IEC61850
public delegate void RCBEventHandler(object parameter, ReportControlBlock rcb, ClientConnection con, RCBEventType eventType, string parameterName, MmsDataAccessError serviceError);
public delegate MmsDataAccessError WriteAccessHandler (DataAttribute dataAttr, MmsValue value,
public delegate MmsDataAccessError WriteAccessHandler (DataAttribute dataAttr, string dataRef, MmsValue value,
ClientConnection connection, object parameter);
/// <summary>
@ -2215,7 +2215,7 @@ namespace IEC61850
static extern void IedServer_setWriteAccessPolicy(IntPtr self, FunctionalConstraint fc, AccessPolicy policy);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int InternalWriteAccessHandler (IntPtr dataAttribute, IntPtr value, IntPtr connection, IntPtr parameter);
private delegate int InternalWriteAccessHandler (IntPtr dataAttribute, IntPtr dataRef, IntPtr value, IntPtr connection, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedServer_handleWriteAccess(IntPtr self, IntPtr dataAttribute,
@ -2397,7 +2397,7 @@ namespace IEC61850
}
}
int WriteAccessHandlerImpl (IntPtr dataAttribute, IntPtr value, IntPtr connection, IntPtr parameter)
int WriteAccessHandlerImpl (IntPtr dataAttribute, IntPtr dataRef, IntPtr value, IntPtr connection, IntPtr parameter)
{
WriteAccessHandlerInfo info;
@ -2407,9 +2407,11 @@ namespace IEC61850
clientConnections.TryGetValue(connection, out con);
string dataRefereence = Marshal.PtrToStringAnsi(dataRef);
MmsValue mmsValue = new MmsValue(value);
return (int)info.handler(info.dataAttribute, mmsValue.Clone(), con, info.parameter);
return (int)info.handler(info.dataAttribute, dataRefereence, mmsValue.Clone(), con, info.parameter);
}
else
{

@ -107,7 +107,7 @@ controlHandlerForBinaryOutput(ControlAction action, void* parameter, MmsValue* v
}
static MmsDataAccessError
writeAccessHandler (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter)
writeAccessHandler (DataAttribute* dataAttribute, char* dataRef, MmsValue* value, ClientConnection connection, void* parameter)
{
ControlModel ctlModelVal = (ControlModel) MmsValue_toInt32(value);

@ -128,7 +128,7 @@ controlHandlerForBinaryOutput(ControlAction action, void* parameter, MmsValue* v
static MmsDataAccessError
writeAccessHandler (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter)
writeAccessHandler (DataAttribute* dataAttribute, char* dataRef, MmsValue* value, ClientConnection connection, void* parameter)
{
void* securityToken = ClientConnection_getSecurityToken(connection);

@ -70,7 +70,7 @@ updateProcessValues()
}
static MmsDataAccessError
writeAccessHandler (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter)
writeAccessHandler (DataAttribute* dataAttribute, char* dataRef, MmsValue* value, ClientConnection connection, void* parameter)
{
if (dataAttribute == IEDMODEL_LD1_GGIO1_AnIn1_subEna) {

@ -22,7 +22,7 @@ void sigint_handler(int signalId)
}
static MmsDataAccessError
writeAccessHandler (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter)
writeAccessHandler (DataAttribute* dataAttribute, char* dataRef, MmsValue* value, ClientConnection connection, void* parameter)
{
if (dataAttribute == IEDMODEL_Inverter_ZINV1_OutVarSet_setMag_f) {

@ -1713,6 +1713,7 @@ MmsGooseControlBlock_getNdsCom(MmsGooseControlBlock self);
* stack will not update the value automatically.
*
* \param the data attribute that has been written by an MMS client.
* \param the dataRef the data reference for alternate access
* \param the value the client want to write to the data attribute
* \param connection the connection object of the client connection that invoked the write operation
* \param parameter the user provided parameter
@ -1720,7 +1721,7 @@ MmsGooseControlBlock_getNdsCom(MmsGooseControlBlock self);
* \return DATA_ACCESS_ERROR_SUCCESS, or DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE if access is accepted, DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED if access is denied.
*/
typedef MmsDataAccessError
(*WriteAccessHandler) (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter);
(*WriteAccessHandler) (DataAttribute* dataAttribute, char* dataRef, MmsValue* value, ClientConnection connection, void* parameter);
/**
* \brief Install a WriteAccessHandler for a data attribute.

@ -2530,7 +2530,7 @@ getAccessPolicyForFC(MmsMapping* self, FunctionalConstraint fc)
static MmsDataAccessError
mmsWriteHandler(void* parameter, MmsDomain* domain,
char* variableId, MmsValue* value, MmsServerConnection connection)
char* variableId, char* dataRef, MmsValue* value, MmsServerConnection connection)
{
MmsMapping* self = (MmsMapping*) parameter;
@ -2838,11 +2838,6 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
cachedValue = MmsServer_getValueFromCache(self->mmsServer, domain, variableId);
if (cachedValue) {
if (!MmsValue_equalTypes(cachedValue, value)) {
return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
}
bool handlerFound = false;
AccessPolicy nodeAccessPolicy = getAccessPolicyForFC(self, fc);
@ -2878,7 +2873,7 @@ mmsWriteHandler(void* parameter, MmsDomain* domain,
connection);
MmsDataAccessError handlerResult =
accessHandler->handler(dataAttribute, value, clientConnection,
accessHandler->handler(dataAttribute, dataRef, value, clientConnection,
accessHandler->parameter);
if ((handlerResult == DATA_ACCESS_ERROR_SUCCESS) || (handlerResult == DATA_ACCESS_ERROR_SUCCESS_NO_UPDATE)) {

@ -403,6 +403,10 @@ LIB61850_INTERNAL MmsDataAccessError
mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* value,
MmsServerConnection connection);
LIB61850_INTERNAL MmsDataAccessError
mmsServer_setValueWithAlternateAccess(MmsServer self, MmsDomain* domain, char* itemId, AlternateAccess_t* alternateAccess,
MmsVariableSpecification* variable, MmsValue* value, MmsServerConnection connection);
/**
* \brief Get the current value of a variable in the server data model
*

@ -34,7 +34,7 @@ typedef MmsDataAccessError (*MmsReadAccessHandler) (void* parameter, MmsDomain*
char* variableId, MmsServerConnection connection, bool isDirectAccess);
typedef MmsDataAccessError (*MmsWriteVariableHandler)(void* parameter,
MmsDomain* domain, char* variableId, MmsValue* value,
MmsDomain* domain, char* variableId, char* dataRef, MmsValue* value,
MmsServerConnection connection);
typedef void (*MmsConnectionHandler)(void* parameter,

@ -481,15 +481,116 @@ MmsServer_insertIntoCache(MmsServer self, MmsDomain* domain, char* itemId, MmsVa
}
}
static bool
isAccessToArrayComponent(AlternateAccess_t* alternateAccess)
{
if (alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess != NULL)
{
if (alternateAccess->list.array[0]->choice.unnamed->
choice.selectAlternateAccess.alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.accessSelection.present ==
AlternateAccessSelection__selectAlternateAccess__accessSelection_PR_component)
{
return true;
}
else
return false;
}
else
return false;
}
static MmsValue*
getComponentOfArrayElement(AlternateAccess_t* alternateAccess, MmsVariableSpecification* namedVariable,
MmsValue* structuredValue, char* dataRefBuf)
{
MmsValue* retValue = NULL ;
if (isAccessToArrayComponent(alternateAccess))
{
Identifier_t component = alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess
->list.array[0]->choice.unnamed->choice.selectAccess.choice.component;
if (component.size > 129)
goto exit_function;
MmsVariableSpecification* structSpec;
if (namedVariable->type == MMS_ARRAY)
structSpec = namedVariable->typeSpec.array.elementTypeSpec;
else if (namedVariable->type == MMS_STRUCTURE)
structSpec = namedVariable;
else
goto exit_function;
int i;
for (i = 0; i < structSpec->typeSpec.structure.elementCount; i++) {
if ((int)strlen(structSpec->typeSpec.structure.elements[i]->name)
== component.size) {
if (strncmp(structSpec->typeSpec.structure.elements[i]->name,
(char*)component.buf, component.size) == 0) {
snprintf(dataRefBuf, 129, "%s.%s", dataRefBuf, (char*)component.buf);
MmsValue* value = MmsValue_getElement(structuredValue, i);
if (isAccessToArrayComponent(
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess)) {
retValue =
getComponentOfArrayElement(
alternateAccess->list.array[0]->choice.unnamed->choice.selectAlternateAccess.alternateAccess,
structSpec->typeSpec.structure.elements[i],
value, dataRefBuf);
}
else
retValue = value;
goto exit_function;
}
}
}
}
exit_function:
return retValue;
}
static char*
mmsServer_getDataRef(MmsDomain* domain, char* itemId) {
char dataRefBuf[130];
const char* separator = strchr(itemId, '$');
if (separator != NULL) {
snprintf(dataRefBuf, 129, "%s/", domain->domainName);
int bufOffset = strlen(domain->domainName) + 1;
strncpy(dataRefBuf + bufOffset, itemId, 129 - bufOffset);
bufOffset += separator - itemId;
strncpy(dataRefBuf + bufOffset, separator + 3, 129 - bufOffset);
}
dataRefBuf[129] = 0;
StringUtils_replace(dataRefBuf, '$', '.');
return dataRefBuf;
}
MmsDataAccessError
mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* value,
MmsServerConnection connection)
{
MmsDataAccessError indication;
char* dataRefBuf = mmsServer_getDataRef(domain, itemId);
if (self->writeHandler != NULL) {
indication = self->writeHandler(self->writeHandlerParameter, domain,
itemId, value, connection);
itemId, dataRefBuf, value, connection);
}
else {
MmsValue* cachedValue;
@ -509,6 +610,96 @@ mmsServer_setValue(MmsServer self, MmsDomain* domain, char* itemId, MmsValue* va
return indication;
}
MmsDataAccessError
mmsServer_setValueWithAlternateAccess(MmsServer self, MmsDomain* domain, char* itemId, AlternateAccess_t* alternateAccess, MmsVariableSpecification* variable,
MmsValue* value, MmsServerConnection connection)
{
MmsDataAccessError indication;
char* dataRefBuf = mmsServer_getDataRef(domain, itemId);
MmsValue* cachedArray;
if (domain == NULL)
domain = (MmsDomain*)self->device;
cachedArray = MmsServer_getValueFromCache(self, domain, itemId);
if (cachedArray != NULL) {
int index = mmsServer_getLowIndex(alternateAccess);
int numberOfElements = mmsServer_getNumberOfElements(alternateAccess);
snprintf(dataRefBuf, 129, "%s(%d)", dataRefBuf, index);
if (numberOfElements == 0) { /* select single array element with index */
MmsValue* elementValue;
if (isAccessToArrayComponent(alternateAccess)) {
if (variable->typeSpec.array.elementTypeSpec->type != MMS_STRUCTURE) {
indication = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
goto exit_function;
}
MmsValue* structValue = MmsValue_getElement(cachedArray, index);
if (structValue == NULL) {
indication = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
goto exit_function;
}
elementValue = getComponentOfArrayElement(alternateAccess, variable, structValue, dataRefBuf);
}
else {
elementValue = MmsValue_getElement(cachedArray, index);
}
if (self->writeHandler == NULL) {
if (MmsValue_update(elementValue, value) == false) {
indication = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto exit_function;
}
}
}
else { /* select sub-array with start-index and number-of-elements */
if (MmsValue_getType(value) != MMS_ARRAY) {
indication = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
}
else {
if (self->writeHandler == NULL) {
int elementNo;
for (elementNo = 0; elementNo < numberOfElements; elementNo++) {
MmsValue* newElement = MmsValue_getElement(value, elementNo);
MmsValue* elementValue = MmsValue_getElement(cachedArray, index++);
if ((elementValue == NULL) || (newElement == NULL))
indication = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
else if (MmsValue_update(elementValue, newElement) == false) {
indication = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto exit_function;
}
}
}
}
}
indication = DATA_ACCESS_ERROR_SUCCESS;
if (self->writeHandler != NULL) {
indication = self->writeHandler(self->writeHandlerParameter, domain,
itemId, dataRefBuf, value, connection);
}
}
else
indication = DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID;
exit_function:
return indication;
}
MmsValue*
mmsServer_getValue(MmsServer self, MmsDomain* domain, char* itemId, MmsServerConnection connection, bool isDirectAccess)
{

@ -615,74 +615,22 @@ mmsServer_handleWriteRequest(
continue;
}
if (alternateAccess != NULL) {
if (domain == NULL)
domain = (MmsDomain*) device;
MmsDataAccessError valueIndication;
MmsValue* cachedArray = MmsServer_getValueFromCache(connection->server, domain, nameIdStr);
if (cachedArray == NULL) {
accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
if (alternateAccess != NULL) {
valueIndication =
mmsServer_setValueWithAlternateAccess(connection->server, domain, nameIdStr, alternateAccess, variable, value, connection);
}
else {
/* Check for correct type */
if (MmsVariableSpecification_isValueOfType(variable, value) == false) {
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto end_of_main_loop;
}
int index = mmsServer_getLowIndex(alternateAccess);
int numberOfElements = mmsServer_getNumberOfElements(alternateAccess);
if (numberOfElements == 0) { /* select single array element with index */
MmsValue* elementValue = MmsValue_getElement(cachedArray, index);
if (elementValue == NULL) {
accessResults[i] = DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT;
goto end_of_main_loop;
}
if (MmsValue_update(elementValue, value) == false) {
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto end_of_main_loop;
}
}
else { /* select sub-array with start-index and number-of-elements */
if (MmsValue_getType(value) != MMS_ARRAY) {
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto end_of_main_loop;
}
int elementNo;
for (elementNo = 0; elementNo < numberOfElements; elementNo++) {
MmsValue* newElement = MmsValue_getElement(value, elementNo);
MmsValue* elementValue = MmsValue_getElement(cachedArray, index++);
if ((elementValue == NULL) || (newElement == NULL) ) {
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto end_of_main_loop;
}
if (MmsValue_update(elementValue, newElement) == false) {
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto end_of_main_loop;
}
}
}
accessResults[i] = DATA_ACCESS_ERROR_SUCCESS;
goto end_of_main_loop;
}
/* Check for correct type */
if (MmsVariableSpecification_isValueOfType(variable, value) == false) {
accessResults[i] = DATA_ACCESS_ERROR_TYPE_INCONSISTENT;
goto end_of_main_loop;
}
MmsDataAccessError valueIndication =
valueIndication =
mmsServer_setValue(connection->server, domain, nameIdStr, value, connection);
}
if (valueIndication == DATA_ACCESS_ERROR_NO_RESPONSE)
sendResponse = false;

Loading…
Cancel
Save