int main(int argc, char** argv) { IedServer iedServer = IedServer_create(&staticIedModel); /* This will create default values for the complete IEC model and installs them in the * MMS server's value cache. */ IedServer_setAllModelDefaultValues(iedServer); /* Get the MMS domain for an IEC 61850 Logical Device */ MmsDomain* sampleDevice = IedServer_getDomain(iedServer, "SampleIEDDevice1"); /* Get the reference to the structured value object */ MmsValue* totW = IedServer_getValue(iedServer, sampleDevice, "MMXU2$MX$TotW"); /* get references to the relevant elements of the copy */ MmsValue* totW_mag_f = MmsValue_getStructElementByIndex(MmsValue_getStructElementByIndex(totW, 0), 0); MmsValue* totW_t = MmsValue_getStructElementByIndex(totW, 2); /* MMS server will be instructed to start listening to client connections. */ IedServer_start(iedServer); running = 1; signal(SIGINT, sigint_handler); float totW_value = 0.f; while (running) { /* Lock the data model - access from MMS Clients will be blocked */ IedServer_lockDataModel(iedServer); /* Update measurement values */ MmsValue_setFloat(totW_mag_f, totW_value); MmsValue_setUtcTime(totW_t, time(NULL)); /* Unlock the data model - access from MMS clients will be processed */ IedServer_unlockDataModel(iedServer); totW_value += 0.1f; Thread_sleep(1000); } /* stop MMS server - close TCP server socket and all client sockets */ IedServer_stop(iedServer); /* Cleanup - free all resources */ IedServer_destroy(iedServer); } /* main() */
void IedServer_updateFloatAttributeValue(IedServer self, DataAttribute* dataAttribute, float value) { assert(MmsValue_getType(dataAttribute->mmsValue) == MMS_FLOAT); assert(dataAttribute != NULL); assert(self != NULL); float currentValue = MmsValue_toFloat(dataAttribute->mmsValue); if (currentValue == value) { checkForUpdateTrigger(self, dataAttribute); } else { MmsValue_setFloat(dataAttribute->mmsValue, value); checkForChangedTriggers(self, dataAttribute); } }
static int parseAllData(uint8_t* buffer, int allDataLength, MmsValue* dataSetValues) { int bufPos = 0; int elementLength = 0; int elementIndex = 0; int maxIndex = MmsValue_getArraySize(dataSetValues) - 1; while (bufPos < allDataLength) { uint8_t tag = buffer[bufPos++]; if (elementIndex > maxIndex) { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: too much elements!\n"); return 0; } MmsValue* value = MmsValue_getElement(dataSetValues, elementIndex); bufPos = BerDecoder_decodeLength(buffer, &elementLength, bufPos, allDataLength); if (bufPos + elementLength > allDataLength) { if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: Malformed message: sub element is too large!\n"); return 0; } switch (tag) { case 0x80: /* reserved for access result */ printf("GOOSE_SUBSCRIBER: found reserved value (tag 0x80)!\n"); break; case 0xa1: /* array */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found array\n"); if (MmsValue_getType(value) == MMS_ARRAY) { if (!parseAllData(buffer + bufPos, elementLength, value)) return -1; } break; case 0xa2: /* structure */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found structure\n"); if (MmsValue_getType(value) == MMS_STRUCTURE) { if (!parseAllData(buffer + bufPos, elementLength, value)) return -1; } break; case 0x83: /* boolean */ if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found boolean\n"); if (MmsValue_getType(value) == MMS_BOOLEAN) { MmsValue_setBoolean(value, BerDecoder_decodeBoolean(buffer, bufPos)); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: message contains value of wrong type!\n"); break; case 0x84: /* BIT STRING */ if (MmsValue_getType(value) == MMS_BIT_STRING) { int padding = buffer[bufPos]; int bitStringLength = (8 * (elementLength - 1)) - padding; if (bitStringLength == value->value.bitString.size) { memcpy(value->value.bitString.buf, buffer + bufPos + 1, elementLength - 1); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("bit-string is of wrong size"); } break; case 0x85: /* integer */ if (MmsValue_getType(value) == MMS_INTEGER) { if (elementLength <= value->value.integer->maxSize) { value->value.integer->size = elementLength; memcpy(value->value.integer->octets, buffer + bufPos, elementLength); } } break; case 0x86: /* unsigned integer */ if (MmsValue_getType(value) == MMS_UNSIGNED) { if (elementLength <= value->value.integer->maxSize) { value->value.integer->size = elementLength; memcpy(value->value.integer->octets, buffer + bufPos, elementLength); } } break; case 0x87: /* Float */ if (MmsValue_getType(value) == MMS_FLOAT) { if (elementLength == 9) { MmsValue_setDouble(value, BerDecoder_decodeDouble(buffer, bufPos)); } else if (elementLength == 5) { MmsValue_setFloat(value, BerDecoder_decodeFloat(buffer, bufPos)); } } break; case 0x89: /* octet string */ if (MmsValue_getType(value) == MMS_OCTET_STRING) { if (elementLength <= value->value.octetString.maxSize) { value->value.octetString.size = elementLength; memcpy(value->value.octetString.buf, buffer + bufPos, elementLength); } } break; case 0x8a: /* visible string */ if (MmsValue_getType(value) == MMS_VISIBLE_STRING) { if (value->value.visibleString.buf != NULL) { if ((int32_t) value->value.visibleString.size >= elementLength) { memcpy(value->value.visibleString.buf, buffer + bufPos, elementLength); value->value.visibleString.buf[elementLength] = 0; } else { GLOBAL_FREEMEM(value->value.visibleString.buf); createNewStringFromBufferElement(value, buffer + bufPos, elementLength); } } else createNewStringFromBufferElement(value, buffer + bufPos, elementLength); } break; case 0x8c: /* binary time */ if (MmsValue_getType(value) == MMS_BINARY_TIME) { if ((elementLength == 4) || (elementLength == 6)) { memcpy(value->value.binaryTime.buf, buffer + bufPos, elementLength); } } break; case 0x91: /* Utctime */ if (elementLength == 8) { if (MmsValue_getType(value) == MMS_UTC_TIME) { MmsValue_setUtcTimeByBuffer(value, buffer + bufPos); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: message contains value of wrong type!\n"); } else if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: UTCTime element is of wrong size!\n"); break; default: if (DEBUG_GOOSE_SUBSCRIBER) printf("GOOSE_SUBSCRIBER: found unkown tag %02x\n", tag); break; } bufPos += elementLength; elementIndex++; } return 1; }