- IEC 61850 server: added IedServer_updateCtlModel function to change control model at runtime

pull/93/head
Michael Zillgith 7 years ago
parent cad88b67a1
commit 91c22b3193

@ -1771,36 +1771,6 @@ ClientDataSet_getDataSetSize(ClientDataSet self);
typedef struct sControlObjectClient* ControlObjectClient;
typedef enum {
/**
* No support for control functions. Control object only support status information.
*/
CONTROL_MODEL_STATUS_ONLY = 0,
/**
* Direct control with normal security: Supports Operate, TimeActivatedOperate (optional),
* and Cancel (optional).
*/
CONTROL_MODEL_DIRECT_NORMAL = 1,
/**
* Select before operate (SBO) with normal security: Supports Select, Operate, TimeActivatedOperate (optional),
* and Cancel (optional).
*/
CONTROL_MODEL_SBO_NORMAL = 2,
/**
* Direct control with enhanced security (enhanced security includes the CommandTermination service)
*/
CONTROL_MODEL_DIRECT_ENHANCED = 3,
/**
* Select before operate (SBO) with enhanced security (enhanced security includes the CommandTermination service)
*/
CONTROL_MODEL_SBO_ENHANCED = 4
} ControlModel;
/**
* \brief Create a new client control object
*

@ -54,6 +54,38 @@ typedef struct {
uint8_t dstAddress[6];
} PhyComAddress;
/**
* \brief Control model (represented by "ctlModel" attribute)
*/
typedef enum {
/**
* No support for control functions. Control object only support status information.
*/
CONTROL_MODEL_STATUS_ONLY = 0,
/**
* Direct control with normal security: Supports Operate, TimeActivatedOperate (optional),
* and Cancel (optional).
*/
CONTROL_MODEL_DIRECT_NORMAL = 1,
/**
* Select before operate (SBO) with normal security: Supports Select, Operate, TimeActivatedOperate (optional),
* and Cancel (optional).
*/
CONTROL_MODEL_SBO_NORMAL = 2,
/**
* Direct control with enhanced security (enhanced security includes the CommandTermination service)
*/
CONTROL_MODEL_DIRECT_ENHANCED = 3,
/**
* Select before operate (SBO) with enhanced security (enhanced security includes the CommandTermination service)
*/
CONTROL_MODEL_SBO_ENHANCED = 4
} ControlModel;
/**
* @defgroup TRIGGER_OPTIONS Trigger options (bit values combinable)
*
@ -76,6 +108,8 @@ typedef struct {
#define TRG_OPT_GI 16
/** @} */
/**
* @defgroup REPORT_OPTIONS Report options (bit values combinable)
*

@ -1195,6 +1195,29 @@ IedServer_setPerformCheckHandler(IedServer self, DataObject* node, ControlPerfor
LIB61850_API void
IedServer_setWaitForExecutionHandler(IedServer self, DataObject* node, ControlWaitForExecutionHandler handler, void* parameter);
/**
* \brief Update the control model for the specified controllable data object with the given value and
* update "ctlModel" attribute value.
*
* NOTE: The corresponding control structures for the control model have to be present in the data model!
*
* \param self the instance of IedServer to operate on.
* \param ctlObject the controllable data object handle
* \param value the new control model value
*/
LIB61850_API void
IedServer_updateCtlModel(IedServer self, DataObject* ctlObject, ControlModel value);
/**
* \brief Refresh the control object parameters (ctlModel, sboClass, sboTimeout) from the current data
* attribute values in the online accessable data model.
*
* \param self the instance of IedServer to operate on.
* \param ctlObject the controllable data object handle
*/
LIB61850_API void
IedServer_refreshControlParameters(IedServer self, DataObject* ctlObject);
/**@}*/
/**

@ -148,4 +148,7 @@ ControlObject_installCheckHandler(ControlObject* self, ControlPerformCheckHandle
LIB61850_INTERNAL void
ControlObject_installWaitForExecutionHandler(ControlObject* self, ControlWaitForExecutionHandler handler, void* parameter);
LIB61850_INTERNAL void
ControlObject_updateControlModel(ControlObject* self, ControlModel value, DataObject* ctlObject);
#endif /* CONTROL_H_ */

