uint32_t ClientReportControlBlock_getIntgPd(ClientReportControlBlock self) { if (self->intgPd != NULL) return MmsValue_toUint32(self->intgPd); else return 0; }
uint32_t ClientReportControlBlock_getBufTm(ClientReportControlBlock self) { if (self->bufTm != NULL) return MmsValue_toUint32(self->bufTm); else return 0; }
uint16_t ClientReportControlBlock_getSqNum(ClientReportControlBlock self) { if (self->sqNum != NULL) return (uint16_t) MmsValue_toUint32(self->sqNum); else return 0; }
uint32_t ClientReportControlBlock_getConvRev(ClientReportControlBlock self) { if (self->confRev != NULL) return MmsValue_toUint32(self->confRev); else return 0; }
uint16_t ClientGooseControlBlock_getDstAddress_appid(ClientGooseControlBlock self) { if (self->dstAddress != NULL) return (uint16_t) MmsValue_toUint32(MmsValue_getElement(self->dstAddress, 3)); else return 0; }
uint8_t ClientGooseControlBlock_getDstAddress_priority(ClientGooseControlBlock self) { if (self->dstAddress != NULL) return (uint8_t) MmsValue_toUint32(MmsValue_getElement(self->dstAddress, 1)); else return 0; }
uint32_t ClientGooseControlBlock_getMaxTime(ClientGooseControlBlock self) { if (self->maxTime != NULL) return MmsValue_toUint32(self->maxTime); else return 0; }
uint32_t IedServer_getUInt32AttributeValue(IedServer self, DataAttribute* dataAttribute) { assert(self != NULL); assert(dataAttribute != NULL); assert(dataAttribute->mmsValue != NULL); assert((MmsValue_getType(dataAttribute->mmsValue) == MMS_INTEGER) || (MmsValue_getType(dataAttribute->mmsValue) == MMS_UNSIGNED)); return MmsValue_toUint32(dataAttribute->mmsValue); }
void handleLastApplErrorMessage(IedConnection self, MmsValue* value) { if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: received LastApplError\n"); MmsValue* lastApplError = value; MmsValue* cntrlObj = MmsValue_getElement(lastApplError, 0); MmsValue* error = MmsValue_getElement(lastApplError, 1); //MmsValue* origin = MmsValue_getElement(lastApplError, 2); MmsValue* ctlNum = MmsValue_getElement(lastApplError, 3); MmsValue* addCause = MmsValue_getElement(lastApplError, 4); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: CntrlObj: %s\n", MmsValue_toString(cntrlObj)); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: ctlNum: %u\n", MmsValue_toUint32(ctlNum)); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: addCause: %i\n", MmsValue_toInt32(addCause)); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: error: %i\n", MmsValue_toInt32(error)); self->lastApplError.ctlNum = MmsValue_toUint32(ctlNum); self->lastApplError.addCause = MmsValue_toInt32(addCause); self->lastApplError.error = MmsValue_toInt32(error); LinkedList control = LinkedList_getNext(self->clientControls); while (control != NULL) { ControlObjectClient object = (ControlObjectClient) control->data; char* objectRef = ControlObjectClient_getObjectReference(object); if (doesControlObjectMatch(objectRef, MmsValue_toString(cntrlObj))) ControlObjectClient_setLastApplError(object, self->lastApplError); control = LinkedList_getNext(control); } }
void IedServer_updateUnsignedAttributeValue(IedServer self, DataAttribute* dataAttribute, uint32_t value) { assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_UNSIGNED); assert(dataAttribute != NULL); assert(self != NULL); uint32_t currentValue = MmsValue_toUint32(dataAttribute->mmsValue); if (currentValue == value) { checkForUpdateTrigger(self, dataAttribute); } else { MmsValue_setUint32(dataAttribute->mmsValue, value); checkForChangedTriggers(self, dataAttribute); } }
void ControlObject_sendLastApplError(ControlObject* self, MmsServerConnection connection, char* ctlVariable, int error, ControlAddCause addCause, MmsValue* ctlNum, MmsValue* origin, bool handlerMode) { MmsValue lastApplErrorMemory; MmsValue* lastApplError = &lastApplErrorMemory; lastApplError->type = MMS_STRUCTURE; lastApplError->value.structure.size = 5; MmsValue* componentContainer[5]; lastApplError->value.structure.components =componentContainer; char ctlObj[130]; StringUtils_createStringInBuffer(ctlObj, 3, self->ctlObjectName, "$", ctlVariable); if (DEBUG_IED_SERVER) { printf("IED_SERVER: sendLastApplError:\n"); printf("IED_SERVER: control object: %s\n", ctlObj); printf("IED_SERVER: ctlNum: %u\n", MmsValue_toUint32(ctlNum)); } MmsValue ctlObjValueMemory; MmsValue* ctlObjValue = &ctlObjValueMemory; ctlObjValue->type = MMS_VISIBLE_STRING; ctlObjValue->value.visibleString.buf = ctlObj; ctlObjValue->value.visibleString.size = sizeof(ctlObj); MmsValue_setElement(lastApplError, 0, ctlObjValue); MmsValue_setInt32(self->error, error); MmsValue_setInt32(self->addCause, addCause); MmsValue_setElement(lastApplError, 1, self->error); MmsValue_setElement(lastApplError, 2, origin); MmsValue_setElement(lastApplError, 3, ctlNum); MmsValue_setElement(lastApplError, 4, self->addCause); MmsServerConnection_sendInformationReportSingleVariableVMDSpecific(connection, "LastApplError", lastApplError, handlerMode); }
uint32_t IedConnection_readUnsigned32Value(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc) { MmsValue* value = IedConnection_readObject(self, error, objectReference, fc); uint32_t retVal = 0.f; if (value != NULL) { if ((MmsValue_getType(value) == MMS_INTEGER) || (MmsValue_getType(value) == MMS_UNSIGNED)) retVal = MmsValue_toUint32(value); else { if (MmsValue_getType(value) == MMS_DATA_ACCESS_ERROR) *error = iedConnection_mapDataAccessErrorToIedError(MmsValue_getDataAccessError(value)); else *error = IED_ERROR_UNEXPECTED_VALUE_RECEIVED; } MmsValue_delete(value); } return retVal; }
ControlObjectClient ControlObjectClient_create(const char* objectReference, IedConnection connection) { ControlObjectClient self = NULL; /* request control model from server */ char domainId[65]; char itemId[65]; char* domainName = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainId); if (domainName == NULL) goto exit_function; convertToMmsAndInsertFC(itemId, objectReference + strlen(domainId) + 1, "CF"); int controlObjectItemIdLen = strlen(itemId); strncat(itemId, "$ctlModel", 64 - controlObjectItemIdLen); MmsError mmsError; MmsValue* ctlModel = MmsConnection_readVariable(IedConnection_getMmsConnection(connection), &mmsError, domainId, itemId); if (ctlModel == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: ControlObjectClient_create: failed to get ctlModel from server\n"); goto exit_function; } int ctlModelVal = MmsValue_toUint32(ctlModel); MmsValue_delete(ctlModel); IedClientError error; LinkedList dataDirectory = IedConnection_getDataDirectory(connection, &error, objectReference); if (dataDirectory == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: ControlObjectClient_create: failed to get data directory of control object\n"); goto exit_function; } /* check what control elements are available */ bool hasOper = false; LinkedList element = LinkedList_getNext(dataDirectory); while (element != NULL) { char* objectName = (char*) element->data; if (strcmp(objectName, "Oper") == 0) hasOper = true; element = LinkedList_getNext(element); } LinkedList_destroy(dataDirectory); if (hasOper == false) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: control is missing required element \"Oper\"\n"); goto exit_function; } /* check for time activated control */ bool hasTimeActivatedControl = false; strcpy(itemId, objectReference); strcat(itemId, ".Oper"); dataDirectory = IedConnection_getDataDirectory(connection, &error, itemId); if (dataDirectory == NULL) goto exit_function; element = LinkedList_getNext(dataDirectory); while (element != NULL) { char* objectName = (char*) element->data; if (strcmp(objectName, "operTm") == 0) { hasTimeActivatedControl = true; break; } element = LinkedList_getNext(element); } LinkedList_destroy(dataDirectory); /* get default parameters for Oper control variable */ MmsValue* oper = IedConnection_readObject(connection, &error, itemId, IEC61850_FC_CO); if (oper == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: reading \"Oper\" failed!\n"); goto exit_function; } self = (ControlObjectClient) GLOBAL_CALLOC(1, sizeof(struct sControlObjectClient)); if (self == NULL) goto exit_function; self->objectReference = copyString(objectReference); self->connection = connection; self->ctlModel = (ControlModel) ctlModelVal; self->hasTimeActivatedMode = hasTimeActivatedControl; self->ctlVal = MmsValue_getElement(oper, 0); /* Check for T element type (EntryTime -> Ed.1, Timestamp -> Ed.2) */ MmsValue* t; if (hasTimeActivatedControl) t = MmsValue_getElement(oper, 4); else t = MmsValue_getElement(oper, 3); if (MmsValue_getType(t) == MMS_BINARY_TIME) self->edition = 1; else self->edition = 2; if (DEBUG_IED_CLIENT) printf("IED_CLIENT: Detected edition %i control\n", self->edition); MmsValue_setElement(oper, 0, NULL); MmsValue_delete(oper); private_IedConnection_addControlClient(connection, self); exit_function: return self; }
MmsDataAccessError Reporting_RCBWriteAccessHandler(MmsMapping* self, ReportControl* rc, char* elementName, MmsValue* value, MmsServerConnection* connection) { if (strcmp(elementName, "RptEna") == 0) { if (value->value.boolean == true) { if (rc->enabled == true) return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; if (DEBUG) printf("Activate report for client %s\n", MmsServerConnection_getClientAddress(connection)); MmsValue* dataSetValue; dataSetValue = ReportControl_getRCBValue(rc, "DatSet"); char* dataSetName = MmsValue_toString(dataSetValue); if (rc->isDynamicDataSet) { if (rc->dataSet != NULL) MmsMapping_freeDynamicallyCreatedDataSet(rc->dataSet); } if (dataSetValue != NULL) { DataSet* dataSet = IedModel_lookupDataSet(self->model, dataSetName); if (dataSet == NULL) { dataSet = MmsMapping_getDomainSpecificDataSet(self, dataSetName); if (dataSet == NULL) return DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; rc->isDynamicDataSet = true; } else rc->isDynamicDataSet = false; rc->dataSet = dataSet; rc->inclusionField = MmsValue_newBitString( dataSet->elementCount); rc->clientConnection = connection; // TODO check integrity bit in trigger options MmsValue* intgPd = ReportControl_getRCBValue(rc, "IntgPd"); rc->intgPd = MmsValue_toUint32(intgPd); MmsValue* rptEna = ReportControl_getRCBValue(rc, "RptEna"); MmsValue_update(rptEna, value); MmsValue* bufTm = ReportControl_getRCBValue(rc, "BufTm"); rc->bufTm = MmsValue_toUint32(bufTm); rc->triggerOps = 0; MmsValue* trgOps = ReportControl_getRCBValue(rc, "TrgOps"); if (MmsValue_getBitStringBit(trgOps, 1)) rc->triggerOps += TRG_OPT_DATA_CHANGED; if (MmsValue_getBitStringBit(trgOps, 2)) rc->triggerOps += TRG_OPT_QUALITY_CHANGED; if (MmsValue_getBitStringBit(trgOps, 3)) rc->triggerOps += TRG_OPT_DATA_UPDATE; if (MmsValue_getBitStringBit(trgOps, 4)) rc->triggerOps += TRG_OPT_INTEGRITY; if (MmsValue_getBitStringBit(trgOps, 5)) rc->triggerOps += TRG_OPT_GI; rc->sqNum = 0; rc->inclusionFlags = (ReportInclusionFlag*) calloc(dataSet->elementCount, sizeof(ReportInclusionFlag)); rc->enabled = true; return DATA_ACCESS_ERROR_SUCCESS; } return DATA_ACCESS_ERROR_OBJECT_ATTRIBUTE_INCONSISTENT; } else { if (((rc->enabled) || (rc->reserved)) && (rc->clientConnection != connection)) return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; if (DEBUG) printf("Deactivate report for client %s\n", MmsServerConnection_getClientAddress(connection)); free(rc->inclusionFlags); rc->inclusionFlags = NULL; rc->enabled = false; } } if (strcmp(elementName, "GI") == 0) { if ((rc->enabled) && (rc->clientConnection == connection)) { rc->gi = true; return DATA_ACCESS_ERROR_SUCCESS;; } else return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; } if (rc->enabled == false) { if ((rc->reserved) && (rc->clientConnection != connection)) return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; if (rc->bufferd == false) { if (strcmp(elementName, "Resv") == 0) { rc->reserved = value->value.boolean; if (rc->reserved == true) rc->clientConnection = connection; } } MmsValue* rcbValue = ReportControl_getRCBValue(rc, elementName); if (rcbValue != NULL) MmsValue_update(rcbValue, value); else return DATA_ACCESS_ERROR_OBJECT_VALUE_INVALID; } else return DATA_ACCESS_ERROR_TEMPORARILY_UNAVAILABLE; return DATA_ACCESS_ERROR_SUCCESS;; }