MmsValue* IedConnection_readObject(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc) { char domainIdBuffer[65]; char itemIdBuffer[129]; MmsValue* value = NULL; char* domainId; char* itemId; domainId = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainIdBuffer); itemId = MmsMapping_createMmsVariableNameFromObjectReference(objectReference, fc, itemIdBuffer); if ((domainId == NULL) || (itemId == NULL)) { *error = IED_ERROR_OBJECT_REFERENCE_INVALID; return NULL; } MmsError mmsError; value = MmsConnection_readVariable(self->connection, &mmsError, domainId, itemId); if (value != NULL) { *error = IED_ERROR_OK; } else *error = iedConnection_mapMmsErrorToIedError(mmsError); return value; }
void IedConnection_deleteDataSet(IedConnection self, IedClientError* error, char* dataSetReference) { char domainId[65]; char itemId[129]; bool isAssociationSpecific = false; if (dataSetReference[0] != '@') { MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainId); copyStringToBuffer(dataSetReference + strlen(domainId) + 1, itemId); StringUtils_replace(itemId, '.', '$'); } else { strncpy(itemId, dataSetReference, 128); itemId[128] = 0; isAssociationSpecific = true; } MmsError mmsError; if (isAssociationSpecific) MmsConnection_deleteAssociationSpecificNamedVariableList(self->connection, &mmsError, itemId); else MmsConnection_deleteNamedVariableList(self->connection, &mmsError, domainId, itemId); *error = iedConnection_mapMmsErrorToIedError(mmsError); }
MmsVariableSpecification* IedConnection_getVariableSpecification(IedConnection self, IedClientError* error, char* objectReference, FunctionalConstraint fc) { char domainIdBuffer[65]; char itemIdBuffer[129]; char* domainId; char* itemId; MmsError mmsError; MmsVariableSpecification* varSpec = NULL; domainId = MmsMapping_getMmsDomainFromObjectReference(objectReference, domainIdBuffer); itemId = MmsMapping_createMmsVariableNameFromObjectReference(objectReference, fc, itemIdBuffer); if ((domainId == NULL) || (itemId == NULL)) { *error = IED_ERROR_OBJECT_REFERENCE_INVALID; goto cleanup_and_exit; } varSpec = MmsConnection_getVariableAccessAttributes(self->connection, &mmsError, domainId, itemId); if (varSpec != NULL) { *error = IED_ERROR_OK; } else *error = iedConnection_mapMmsErrorToIedError(mmsError); cleanup_and_exit: return varSpec; }
ClientReportControlBlock IedConnection_getRCBValues(IedConnection self, IedClientError* error, char* rcbReference, ClientReportControlBlock updateRcb) { MmsError mmsError = MMS_ERROR_NONE; ClientReportControlBlock returnRcb = updateRcb; char domainId[65]; char itemId[129]; MmsMapping_getMmsDomainFromObjectReference(rcbReference, domainId); strcpy(itemId, rcbReference + strlen(domainId) + 1); StringUtils_replace(itemId, '.', '$'); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: readRCBValues for %s\n", rcbReference); MmsValue* rcb = MmsConnection_readVariable(self->connection, &mmsError, domainId, itemId); if (mmsError != MMS_ERROR_NONE) { *error = iedConnection_mapMmsErrorToIedError(mmsError); return NULL; } if (rcb == NULL) { *error = IED_ERROR_OBJECT_DOES_NOT_EXIST; return NULL; } if (MmsValue_getType(rcb) != MMS_STRUCTURE) { if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: getRCBValues returned wrong type!\n"); MmsValue_delete(rcb); *error = IED_ERROR_UNKNOWN; return NULL; } if (returnRcb == NULL) returnRcb = ClientReportControlBlock_create(rcbReference); private_ClientReportControlBlock_updateValues(returnRcb, rcb); MmsValue_delete(rcb); *error = IED_ERROR_OK; return returnRcb; }
ClientDataSet IedConnection_readDataSetValues(IedConnection self, IedClientError* error, char* dataSetReference, ClientDataSet dataSet) { char domainIdBuffer[65]; char itemIdBuffer[129]; char* domainId = NULL; char* itemId = NULL; bool isAssociationSpecific = false; if (dataSetReference[0] != '@') { domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer); itemId = copyStringToBuffer(dataSetReference + strlen(domainId) + 1, itemIdBuffer); StringUtils_replace(itemId, '.', '$'); } else { itemId = dataSetReference; isAssociationSpecific = true; } MmsError mmsError; MmsValue* dataSetVal; if (isAssociationSpecific) dataSetVal = MmsConnection_readNamedVariableListValuesAssociationSpecific(self->connection, &mmsError, itemId, true); else dataSetVal= MmsConnection_readNamedVariableListValues(self->connection, &mmsError, domainId, itemId, true); if (dataSetVal == NULL) { *error = iedConnection_mapMmsErrorToIedError(mmsError); goto cleanup_and_exit; } else *error = IED_ERROR_OK; if (dataSet == NULL) { dataSet = ClientDataSet_create(dataSetReference); ClientDataSet_setDataSetValues(dataSet, dataSetVal); } else { MmsValue* dataSetValues = ClientDataSet_getValues(dataSet); MmsValue_update(dataSetValues, dataSetVal); } cleanup_and_exit: return dataSet; }
void IedConnection_createDataSet(IedConnection self, IedClientError* error, char* dataSetReference, LinkedList /* <char*> */dataSetElements) { char domainIdBuffer[65]; char itemIdBuffer[129]; char* domainId; char* itemId; bool isAssociationSpecific = false; if (dataSetReference[0] != '@') { domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer); itemId = copyStringToBuffer(dataSetReference + strlen(domainId) + 1, itemIdBuffer); StringUtils_replace(itemId, '.', '$'); } else { itemId = dataSetReference; isAssociationSpecific = true; } MmsError mmsError; LinkedList dataSetEntries = LinkedList_create(); LinkedList dataSetElement = LinkedList_getNext(dataSetElements); while (dataSetElement != NULL) { MmsVariableAccessSpecification* dataSetEntry = MmsMapping_ObjectReferenceToVariableAccessSpec((char*) dataSetElement->data); LinkedList_add(dataSetEntries, (void*) dataSetEntry); dataSetElement = LinkedList_getNext(dataSetElement); } if (isAssociationSpecific) MmsConnection_defineNamedVariableListAssociationSpecific(self->connection, &mmsError, itemId, dataSetEntries); else MmsConnection_defineNamedVariableList(self->connection, &mmsError, domainId, itemId, dataSetEntries); /* delete list and all elements */ LinkedList_destroyDeep(dataSetEntries, (LinkedListValueDeleteFunction) MmsVariableAccessSpecification_destroy); *error = iedConnection_mapMmsErrorToIedError(mmsError); }
static void createDataSetsFromLogicalNode(MmsDevice* mmsDevice, LogicalNode* logicalNode, MmsDomain* domain) { if (logicalNode->dataSets != NULL) { int dataSetCount = ArrayList_listSize((void**) (logicalNode->dataSets)); int i; for (i = 0; i < dataSetCount; i++) { char* dataSetName = createString(3, logicalNode->name, "$", logicalNode->dataSets[i]->name); MmsNamedVariableList varList = MmsNamedVariableList_create(dataSetName, false); int fcdaCount = ArrayList_listSize((void**) (logicalNode->dataSets[i]->fcda)); int j; MmsNamedVariableListEntry variableListEntry; for (j = 0; j < fcdaCount; j++) { char* variableName = MmsMapping_createMmsVariableNameFromObjectReference( logicalNode->dataSets[i]->fcda[j]->objectReference, logicalNode->dataSets[i]->fcda[j]->fc); char* domainName = MmsMapping_getMmsDomainFromObjectReference( logicalNode->dataSets[i]->fcda[j]->objectReference); MmsDomain* variableDomain; if (domainName != NULL) variableDomain = MmsDevice_getDomain(mmsDevice, domainName); else variableDomain = domain; variableListEntry = MmsNamedVariableListEntry_create(variableDomain, variableName); MmsNamedVariableList_addVariable(varList, variableListEntry); free(domainName); free(variableName); } MmsDomain_addNamedVariableList(domain, varList); free(dataSetName); } } }
static void installDefaultValuesForDataAttribute(IedServer self, DataAttribute* dataAttribute, char* objectReference, int position) { sprintf(objectReference + position, ".%s", dataAttribute->name); char mmsVariableName[65]; /* maximum size is 64 according to 61850-8-1 */ MmsValue* value = dataAttribute->mmsValue; MmsMapping_createMmsVariableNameFromObjectReference(objectReference, dataAttribute->fc, mmsVariableName); char domainName[65]; MmsMapping_getMmsDomainFromObjectReference(objectReference, domainName); MmsDomain* domain = MmsDevice_getDomain(self->mmsDevice, domainName); if (domain == NULL) { if (DEBUG_IED_SERVER) printf("Error domain (%s) not found!\n", domainName); return; } MmsValue* cacheValue = MmsServer_getValueFromCache(self->mmsServer, domain, mmsVariableName); dataAttribute->mmsValue = cacheValue; if (value != NULL) { MmsValue_update(cacheValue, value); MmsValue_delete(value); } int childPosition = strlen(objectReference); DataAttribute* subDataAttribute = (DataAttribute*) dataAttribute->firstChild; while (subDataAttribute != NULL) { installDefaultValuesForDataAttribute(self, subDataAttribute, objectReference, childPosition); subDataAttribute = (DataAttribute*) subDataAttribute->sibling; } }
bool ControlObjectClient_cancel(ControlObjectClient self) { resetLastApplError(self); MmsValue* cancelParameters; if (self->hasTimeActivatedMode) cancelParameters = MmsValue_createEmptyStructure(6); else cancelParameters = MmsValue_createEmptyStructure(5); MmsValue_setElement(cancelParameters, 0, self->ctlVal); int index = 1; if (self->hasTimeActivatedMode) { MmsValue* operTm = MmsValue_newUtcTimeByMsTime(self->opertime); MmsValue_setElement(cancelParameters, index++, operTm); } MmsValue* origin = createOriginValue(self); MmsValue_setElement(cancelParameters, index++, origin); MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum); MmsValue_setElement(cancelParameters, index++, ctlNum); uint64_t timestamp = Hal_getTimeInMs(); MmsValue* ctlTime; if (self->edition == 2) ctlTime = MmsValue_newUtcTimeByMsTime(timestamp); else { ctlTime = MmsValue_newBinaryTime(false); MmsValue_setBinaryTime(ctlTime, timestamp); } MmsValue_setElement(cancelParameters, index++, ctlTime); MmsValue* ctlTest = MmsValue_newBoolean(self->test); MmsValue_setElement(cancelParameters, index++, ctlTest); char domainId[65]; char itemId[65]; MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId); convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO"); strncat(itemId, "$Cancel", 64); if (DEBUG_IED_CLIENT) printf("IED_CLIENT: cancel: %s/%s\n", domainId, itemId); MmsError mmsError; MmsConnection_writeVariable(IedConnection_getMmsConnection(self->connection), &mmsError, domainId, itemId, cancelParameters); MmsValue_setElement(cancelParameters, 0, NULL); MmsValue_delete(cancelParameters); if (mmsError != MMS_ERROR_NONE) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: cancel failed!\n"); return false; } return true; }
bool ControlObjectClient_select(ControlObjectClient self) { resetLastApplError(self); char domainId[65]; char itemId[65]; MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId); convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO"); strncat(itemId, "$SBO", 64); if (DEBUG_IED_CLIENT) printf("IED_CLIENT: select: %s/%s\n", domainId, itemId); MmsError mmsError; MmsValue* value = MmsConnection_readVariable(IedConnection_getMmsConnection(self->connection), &mmsError, domainId, itemId); bool selected = false; self->ctlNum++; if (value == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: select: read SBO failed!\n"); goto exit_function; } char sboReference[130]; snprintf(sboReference, 129, "%s/%s", domainId, itemId); if (MmsValue_getType(value) == MMS_VISIBLE_STRING) { if (strcmp(MmsValue_toString(value), "") == 0) { if (DEBUG_IED_CLIENT) printf("select-response-\n"); } else if (strcmp(MmsValue_toString(value), sboReference)) { if (DEBUG_IED_CLIENT) printf("select-response+: (%s)\n", MmsValue_toString(value)); selected = true; } else { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: select-response: (%s)\n", MmsValue_toString(value)); } } else { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: select: unexpected response from server!\n"); } MmsValue_delete(value); exit_function: return selected; }
bool ControlObjectClient_operate(ControlObjectClient self, MmsValue* ctlVal, uint64_t operTime) { bool success = false; if (ctlVal == NULL) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: operate - (ctlVal == NULL)!\n"); goto exit_function; } resetLastApplError(self); MmsValue* operParameters; if (self->hasTimeActivatedMode) operParameters = MmsValue_createEmptyStructure(7); else operParameters = MmsValue_createEmptyStructure(6); MmsValue_setElement(operParameters, 0, ctlVal); int index = 1; if (self->hasTimeActivatedMode) { MmsValue* operTm = MmsValue_newUtcTimeByMsTime(operTime); MmsValue_setElement(operParameters, index++, operTm); } MmsValue* origin = createOriginValue(self); MmsValue_setElement(operParameters, index++, origin); if (!((self->ctlModel == CONTROL_MODEL_SBO_NORMAL) || (self->ctlModel == CONTROL_MODEL_SBO_ENHANCED))) { self->ctlNum++; } MmsValue* ctlNum = MmsValue_newUnsignedFromUint32(self->ctlNum); MmsValue_setElement(operParameters, index++, ctlNum); uint64_t timestamp = Hal_getTimeInMs(); MmsValue* ctlTime; if (self->edition == 2) ctlTime = MmsValue_newUtcTimeByMsTime(timestamp); else { ctlTime = MmsValue_newBinaryTime(false); MmsValue_setBinaryTime(ctlTime, timestamp); } MmsValue_setElement(operParameters, index++, ctlTime); MmsValue* ctlTest = MmsValue_newBoolean(self->test); MmsValue_setElement(operParameters, index++, ctlTest); MmsValue* check = MmsValue_newBitString(2); MmsValue_setBitStringBit(check, 1, self->interlockCheck); MmsValue_setBitStringBit(check, 0, self->synchroCheck); MmsValue_setElement(operParameters, index++, check); char domainId[65]; char itemId[65]; MmsMapping_getMmsDomainFromObjectReference(self->objectReference, domainId); convertToMmsAndInsertFC(itemId, self->objectReference + strlen(domainId) + 1, "CO"); int controlObjectItemIdLen = strlen(itemId); strncat(itemId, "$Oper", 64 - controlObjectItemIdLen); if (DEBUG_IED_CLIENT) printf("IED_CLIENT: operate: %s/%s\n", domainId, itemId); MmsError mmsError; MmsConnection_writeVariable(IedConnection_getMmsConnection(self->connection), &mmsError, domainId, itemId, operParameters); MmsValue_setElement(operParameters, 0, NULL); MmsValue_delete(operParameters); if (mmsError != MMS_ERROR_NONE) { if (DEBUG_IED_CLIENT) printf("IED_CLIENT: operate failed!\n"); goto exit_function; } MmsValue_update(self->ctlVal, ctlVal); self->opertime = operTime; success = true; exit_function: return success; }
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; }
LinkedList /* <char*> */ IedConnection_getDataSetDirectory(IedConnection self, IedClientError* error, char* dataSetReference, bool* isDeletable) { bool deletable = false; LinkedList dataSetMembers = NULL; char domainIdBuffer[65]; char itemIdBuffer[129]; char* domainId = NULL; char* itemId = NULL; bool isAssociationSpecific = false; if (dataSetReference[0] != '@') { domainId = MmsMapping_getMmsDomainFromObjectReference(dataSetReference, domainIdBuffer); itemId = copyStringToBuffer(dataSetReference + strlen(domainId) + 1, itemIdBuffer); StringUtils_replace(itemId, '.', '$'); } else { itemId = dataSetReference; isAssociationSpecific = true; } MmsError mmsError; LinkedList entries; if (isAssociationSpecific) entries = MmsConnection_readNamedVariableListDirectoryAssociationSpecific(self->connection, &mmsError, itemId, &deletable); else entries = MmsConnection_readNamedVariableListDirectory(self->connection, &mmsError, domainId, itemId, &deletable); if (mmsError == MMS_ERROR_NONE) { LinkedList entry = LinkedList_getNext(entries); dataSetMembers = LinkedList_create(); while (entry != NULL) { MmsVariableAccessSpecification* varAccessSpec = (MmsVariableAccessSpecification*) entry->data; char* objectReference = MmsMapping_varAccessSpecToObjectReference(varAccessSpec); LinkedList_add(dataSetMembers, objectReference); entry = LinkedList_getNext(entry); } if (isDeletable != NULL) *isDeletable = deletable; LinkedList_destroyDeep(entries, (LinkedListValueDeleteFunction) MmsVariableAccessSpecification_destroy); } *error = iedConnection_mapMmsErrorToIedError(mmsError); return dataSetMembers; }
void IedConnection_setRCBValues(IedConnection self, IedClientError* error, ClientReportControlBlock rcb, uint32_t parametersMask, bool singleRequest) { *error = IED_ERROR_OK; MmsError mmsError = MMS_ERROR_NONE; bool isBuffered = ClientReportControlBlock_isBuffered(rcb); char domainId[65]; char itemId[129]; char* rcbReference = ClientReportControlBlock_getObjectReference(rcb); MmsMapping_getMmsDomainFromObjectReference(rcbReference, domainId); strcpy(itemId, rcbReference + strlen(domainId) + 1); StringUtils_replace(itemId, '.', '$'); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: setRCBValues for %s\n", rcbReference); int itemIdLen = strlen(itemId); /* create the list of requested itemIds references */ LinkedList itemIds = LinkedList_create(); LinkedList values = LinkedList_create(); /* add resv/resvTms as first element and rptEna as last element */ if (parametersMask & RCB_ELEMENT_RESV) { if (isBuffered) goto error_invalid_parameter; strcpy(itemId + itemIdLen, "$Resv"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->resv); } if (parametersMask & RCB_ELEMENT_RESV_TMS) { if (!isBuffered) goto error_invalid_parameter; strcpy(itemId + itemIdLen, "$ResvTms"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->resvTms); } if (parametersMask & RCB_ELEMENT_RPT_ID) { strcpy(itemId + itemIdLen, "$RptID"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->rptId); } if (parametersMask & RCB_ELEMENT_DATSET) { strcpy(itemId + itemIdLen, "$DatSet"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->datSet); } if (parametersMask & RCB_ELEMENT_ENTRY_ID) { strcpy(itemId + itemIdLen, "$EntryID"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->entryId); } if (parametersMask & RCB_ELEMENT_OPT_FLDS) { strcpy(itemId + itemIdLen, "$OptFlds"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->optFlds); } if (parametersMask & RCB_ELEMENT_BUF_TM) { strcpy(itemId + itemIdLen, "$BufTm"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->bufTm); } if (parametersMask & RCB_ELEMENT_TRG_OPS) { strcpy(itemId + itemIdLen, "$TrgOps"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->trgOps); } if (parametersMask & RCB_ELEMENT_INTG_PD) { strcpy(itemId + itemIdLen, "$IntgPd"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->intgPd); } if (parametersMask & RCB_ELEMENT_GI) { strcpy(itemId + itemIdLen, "$GI"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->gi); } if (parametersMask & RCB_ELEMENT_PURGE_BUF) { if (!isBuffered) goto error_invalid_parameter; strcpy(itemId + itemIdLen, "$PurgeBuf"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->purgeBuf); } if (parametersMask & RCB_ELEMENT_TIME_OF_ENTRY) { if (!isBuffered) goto error_invalid_parameter; strcpy(itemId + itemIdLen, "$TimeOfEntry"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->timeOfEntry); } if (parametersMask & RCB_ELEMENT_RPT_ENA) { strcpy(itemId + itemIdLen, "$RptEna"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, rcb->rptEna); } if (singleRequest) { LinkedList accessResults = NULL; MmsConnection_writeMultipleVariables(self->connection, &mmsError, domainId, itemIds, values, &accessResults); if (accessResults != NULL) LinkedList_destroyDeep(accessResults, (LinkedListValueDeleteFunction) MmsValue_delete); *error = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } else { LinkedList itemIdElement = LinkedList_getNext(itemIds); LinkedList valueElement = LinkedList_getNext(values); while (itemIdElement != NULL) { char* rcbItemId = (char*) itemIdElement->data; MmsValue* value = (MmsValue*) valueElement->data; MmsConnection_writeVariable(self->connection, &mmsError, domainId, rcbItemId, value); if (mmsError != MMS_ERROR_NONE) break; itemIdElement = LinkedList_getNext(itemIdElement); valueElement = LinkedList_getNext(valueElement); } *error = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } error_invalid_parameter: *error = IED_ERROR_USER_PROVIDED_INVALID_ARGUMENT; exit_function: LinkedList_destroy(itemIds); LinkedList_destroyStatic(values); }
void IedConnection_setGoCBValues(IedConnection self, IedClientError* error, ClientGooseControlBlock goCB, uint32_t parametersMask, bool singleRequest) { *error = IED_ERROR_OK; MmsError mmsError = MMS_ERROR_NONE; char domainId[65]; char itemId[129]; MmsMapping_getMmsDomainFromObjectReference(goCB->objectReference, domainId); char* itemIdStart = goCB->objectReference + strlen(domainId) + 1; char* separator = strchr(itemIdStart, '.'); if (separator == NULL) { *error = IED_ERROR_OBJECT_REFERENCE_INVALID; return; } int separatorOffset = separator - itemIdStart; memcpy(itemId, itemIdStart, separatorOffset); itemId[separatorOffset] = '$'; itemId[separatorOffset + 1] = 'G'; itemId[separatorOffset + 2] = 'O'; itemId[separatorOffset + 3] = '$'; strcpy(itemId + separatorOffset + 4, separator + 1); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: setGoCBValues for %s\n", goCB->objectReference); int itemIdLen = strlen(itemId); /* create the list of requested itemIds references */ LinkedList itemIds = LinkedList_create(); LinkedList values = LinkedList_create(); /* add rGoEna as last element */ if (parametersMask & GOCB_ELEMENT_GO_ID) { strcpy(itemId + itemIdLen, "$GoID"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->goID); } if (parametersMask & GOCB_ELEMENT_DATSET) { strcpy(itemId + itemIdLen, "$DatSet"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->datSet); } if (parametersMask & GOCB_ELEMENT_CONF_REV) { strcpy(itemId + itemIdLen, "$ConfRev"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->confRev); } if (parametersMask & GOCB_ELEMENT_NDS_COMM) { strcpy(itemId + itemIdLen, "$NdsCom"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->ndsCom); } if (parametersMask & GOCB_ELEMENT_DST_ADDRESS) { strcpy(itemId + itemIdLen, "$DstAddress"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->dstAddress); } if (parametersMask & GOCB_ELEMENT_MIN_TIME) { strcpy(itemId + itemIdLen, "$MinTime"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->minTime); } if (parametersMask & GOCB_ELEMENT_MAX_TIME) { strcpy(itemId + itemIdLen, "$MaxTime"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->maxTime); } if (parametersMask & GOCB_ELEMENT_FIXED_OFFS) { strcpy(itemId + itemIdLen, "$FixedOffs"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->fixedOffs); } if (parametersMask & GOCB_ELEMENT_GO_ENA) { strcpy(itemId + itemIdLen, "$GoEna"); LinkedList_add(itemIds, copyString(itemId)); LinkedList_add(values, goCB->goEna); } if (singleRequest) { LinkedList accessResults = NULL; MmsConnection_writeMultipleVariables(self->connection, &mmsError, domainId, itemIds, values, &accessResults); if (accessResults != NULL) { LinkedList element = LinkedList_getNext(accessResults); while (element != NULL) { MmsValue* accessResult = (MmsValue*) element->data; if (MmsValue_getDataAccessError(accessResult) != DATA_ACCESS_ERROR_SUCCESS) { mmsError = MMS_ERROR_ACCESS_OBJECT_NON_EXISTENT; break; } element = LinkedList_getNext(element); } LinkedList_destroyDeep(accessResults, (LinkedListValueDeleteFunction) MmsValue_delete); } *error = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } else { LinkedList itemIdElement = LinkedList_getNext(itemIds); LinkedList valueElement = LinkedList_getNext(values); while (itemIdElement != NULL) { char* rcbItemId = (char*) itemIdElement->data; MmsValue* value = (MmsValue*) valueElement->data; MmsConnection_writeVariable(self->connection, &mmsError, domainId, rcbItemId, value); if (mmsError != MMS_ERROR_NONE) break; itemIdElement = LinkedList_getNext(itemIdElement); valueElement = LinkedList_getNext(valueElement); } *error = iedConnection_mapMmsErrorToIedError(mmsError); goto exit_function; } exit_function: LinkedList_destroy(itemIds); LinkedList_destroyStatic(values); }
ClientGooseControlBlock IedConnection_getGoCBValues(IedConnection self, IedClientError* error, const char* goCBReference, ClientGooseControlBlock updateGoCB) { MmsError mmsError = MMS_ERROR_NONE; *error = IED_ERROR_OK; ClientGooseControlBlock returnGoCB = updateGoCB; char domainId[65]; char itemId[129]; MmsMapping_getMmsDomainFromObjectReference(goCBReference, domainId); const char* itemIdStart = goCBReference + strlen(domainId) + 1; const char* separator = strchr(itemIdStart, '.'); if (separator == NULL) { *error = IED_ERROR_OBJECT_REFERENCE_INVALID; return NULL; } int separatorOffset = separator - itemIdStart; memcpy(itemId, itemIdStart, separatorOffset); itemId[separatorOffset] = '$'; itemId[separatorOffset + 1] = 'G'; itemId[separatorOffset + 2] = 'O'; itemId[separatorOffset + 3] = '$'; strcpy(itemId + separatorOffset + 4, separator + 1); if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: getGoCBValues for %s\n", goCBReference); MmsValue* goCB = MmsConnection_readVariable(self->connection, &mmsError, domainId, itemId); if (mmsError != MMS_ERROR_NONE) { *error = iedConnection_mapMmsErrorToIedError(mmsError); return NULL; } if (goCB == NULL) { *error = IED_ERROR_OBJECT_DOES_NOT_EXIST; return NULL; } if (MmsValue_getType(goCB) != MMS_STRUCTURE) { if (DEBUG_IED_CLIENT) printf("DEBUG_IED_CLIENT: getRCBValues returned wrong type!\n"); MmsValue_delete(goCB); *error = IED_ERROR_UNKNOWN; return NULL; } if (returnGoCB == NULL) returnGoCB = ClientGooseControlBlock_create(goCBReference); if (private_ClientGooseControlBlock_updateValues(returnGoCB, goCB)) *error = IED_ERROR_OK; else *error = IED_ERROR_UNEXPECTED_VALUE_RECEIVED; MmsValue_delete(goCB); return returnGoCB; }