@ -62,8 +62,10 @@ createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariabl
bool hasCancel = false;
int cancelIndex = 0;
bool hasSBOw = false;
bool hasSBO = false;
int sBOwIndex = 0;
int operIndex = 0;
int sBOIndex = 0;
MmsVariableSpecification* coSpec = typeSpec->typeSpec.structure.elements[i];
@ -89,11 +91,14 @@ createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariabl
hasSBOw = true;
sBOwIndex = j;
}
else if (!(strcmp(coElementSpec->name, "SBO") == 0)) {
else if ((strcmp(coElementSpec->name, "SBO") == 0)) {
hasSBO = true;
sBOIndex = j;
}
else {
if (DEBUG_IED_SERVER)
printf("IED_SERVER: createControlObjects: Unknown element in CO: %s! --> seems not to be a control object\n", coElementSpec->name);
printf("IED_SERVER: createControlObjects: Unknown element in CO: %s\n", coElementSpec->name);
break;
}
}
@ -128,6 +133,9 @@ createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariabl
if (hasSBOw)
controlObject->sbow = MmsValue_getElement(structure, sBOwIndex);
if (hasSBO)
controlObject->sbo = MmsValue_getElement(structure, sBOIndex);
MmsMapping_addControlObject(mapping, controlObject);
}
else {
@ -775,6 +783,22 @@ IedServer_setWaitForExecutionHandler(IedServer self, DataObject* node, ControlWa
if (controlObject != NULL)
ControlObject_installWaitForExecutionHandler(controlObject, handler, parameter);
}
void
IedServer_updateCtlModel(IedServer self, DataObject* ctlObject, ControlModel value)
{
ControlObject* controlObject = lookupControlObject(self, ctlObject);
if (controlObject != NULL)
ControlObject_updateControlModel(controlObject, value, ctlObject);
}
void
IedServer_refreshControlParameters(IedServer self, DataObject* ctlObject)
{
}
#endif /* (CONFIG_IEC61850_CONTROL_SERVICE == 1) */
#if (CONFIG_IEC61850_SAMPLED_VALUES_SUPPORT == 1)

@ -291,7 +291,7 @@ ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char*
goto exit_function;
if (DEBUG_IED_SERVER)
printf("create control object for LD: %s, LN: %s, name: %s\n", domain->domainName, lnName, name);
printf("IED_SERVER: create control object for LD: %s, LN: %s, name: %s\n", domain->domainName, lnName, name);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
self->stateLock = Semaphore_create(1);
@ -339,14 +339,14 @@ ControlObject_initialize(ControlObject* self)
char* ctlModelName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$ctlModel");
if (DEBUG_IED_SERVER)
printf("initialize control for %s\n", ctlModelName);
printf("IED_SERVER: initialize control for %s\n", ctlModelName);
MmsValue* ctlModel = MmsServer_getValueFromCache(mmsServer,
self->mmsDomain, ctlModelName);
if (ctlModel == NULL) {
if (DEBUG_IED_SERVER)
printf("No control model found for variable %s\n", ctlModelName);
printf("IED_SERVER: No control model found for variable %s\n", ctlModelName);
}
char* sboClassName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$sboClass");
@ -364,6 +364,20 @@ ControlObject_initialize(ControlObject* self)
self->originSt = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, originName);
char* sboTimeoutName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$sboTimeout");
self->sboTimeout = MmsServer_getValueFromCache(mmsServer,
self->mmsDomain, sboTimeoutName);
updateSboTimeoutValue(self);
if (self->sbo) {
char* controlObjectReference = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName,
"/", self->lnName, "$CO$", self->name, "$SBO");
MmsValue_setVisibleString(self->sbo, controlObjectReference);
}
self->error = MmsValue_newIntegerFromInt32(0);
self->addCause = MmsValue_newIntegerFromInt32(0);
@ -373,33 +387,12 @@ ControlObject_initialize(ControlObject* self)
self->ctlModel = ctlModelVal;
if (DEBUG_IED_SERVER)
printf(" ctlModel: %i\n", ctlModelVal);
if ((ctlModelVal == 2) || (ctlModelVal == 4)) { /* SBO */
char* controlObjectReference = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName,
"/", self->lnName, "$CO$", self->name, "$SBO");
self->sbo = MmsValue_newVisibleString(controlObjectReference);
char* sboTimeoutName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$sboTimeout");
self->sboTimeout = MmsServer_getValueFromCache(mmsServer,
self->mmsDomain, sboTimeoutName);
updateSboTimeoutValue(self);
printf("IED_SERVER: ctlModel: %i\n", ctlModelVal);
if ((ctlModelVal == 2) || (ctlModelVal == 4)) /* SBO */
setState(self, STATE_UNSELECTED);
if (DEBUG_IED_SERVER)
printf("timeout for %s is %i\n", sboTimeoutName, self->selectTimeout);
}
else {
self->sbo = MmsValue_newVisibleString(NULL);
else
setState(self, STATE_READY);
}
}
}
@ -409,8 +402,8 @@ ControlObject_destroy(ControlObject* self)
if (self->mmsValue != NULL)
MmsValue_delete(self->mmsValue);
if (self->sbo != NULL)
MmsValue_delete(self->sbo);
// if (self->sbo != NULL)
// MmsValue_delete(self->sbo);
if (self->emptyString != NULL)
MmsValue_delete(self->emptyString);
@ -557,6 +550,23 @@ ControlObject_installWaitForExecutionHandler(ControlObject* self, ControlWaitFor
self->waitForExecutionHandlerParameter = parameter;
}
void
ControlObject_updateControlModel(ControlObject* self, ControlModel value, DataObject* ctlObject)
{
self->ctlModel = (uint32_t) value;
if ((self->ctlModel == 2) || (self->ctlModel == 4)) /* SBO */
setState(self, STATE_UNSELECTED);
else
setState(self, STATE_READY);
DataAttribute* ctlModel = (DataAttribute*) ModelNode_getChild((ModelNode*) ctlObject, "ctlModel");
if (ctlModel) {
IedServer_updateInt32AttributeValue(self->iedServer, ctlModel, (int32_t) value);
}
}
void
Control_processControlActions(MmsMapping* self, uint64_t currentTimeInMs)
{
@ -1163,6 +1173,11 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
if (controlObject->ctlModel == CONTROL_MODEL_STATUS_ONLY) {
indication = DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED;
goto free_and_return;
}
if (strcmp(varName, "SBOw") == 0) { /* select with value */
if (controlObject->ctlModel == 4) {

Loading…
Cancel
Save