Merge branch 'v1.6_develop_528' into v1.6_develop_535

v1.6_develop
Michael Zillgith 16 hours ago
commit def9a6d70e

@ -27,32 +27,46 @@ updateCMVArrayElement(IedServer server, DataObject* phsAHar, int idx, float magn
{
DataObject* phsAHarArrayElem = (DataObject*)ModelNode_getChildWithIdx((ModelNode*)phsAHar, idx);
if (phsAHarArrayElem) {
if (phsAHarArrayElem)
{
DataAttribute* mag = (DataAttribute*)ModelNode_getChild((ModelNode*)phsAHarArrayElem, "cVal.mag.f");
DataAttribute* ang = (DataAttribute*)ModelNode_getChild((ModelNode*)phsAHarArrayElem, "cVal.ang.f");
DataAttribute* q = (DataAttribute*)ModelNode_getChild((ModelNode*)phsAHarArrayElem, "q");
DataAttribute* t = (DataAttribute*)ModelNode_getChild((ModelNode*)phsAHarArrayElem, "t");
if (mag && ang && q && t) {
if (mag && ang && q && t)
{
IedServer_updateQuality(server, q, quality);
IedServer_updateTimestampAttributeValue(server, t, &timestamp);
IedServer_updateFloatAttributeValue(server, mag, magnitude);
IedServer_updateFloatAttributeValue(server, ang, angle);
}
else {
else
{
printf("one of mag, ang, q, t not found\n");
}
}
else {
else
{
printf("Element with index %i not found\n", idx);
}
}
static MmsDataAccessError
writeAccessHandler(DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter)
{
char objRef[200];
char valueBuf[200];
ModelNode_getObjectReference((ModelNode*)dataAttribute, objRef);
printf("Write access - %s: %s\n", objRef, MmsValue_printToBuffer(value, valueBuf, sizeof(valueBuf)));
return DATA_ACCESS_ERROR_SUCCESS;
}
int
main(int argc, char **argv)
{
int tcpPort = 102;
if (argc > 1) {
@ -61,6 +75,8 @@ main(int argc, char **argv)
IedServer iedServer = IedServer_create(&iedModel);
IedServer_handleWriteAccessGlobally(iedServer, writeAccessHandler, NULL);
/* Get access to the MHAI1.HA data object handle - for static and dynamic model*/
DataObject* mhai1_ha_phsAHar = (DataObject*)
IedModel_getModelNodeByShortObjectReference(&iedModel, "ComplexArray/MHAI1.HA.phsAHar");
@ -75,7 +91,8 @@ main(int argc, char **argv)
Timestamp_setTimeInMilliseconds(&timestamp, Hal_getTimeInMs());
int i;
for (i = 0; i < 16; i++) {
for (i = 0; i < 16; i++)
{
updateCMVArrayElement(iedServer, mhai1_ha_phsAHar, i, mag, angle, quality, timestamp);
mag += 1.f;
angle += 0.01f;
@ -84,7 +101,8 @@ main(int argc, char **argv)
/* MMS server will be instructed to start listening to client connections. */
IedServer_start(iedServer, tcpPort);
if (!IedServer_isRunning(iedServer)) {
if (!IedServer_isRunning(iedServer))
{
printf("Starting server failed! Exit.\n");
IedServer_destroy(iedServer);
exit(-1);
@ -96,14 +114,16 @@ main(int argc, char **argv)
int counter = 0;
while (running) {
while (running)
{
Thread_sleep(1000);
Timestamp_setTimeInMilliseconds(&timestamp, Hal_getTimeInMs());
IedServer_lockDataModel(iedServer);
for (i = 0; i < 16; i++) {
for (i = 0; i < 16; i++)
{
updateCMVArrayElement(iedServer, mhai1_ha_phsAHar, i, mag, angle, quality, timestamp);
mag += 0.1f;
angle += 0.05f;
@ -126,4 +146,4 @@ main(int argc, char **argv)
IedServer_destroy(iedServer);
return 0;
} /* main() */
}

@ -1964,6 +1964,9 @@ IedServer_handleWriteAccessForComplexAttribute(IedServer self, DataAttribute* da
LIB61850_API void
IedServer_handleWriteAccessForDataObject(IedServer self, DataObject* dataObject, FunctionalConstraint fc, WriteAccessHandler handler, void* parameter);
LIB61850_API void
IedServer_handleWriteAccessGlobally(IedServer self, WriteAccessHandler handler, void* parameter);
typedef enum {
ACCESS_POLICY_ALLOW,
ACCESS_POLICY_DENY

@ -142,6 +142,9 @@ MmsMapping_setConnectionIndicationHandler(MmsMapping* self, IedConnectionIndicat
LIB61850_INTERNAL void
MmsMapping_setLogStorage(MmsMapping* self, const char* logRef, LogStorage logStorage);
LIB61850_INTERNAL void
MmsMapping_installGlobalWriteAccessHandler(MmsMapping* self, WriteAccessHandler handler, void* parameter);
LIB61850_INTERNAL void
MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter);

@ -288,7 +288,10 @@ struct sMmsMapping {
uint64_t nextControlTimeout; /* next monotonic time timeout in one of the control state machines (e.g. for select timeout) */
uint64_t nextRealTimeControlTimeout; /* next real time clock based timeout in one of the control state machines (e.g. for operTm)*/
LinkedList attributeAccessHandlers;
LinkedList attributeAccessHandlers; /* write access handlers for individual data attribtues */
WriteAccessHandler writeAccessHandler; /* global write access handler */
void* writeAccessHandlerParam;
#if (CONFIG_IEC61850_SUPPORT_USER_READ_ACCESS_CONTROL == 1)
ReadAccessHandler readAccessHandler;

@ -954,7 +954,6 @@ IedServer_setLocalIpAddress(IedServer self, const char* localIpAddress)
MmsServer_setLocalIpAddress(self->mmsServer, self->localIpAddress);
}
void
IedServer_startThreadless(IedServer self, int tcpPort)
{
@ -1820,6 +1819,15 @@ IedServer_setWriteAccessPolicy(IedServer self, FunctionalConstraint fc, AccessPo
}
}
void
IedServer_handleWriteAccessGlobally(IedServer self, WriteAccessHandler handler, void* parameter)
{
if (self && self->mmsMapping)
{
MmsMapping_installGlobalWriteAccessHandler(self->mmsMapping, handler, parameter);
}
}
void
IedServer_handleWriteAccess(IedServer self, DataAttribute* dataAttribute, WriteAccessHandler handler, void* parameter)
{

@ -2808,6 +2808,71 @@ getAccessPolicyForFC(MmsMapping* self, FunctionalConstraint fc)
return ACCESS_POLICY_DENY;
}
static MmsDataAccessError
getWriteAccessResultForFCDO(MmsMapping* self, DataObject* dataObject, FunctionalConstraint fc, MmsValue* value, ClientConnection clientConnection)
{
MmsDataAccessError result = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
ModelNode* child = dataObject->firstChild;
int idx = 0;
while (child)
{
if (child->modelType == DataAttributeModelType)
{
DataAttribute* da = (DataAttribute*)child;
if (da->fc == fc)
{
MmsValue* subValue = MmsValue_getElement(value, idx);
if (subValue)
{
if (self->writeAccessHandler)
{
result = self->writeAccessHandler(da, subValue, clientConnection, self->writeAccessHandlerParam);
if (result == DATA_ACCESS_ERROR_SUCCESS)
{
IedServer_updateAttributeValue(self->iedServer, da, subValue);
}
if ((result != DATA_ACCESS_ERROR_SUCCESS) && (result != DATA_ACCESS_ERROR_SUCCESS))
{
return result;
}
}
}
idx++;
}
}
else if (child->modelType == DataObjectModelType)
{
DataObject* subDataObject = (DataObject*)child;
if (DataObject_hasFCData(subDataObject, fc))
{
MmsValue* subValue = MmsValue_getElement(value, idx);
result = getWriteAccessResultForFCDO(self, subDataObject, fc, subValue, clientConnection);
if ((result != DATA_ACCESS_ERROR_SUCCESS) && (result != DATA_ACCESS_ERROR_SUCCESS))
{
return result;
}
idx++;
}
}
child = child->sibling;
}
return result;
}
static MmsDataAccessError
mmsWriteHandler(void* parameter, MmsDomain* domain, const char* variableId, int arrayIdx, const char* componentId,
MmsValue* value, MmsServerConnection connection)
@ -3274,6 +3339,70 @@ mmsWriteHandler(void* parameter, MmsDomain* domain, const char* variableId, int
writeHandlerListElement = LinkedList_getNext(writeHandlerListElement);
}
/* Call global write access handler */
if (self->writeAccessHandler && (handlerFound == false))
{
/* lookup data attribute */
IedModel* model = self->iedServer->model;
ModelNode* ld = IedModel_getModelNodeByObjectReference(model, domain->domainName);
if (ld)
{
*separator = 0;
ModelNode* ln = ModelNode_getChild(ld, variableId);
if (ln)
{
char* daRef = separator + 4;
StringUtils_replace(daRef, '$', '.');
ModelNode* da = ModelNode_getChild(ln, daRef);
if (da)
{
if (arrayIdx != -1)
{
da = ModelNode_getChildWithIdx(da, arrayIdx);
if (da && componentId)
{
char compIdBuf[65];
StringUtils_copyStringMax(compIdBuf, sizeof(compIdBuf), componentId);
StringUtils_replace(compIdBuf, '$', '.');
da = ModelNode_getChild(da, compIdBuf);
}
}
MmsDataAccessError handlerResult = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
if (da)
{
ClientConnection clientConnection =
private_IedServer_getClientConnectionByHandle(self->iedServer, connection);
if (da->modelType == DataAttributeModelType)
{
handlerResult =
self->writeAccessHandler((DataAttribute*)da, value, clientConnection, self->writeAccessHandlerParam);
}
else if (da->modelType == DataObjectModelType)
{
handlerResult = getWriteAccessResultForFCDO(self, (DataObject*)da, fc, value, clientConnection);
}
return handlerResult;
}
}
}
}
}
/* DENY access if no handler is found and default policy is DENY */
if (!handlerFound)
{
@ -3318,6 +3447,13 @@ getAccessHandlerForAttribute(MmsMapping* self, DataAttribute* dataAttribute)
return NULL;
}
void
MmsMapping_installGlobalWriteAccessHandler(MmsMapping* self, WriteAccessHandler handler, void* parameter)
{
self->writeAccessHandler = handler;
self->writeAccessHandlerParam = parameter;
}
void
MmsMapping_installWriteAccessHandler(MmsMapping* self, DataAttribute* dataAttribute, WriteAccessHandler handler,
void* parameter)

Loading…
Cancel
Save