- added client side control service support for edition 1/2 APC CDCs

pull/6/head
Michael Zillgith 10 years ago
parent b0e8a6331b
commit 94a98bcc6d

@ -47,7 +47,10 @@ struct sControlObjectClient
bool synchroCheck;
bool hasTimeActivatedMode;
int edition; /* 1 = Ed. 1 - 2 = Ed. 2 */
MmsValue* analogValue; /* for APC-CDCs */
int edition; /* 1 = Ed. 1 - 2 = Ed. 2 - to distinguish time stamp format */
bool hasCtlNum; /* Check if ctlNum attribute is present - ctlNum is(/can be?) absent in edition 1 APC CDC */
bool useConstantT; /* some servers require a constant T parameter for select and operate */
uint64_t constantT; /* timestamp of select/operate to be used when constant T option is selected */
@ -177,8 +180,9 @@ ControlObjectClient_create(const char* objectReference, IedConnection connection
goto exit_function;
}
/* check for time activated control */
/* check for time activated control and ctlNum */
bool hasTimeActivatedControl = false;
bool hasCtlNum = false;
strcpy(itemId, objectReference);
strcat(itemId, ".Oper");
@ -194,7 +198,9 @@ ControlObjectClient_create(const char* objectReference, IedConnection connection
if (strcmp(objectName, "operTm") == 0) {
hasTimeActivatedControl = true;
break;
}
else if (strcmp(objectName, "ctlNum") == 0) {
hasCtlNum = true;
}
element = LinkedList_getNext(element);
@ -222,9 +228,16 @@ ControlObjectClient_create(const char* objectReference, IedConnection connection
self->connection = connection;
self->ctlModel = (ControlModel) ctlModelVal;
self->hasTimeActivatedMode = hasTimeActivatedControl;
self->hasCtlNum = hasCtlNum;
self->ctlVal = MmsValue_getElement(oper, 0);
/* Check for T element type (EntryTime -> Ed.1, Timestamp -> Ed.2) */
if (MmsValue_getType(self->ctlVal) == MMS_STRUCTURE)
self->analogValue = MmsValue_createEmptyStructure(1);
else
self->analogValue = NULL;
/* Check for T element type (Binary time -> Ed.1,UTC time -> Ed.2) */
MmsValue* t;
if (hasTimeActivatedControl)
@ -261,6 +274,9 @@ ControlObjectClient_destroy(ControlObjectClient self)
if (self->ctlVal != NULL)
MmsValue_delete(self->ctlVal);
if (self->analogValue != NULL)
MmsValue_delete(self->analogValue);
if (self->orIdent != NULL)
GLOBAL_FREEMEM(self->orIdent);
@ -358,10 +374,23 @@ ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t
MmsValue* operParameters;
int operElementCount = 5;
if (self->hasTimeActivatedMode)
operParameters = MmsValue_createEmptyStructure(7);
else
operParameters = MmsValue_createEmptyStructure(6);
operElementCount++;
if (self->hasCtlNum)
operElementCount++;
operParameters = MmsValue_createEmptyStructure(operElementCount);
/* support simplified usage of APC controls - user doesn't need to create the structure */
if (self->analogValue != NULL) {
if (MmsValue_getType(ctlVal) != MMS_STRUCTURE) {
MmsValue_setElement(self->analogValue, 0, ctlVal);
ctlVal = self->analogValue;
}
}
MmsValue_setElement(operParameters, 0, ctlVal);
@ -381,8 +410,10 @@ ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t
self->ctlNum++;
}
MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum);
MmsValue_setElement(operParameters, index++, ctlNum);
if (self->hasCtlNum) {
MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum);
MmsValue_setElement(operParameters, index++, ctlNum);
}
uint64_t timestamp;
@ -443,6 +474,10 @@ ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t
}
MmsValue_update(self->ctlVal, ctlVal);
if (self->analogValue)
MmsValue_setElement(self->analogValue, 0, NULL);
self->opertime = operTime;
success = true;
@ -470,12 +505,23 @@ ControlObjectClient_selectWithValue(ControlObjectClient self, MmsValue* ctlVal)
MmsError mmsError;
MmsValue* selValParameters;
int selValElementCount = 5;
if (self->hasTimeActivatedMode)
selValParameters = MmsValue_createEmptyStructure(7);
else
selValParameters = MmsValue_createEmptyStructure(6);
selValElementCount++;
if (self->hasCtlNum)
selValElementCount++;
MmsValue* selValParameters = MmsValue_createEmptyStructure(selValElementCount);
/* support simplified usage of APC controls - user doesn't need to create the structure */
if (self->analogValue != NULL) {
if (MmsValue_getType(ctlVal) != MMS_STRUCTURE) {
MmsValue_setElement(self->analogValue, 0, ctlVal);
ctlVal = self->analogValue;
}
}
MmsValue_setElement(selValParameters, 0, ctlVal);
@ -491,9 +537,10 @@ ControlObjectClient_selectWithValue(ControlObjectClient self, MmsValue* ctlVal)
self->ctlNum++;
MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum);
MmsValue_setElement(selValParameters, index++, ctlNum);
if (self->hasCtlNum) {
MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum);
MmsValue_setElement(selValParameters, index++, ctlNum);
}
uint64_t timestamp = Hal_getTimeInMs();
MmsValue* ctlTime;
@ -532,6 +579,9 @@ ControlObjectClient_selectWithValue(ControlObjectClient self, MmsValue* ctlVal)
MmsValue_update(self->ctlVal, ctlVal);
if (self->analogValue)
MmsValue_setElement(self->analogValue, 0, NULL);
return true;
}

@ -1311,12 +1311,29 @@ ControlObjectClient_getObjectReference(ControlObjectClient self);
ControlModel
ControlObjectClient_getControlModel(ControlObjectClient self);
/**
* \brief Send an operate command to the server
*
* \param self the control object instance to use
* \param ctlVal the control value (for APC the value may be either AnalogueValue (MMS_STRUCT) or MMS_FLOAT/MMS_INTEGER
* \param operTime the time when the command has to be executed (for time activated control). If this value is 0 the command will be executed instantly.
*
* \return true if operation has been successful, false otherwise.
*/
bool
ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t operTime);
bool
ControlObjectClient_select(ControlObjectClient self);
/**
* \brief Send an select with value command to the server
*
* \param self the control object instance to use
* \param ctlVal the control value (for APC the value may be either AnalogueValue (MMS_STRUCT) or MMS_FLOAT/MMS_INTEGER
*
* \return true if select has been successful, false otherwise.
*/
bool
ControlObjectClient_selectWithValue(ControlObjectClient self, MmsValue* ctlVal);

Loading…
Cancel
Save