#include "iec_include.h" typedef struct sASDUFrame* ASDUFrame; struct sASDUFrame { FrameVFT virtualFunctionTable; CS101_ASDU asdu; }; static void asduFrame_destroy(Frame self) { UNUSED_PARAMETER(self); } static void asduFrame_setNextByte(Frame self, uint8_t byte) { ASDUFrame frame = (ASDUFrame) self; frame->asdu->payload[frame->asdu->payloadSize++] = byte; } static void asduFrame_appendBytes(Frame self, const uint8_t* bytes, int numberOfBytes) { ASDUFrame frame = (ASDUFrame) self; uint8_t* target = frame->asdu->payload + frame->asdu->payloadSize; int i; for (i = 0; i < numberOfBytes; i++) target[i] = bytes[i]; frame->asdu->payloadSize += numberOfBytes; } static int asduFrame_getSpaceLeft(Frame self) { ASDUFrame frame = (ASDUFrame) self; return (frame->asdu->parameters->maxSizeOfASDU - frame->asdu->payloadSize - frame->asdu->asduHeaderLength); } struct sFrameVFT asduFrameVFT = { asduFrame_destroy, NULL, asduFrame_setNextByte, asduFrame_appendBytes, NULL, NULL, asduFrame_getSpaceLeft }; CS101_ASDU CS101_ASDU_create(CS101_AppLayerParameters parameters, bool isSequence, CS101_CauseOfTransmission cot, int oa, int ca, bool isTest, bool isNegative) { CS101_StaticASDU self = (CS101_StaticASDU) GLOBAL_MALLOC(sizeof(sCS101_StaticASDU)); if (self != NULL) CS101_ASDU_initializeStatic(self, parameters, isSequence, cot, oa, ca, isTest, isNegative); return (CS101_ASDU) self; } CS101_ASDU CS101_ASDU_clone(CS101_ASDU self, CS101_StaticASDU clone) { if (clone == NULL) { clone = (CS101_StaticASDU) GLOBAL_MALLOC(sizeof(sCS101_StaticASDU)); } if (clone) { CS101_ASDU_initializeStatic(clone, self->parameters, CS101_ASDU_isSequence(self), CS101_ASDU_getCOT(self), CS101_ASDU_getOA(self), CS101_ASDU_getCA(self), CS101_ASDU_isTest(self), CS101_ASDU_isNegative(self)); uint8_t* payload = CS101_ASDU_getPayload(self); int payloadSize = CS101_ASDU_getPayloadSize(self); CS101_ASDU_setTypeID((CS101_ASDU)clone, CS101_ASDU_getTypeID(self)); CS101_ASDU_setNumberOfElements((CS101_ASDU)clone, CS101_ASDU_getNumberOfElements(self)); CS101_ASDU_addPayload((CS101_ASDU)clone, payload, payloadSize); } return (CS101_ASDU) clone; } CS101_ASDU CS101_ASDU_initializeStatic(CS101_StaticASDU self, CS101_AppLayerParameters parameters, bool isSequence, CS101_CauseOfTransmission cot, int oa, int ca, bool isTest, bool isNegative) { int asduHeaderLength = 2 + parameters->sizeOfCOT + parameters->sizeOfCA; self->encodedData[0] = (uint8_t) 0; if (isSequence) self->encodedData[1] = 0x80; else self->encodedData[1] = 0; self->encodedData[2] = (uint8_t) (cot & 0x3f); if (isTest) self->encodedData[2] |= 0x80; if (isNegative) self->encodedData[2] |= 0x40; int caIndex; if (parameters->sizeOfCOT > 1) { self->encodedData[3] = (uint8_t) oa; caIndex = 4; } else caIndex = 3; self->encodedData[caIndex] = ca % 0x100; if (parameters->sizeOfCA > 1) self->encodedData[caIndex + 1] = ca / 0x100; self->asdu = self->encodedData; self->asduHeaderLength = asduHeaderLength; self->payload = self->encodedData + asduHeaderLength; self->payloadSize = 0; self->parameters = parameters; return (CS101_ASDU) self; } void CS101_ASDU_destroy(CS101_ASDU self) { GLOBAL_FREEMEM(self); } void CS101_ASDU_encode(CS101_ASDU self, Frame frame) { Frame_appendBytes(frame, self->asdu, self->asduHeaderLength + self->payloadSize); } CS101_ASDU CS101_ASDU_createFromBuffer(CS101_AppLayerParameters parameters, uint8_t* msg, int msgLength) { int asduHeaderLength = 2 + parameters->sizeOfCOT + parameters->sizeOfCA; if (msgLength < asduHeaderLength) return NULL; CS101_ASDU self = (CS101_ASDU) GLOBAL_MALLOC(sizeof(struct sCS101_ASDU)); if (self != NULL) { self->parameters = parameters; self->asdu = msg; self->asduHeaderLength = asduHeaderLength; self->payload = msg + asduHeaderLength; self->payloadSize = msgLength - asduHeaderLength; } return self; } uint8_t* CS101_ASDU_getPayload(CS101_ASDU self) { return self->payload; } int CS101_ASDU_getPayloadSize(CS101_ASDU self) { return self->payloadSize; } bool CS101_ASDU_addPayload(CS101_ASDU self, uint8_t* buffer, int size) { if (buffer == NULL) return false; if (self->payloadSize + self->asduHeaderLength + size <= 256) { memcpy(self->payload + self->payloadSize, buffer, size); self->payloadSize += size; return true; } else return false; } static int getFirstIOA(CS101_ASDU self) { int startIndex = self->asduHeaderLength; int ioa = self->asdu[startIndex]; if (self->parameters->sizeOfIOA > 1) ioa += (self->asdu [startIndex + 1] * 0x100); if (self->parameters->sizeOfIOA > 2) ioa += (self->asdu [startIndex + 2] * 0x10000); return ioa; } bool CS101_ASDU_addInformationObject(CS101_ASDU self, InformationObject io) { struct sASDUFrame asduFrame = { &asduFrameVFT, self }; bool encoded = false; int numberOfElements = CS101_ASDU_getNumberOfElements(self); if (numberOfElements == 0) { self->asdu[0] = (uint8_t) InformationObject_getType(io); encoded = InformationObject_encode(io, (Frame) &asduFrame, self->parameters, false); } else if (numberOfElements < 0x7f) { /* Check if type of information object is matching ASDU type */ if (self->asdu[0] == (uint8_t) InformationObject_getType(io)) { if (CS101_ASDU_isSequence(self)) { /* check that new information object has correct IOA */ if (InformationObject_getObjectAddress(io) == (getFirstIOA(self) + CS101_ASDU_getNumberOfElements(self))) encoded = InformationObject_encode(io, (Frame) &asduFrame, self->parameters, true); else encoded = false; } else { encoded = InformationObject_encode(io, (Frame) &asduFrame, self->parameters, false);; } } } if (encoded) self->asdu[1]++; /* increase number of elements in VSQ */ return encoded; } void CS101_ASDU_removeAllElements(CS101_ASDU self) { self->asdu[1] = (self->asdu[1] & 0x80); self->payloadSize = 0; } bool CS101_ASDU_isTest(CS101_ASDU self) { if ((self->asdu[2] & 0x80) == 0x80) return true; else return false; } void CS101_ASDU_setTest(CS101_ASDU self, bool value) { if (value) self->asdu[2] |= 0x80; else self->asdu[2] &= ~(0x80); } bool CS101_ASDU_isNegative(CS101_ASDU self) { if ((self->asdu[2] & 0x40) == 0x40) return true; else return false; } void CS101_ASDU_setNegative(CS101_ASDU self, bool value) { if (value) self->asdu[2] |= 0x40; else self->asdu[2] &= ~(0x40); } int CS101_ASDU_getOA(CS101_ASDU self) { if (self->parameters->sizeOfCOT < 2) return -1; else return (int) self->asdu[3]; } CS101_CauseOfTransmission CS101_ASDU_getCOT(CS101_ASDU self) { return (CS101_CauseOfTransmission) (self->asdu[2] & 0x3f); } void CS101_ASDU_setCOT(CS101_ASDU self, CS101_CauseOfTransmission value) { uint8_t cot = self->asdu[2] & 0xc0; cot += ((int) value) & 0x3f; self->asdu[2] = cot; } int CS101_ASDU_getCA(CS101_ASDU self) { int caIndex = 2 + self->parameters->sizeOfCOT; int ca = self->asdu[caIndex]; if (self->parameters->sizeOfCA > 1) ca += (self->asdu[caIndex + 1] * 0x100); return ca; } void CS101_ASDU_setCA(CS101_ASDU self, int ca) { int caIndex = 2 + self->parameters->sizeOfCOT; int setCa = ca; /* Check if CA is in range and adjust if not */ if (ca < 0) setCa = 0; else { if (self->parameters->sizeOfCA == 1) { if (ca > 255) setCa = 255; } else if (self->parameters->sizeOfCA > 1) { if (ca > 65535) setCa = 65535; } } if (self->parameters->sizeOfCA == 1) { self->asdu[caIndex] = (uint8_t) setCa; } else { self->asdu[caIndex] = (uint8_t) (setCa % 0x100); self->asdu[caIndex + 1] = (uint8_t) (setCa / 0x100); } } IEC60870_5_TypeID CS101_ASDU_getTypeID(CS101_ASDU self) { return (TypeID) (self->asdu[0]); } void CS101_ASDU_setTypeID(CS101_ASDU self, IEC60870_5_TypeID typeId) { self->asdu[0] = (uint8_t) typeId; } bool CS101_ASDU_isSequence(CS101_ASDU self) { if ((self->asdu[1] & 0x80) != 0) return true; else return false; } void CS101_ASDU_setSequence(CS101_ASDU self, bool isSequence) { if (isSequence) self->asdu[1] |= 0x80; else self->asdu[1] &= 0x7f; } int CS101_ASDU_getNumberOfElements(CS101_ASDU self) { return (self->asdu[1] & 0x7f); } void CS101_ASDU_setNumberOfElements(CS101_ASDU self, int numberOfElements) { self->asdu[1] &= 0x80; self->asdu[1] |= ((uint8_t) numberOfElements) & 0x7f; } InformationObject CS101_ASDU_getElement(CS101_ASDU self, int index) { return CS101_ASDU_getElementEx(self, NULL, index); } InformationObject CS101_ASDU_getElementEx(CS101_ASDU self, InformationObject io, int index) { InformationObject retVal = NULL; int elementSize; switch (CS101_ASDU_getTypeID(self)) { case M_SP_NA_1: /* 1 */ elementSize = 1; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) SinglePointInformation_getFromBuffer((SinglePointInformation) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) SinglePointInformation_getFromBuffer((SinglePointInformation) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_SP_TA_1: /* 2 */ elementSize = 4; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) SinglePointWithCP24Time2a_getFromBuffer((SinglePointWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) SinglePointWithCP24Time2a_getFromBuffer((SinglePointWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_DP_NA_1: /* 3 */ elementSize = 1; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) DoublePointInformation_getFromBuffer((DoublePointInformation) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) DoublePointInformation_getFromBuffer((DoublePointInformation) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_DP_TA_1: /* 4 */ elementSize = 4; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) DoublePointWithCP24Time2a_getFromBuffer((DoublePointWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) DoublePointWithCP24Time2a_getFromBuffer((DoublePointWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ST_NA_1: /* 5 */ elementSize = 2; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) StepPositionInformation_getFromBuffer((StepPositionInformation) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) StepPositionInformation_getFromBuffer((StepPositionInformation) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ST_TA_1: /* 6 */ elementSize = 5; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) StepPositionWithCP24Time2a_getFromBuffer((StepPositionWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) StepPositionWithCP24Time2a_getFromBuffer((StepPositionWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_BO_NA_1: /* 7 */ elementSize = 5; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) BitString32_getFromBuffer((BitString32) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) BitString32_getFromBuffer((BitString32) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_BO_TA_1: /* 8 */ elementSize = 8; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) Bitstring32WithCP24Time2a_getFromBuffer((Bitstring32WithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) Bitstring32WithCP24Time2a_getFromBuffer((Bitstring32WithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_NA_1: /* 9 */ elementSize = 3; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueNormalized_getFromBuffer((MeasuredValueNormalized) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueNormalized_getFromBuffer((MeasuredValueNormalized) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_TA_1: /* 10 */ elementSize = 6; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueNormalizedWithCP24Time2a_getFromBuffer((MeasuredValueNormalizedWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueNormalizedWithCP24Time2a_getFromBuffer((MeasuredValueNormalizedWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_NB_1: /* 11 */ elementSize = 3; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueScaled_getFromBuffer((MeasuredValueScaled) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueScaled_getFromBuffer((MeasuredValueScaled) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_TB_1: /* 12 */ elementSize = 6; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueScaledWithCP24Time2a_getFromBuffer((MeasuredValueScaledWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueScaledWithCP24Time2a_getFromBuffer((MeasuredValueScaledWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_NC_1: /* 13 */ elementSize = 5; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueShort_getFromBuffer((MeasuredValueShort) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueShort_getFromBuffer((MeasuredValueShort) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_TC_1: /* 14 */ elementSize = 8; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueShortWithCP24Time2a_getFromBuffer((MeasuredValueShortWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueShortWithCP24Time2a_getFromBuffer((MeasuredValueShortWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_IT_NA_1: /* 15 */ elementSize = 5; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) IntegratedTotals_getFromBuffer((IntegratedTotals) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) IntegratedTotals_getFromBuffer((IntegratedTotals) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_IT_TA_1: /* 16 */ elementSize = 8; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) IntegratedTotalsWithCP24Time2a_getFromBuffer((IntegratedTotalsWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) IntegratedTotalsWithCP24Time2a_getFromBuffer((IntegratedTotalsWithCP24Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_EP_TA_1: /* 17 */ elementSize = 6; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) EventOfProtectionEquipment_getFromBuffer((EventOfProtectionEquipment) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) EventOfProtectionEquipment_getFromBuffer((EventOfProtectionEquipment) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_EP_TB_1: /* 18 */ elementSize = 7; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) PackedStartEventsOfProtectionEquipment_getFromBuffer((PackedStartEventsOfProtectionEquipment) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) PackedStartEventsOfProtectionEquipment_getFromBuffer((PackedStartEventsOfProtectionEquipment) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_EP_TC_1: /* 19 */ elementSize = 7; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) PackedOutputCircuitInfo_getFromBuffer((PackedOutputCircuitInfo) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) PackedOutputCircuitInfo_getFromBuffer((PackedOutputCircuitInfo) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_PS_NA_1: /* 20 */ elementSize = 5; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) PackedSinglePointWithSCD_getFromBuffer((PackedSinglePointWithSCD) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) PackedSinglePointWithSCD_getFromBuffer((PackedSinglePointWithSCD) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_ND_1: /* 21 */ elementSize = 2; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueNormalizedWithoutQuality_getFromBuffer((MeasuredValueNormalizedWithoutQuality) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueNormalizedWithoutQuality_getFromBuffer((MeasuredValueNormalizedWithoutQuality) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_SP_TB_1: /* 30 */ elementSize = 8; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) SinglePointWithCP56Time2a_getFromBuffer((SinglePointWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) SinglePointWithCP56Time2a_getFromBuffer((SinglePointWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_DP_TB_1: /* 31 */ elementSize = 8; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) DoublePointWithCP56Time2a_getFromBuffer((DoublePointWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) DoublePointWithCP56Time2a_getFromBuffer((DoublePointWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ST_TB_1: /* 32 */ elementSize = 9; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) StepPositionWithCP56Time2a_getFromBuffer((StepPositionWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) StepPositionWithCP56Time2a_getFromBuffer((StepPositionWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_BO_TB_1: /* 33 */ elementSize = 12; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) Bitstring32WithCP56Time2a_getFromBuffer((Bitstring32WithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) Bitstring32WithCP56Time2a_getFromBuffer((Bitstring32WithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_TD_1: /* 34 */ elementSize = 10; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueNormalizedWithCP56Time2a_getFromBuffer((MeasuredValueNormalizedWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueNormalizedWithCP56Time2a_getFromBuffer((MeasuredValueNormalizedWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_TE_1: /* 35 */ elementSize = 10; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueScaledWithCP56Time2a_getFromBuffer((MeasuredValueScaledWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueScaledWithCP56Time2a_getFromBuffer((MeasuredValueScaledWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_ME_TF_1: /* 36 */ elementSize = 12; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) MeasuredValueShortWithCP56Time2a_getFromBuffer((MeasuredValueShortWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) MeasuredValueShortWithCP56Time2a_getFromBuffer((MeasuredValueShortWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_IT_TB_1: /* 37 */ elementSize = 12; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) IntegratedTotalsWithCP56Time2a_getFromBuffer((IntegratedTotalsWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) IntegratedTotalsWithCP56Time2a_getFromBuffer((IntegratedTotalsWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_EP_TD_1: /* 38 */ elementSize = 10; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) EventOfProtectionEquipmentWithCP56Time2a_getFromBuffer((EventOfProtectionEquipmentWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) EventOfProtectionEquipmentWithCP56Time2a_getFromBuffer((EventOfProtectionEquipmentWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_EP_TE_1: /* 39 */ elementSize = 11; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) PackedStartEventsOfProtectionEquipmentWithCP56Time2a_getFromBuffer((PackedStartEventsOfProtectionEquipmentWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) PackedStartEventsOfProtectionEquipmentWithCP56Time2a_getFromBuffer((PackedStartEventsOfProtectionEquipmentWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case M_EP_TF_1: /* 40 */ elementSize = 11; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) PackedOutputCircuitInfoWithCP56Time2a_getFromBuffer((PackedOutputCircuitInfoWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) PackedOutputCircuitInfoWithCP56Time2a_getFromBuffer((PackedOutputCircuitInfoWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; /* 41 - 44 reserved */ case C_SC_NA_1: /* 45 */ elementSize = self->parameters->sizeOfIOA + 1; retVal = (InformationObject) SingleCommand_getFromBuffer((SingleCommand) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_DC_NA_1: /* 46 */ elementSize = self->parameters->sizeOfIOA + 1; retVal = (InformationObject) DoubleCommand_getFromBuffer((DoubleCommand) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_RC_NA_1: /* 47 */ elementSize = self->parameters->sizeOfIOA + 1; retVal = (InformationObject) StepCommand_getFromBuffer((StepCommand) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_SE_NA_1: /* 48 - Set-point command, normalized value */ elementSize = self->parameters->sizeOfIOA + 3; retVal = (InformationObject) SetpointCommandNormalized_getFromBuffer((SetpointCommandNormalized) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_SE_NB_1: /* 49 - Set-point command, scaled value */ elementSize = self->parameters->sizeOfIOA + 3; retVal = (InformationObject) SetpointCommandScaled_getFromBuffer((SetpointCommandScaled) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_SE_NC_1: /* 50 - Set-point command, short floating point number */ elementSize = self->parameters->sizeOfIOA + 5; retVal = (InformationObject) SetpointCommandShort_getFromBuffer((SetpointCommandShort) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_BO_NA_1: /* 51 - Bitstring command */ elementSize = self->parameters->sizeOfIOA + 4; retVal = (InformationObject) Bitstring32Command_getFromBuffer((Bitstring32Command) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; /* 52 - 57 reserved */ case C_SC_TA_1: /* 58 - Single command with CP56Time2a */ elementSize = self->parameters->sizeOfIOA + 8; retVal = (InformationObject) SingleCommandWithCP56Time2a_getFromBuffer((SingleCommandWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_DC_TA_1: /* 59 - Double command with CP56Time2a */ elementSize = self->parameters->sizeOfIOA + 8; retVal = (InformationObject) DoubleCommandWithCP56Time2a_getFromBuffer((DoubleCommandWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_RC_TA_1: /* 60 - Step command with CP56Time2a */ elementSize = self->parameters->sizeOfIOA + 8; retVal = (InformationObject) StepCommandWithCP56Time2a_getFromBuffer((StepCommandWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_SE_TA_1: /* 61 - Setpoint command, normalized value with CP56Time2a */ elementSize = self->parameters->sizeOfIOA + 10; retVal = (InformationObject) SetpointCommandNormalizedWithCP56Time2a_getFromBuffer((SetpointCommandNormalizedWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_SE_TB_1: /* 62 - Setpoint command, scaled value with CP56Time2a */ elementSize = self->parameters->sizeOfIOA + 10; retVal = (InformationObject) SetpointCommandScaledWithCP56Time2a_getFromBuffer((SetpointCommandScaledWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_SE_TC_1: /* 63 - Setpoint command, short value with CP56Time2a */ elementSize = self->parameters->sizeOfIOA + 12; retVal = (InformationObject) SetpointCommandShortWithCP56Time2a_getFromBuffer((SetpointCommandShortWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case C_BO_TA_1: /* 64 - Bitstring command with CP56Time2a */ elementSize = self->parameters->sizeOfIOA + 11; retVal = (InformationObject) Bitstring32CommandWithCP56Time2a_getFromBuffer((Bitstring32CommandWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case M_EI_NA_1: /* 70 - End of Initialization */ retVal = (InformationObject) EndOfInitialization_getFromBuffer((EndOfInitialization) io, self->parameters, self->payload, self->payloadSize, 0); break; case C_IC_NA_1: /* 100 - Interrogation command */ retVal = (InformationObject) InterrogationCommand_getFromBuffer((InterrogationCommand) io, self->parameters, self->payload, self->payloadSize, 0); break; case C_CI_NA_1: /* 101 - Counter interrogation command */ retVal = (InformationObject) CounterInterrogationCommand_getFromBuffer((CounterInterrogationCommand) io, self->parameters, self->payload, self->payloadSize, 0); break; case C_RD_NA_1: /* 102 - Read command */ retVal = (InformationObject) ReadCommand_getFromBuffer((ReadCommand) io, self->parameters, self->payload, self->payloadSize, 0); break; case C_CS_NA_1: /* 103 - Clock synchronization command */ retVal = (InformationObject) ClockSynchronizationCommand_getFromBuffer((ClockSynchronizationCommand) io, self->parameters, self->payload, self->payloadSize, 0); break; case C_TS_NA_1: /* 104 - Test command */ retVal = (InformationObject) TestCommand_getFromBuffer((TestCommand) io, self->parameters, self->payload, self->payloadSize, 0); break; case C_RP_NA_1: /* 105 - Reset process command */ retVal = (InformationObject) ResetProcessCommand_getFromBuffer((ResetProcessCommand) io, self->parameters, self->payload, self->payloadSize, 0); break; case C_CD_NA_1: /* 106 - Delay acquisition command */ retVal = (InformationObject) DelayAcquisitionCommand_getFromBuffer((DelayAcquisitionCommand) io, self->parameters, self->payload, self->payloadSize, 0); break; case C_TS_TA_1: /* 107 - Test command with time */ retVal = (InformationObject) TestCommandWithCP56Time2a_getFromBuffer((TestCommandWithCP56Time2a) io, self->parameters, self->payload, self->payloadSize, 0); break; case P_ME_NA_1: /* 110 - Parameter of measured values, normalized value */ elementSize = self->parameters->sizeOfIOA + 3; retVal = (InformationObject) ParameterNormalizedValue_getFromBuffer((ParameterNormalizedValue) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case P_ME_NB_1: /* 111 - Parameter of measured values, scaled value */ elementSize = self->parameters->sizeOfIOA + 3; retVal = (InformationObject) ParameterScaledValue_getFromBuffer((ParameterScaledValue) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case P_ME_NC_1: /* 112 - Parameter of measured values, short floating point number */ elementSize = self->parameters->sizeOfIOA + 5; retVal = (InformationObject) ParameterFloatValue_getFromBuffer((ParameterFloatValue) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case P_AC_NA_1: /* 113 - Parameter for activation */ elementSize = self->parameters->sizeOfIOA + 1; retVal = (InformationObject) ParameterActivation_getFromBuffer((ParameterActivation) io, self->parameters, self->payload, self->payloadSize, index * elementSize); break; case F_FR_NA_1: /* 120 - File ready */ retVal = (InformationObject) FileReady_getFromBuffer((FileReady) io, self->parameters, self->payload, self->payloadSize, 0); break; case F_SR_NA_1: /* 121 - Section ready */ retVal = (InformationObject) SectionReady_getFromBuffer((SectionReady) io, self->parameters, self->payload, self->payloadSize, 0); break; case F_SC_NA_1: /* 122 - Call/Select directory/file/section */ retVal = (InformationObject) FileCallOrSelect_getFromBuffer((FileCallOrSelect) io, self->parameters, self->payload, self->payloadSize, 0); break; case F_LS_NA_1: /* 123 - Last segment/section */ retVal = (InformationObject) FileLastSegmentOrSection_getFromBuffer((FileLastSegmentOrSection) io, self->parameters, self->payload, self->payloadSize, 0); break; case F_AF_NA_1: /* 124 - ACK file/section */ retVal = (InformationObject) FileACK_getFromBuffer((FileACK) io, self->parameters, self->payload, self->payloadSize, 0); break; case F_SG_NA_1: /* 125 - File segment */ retVal = (InformationObject) FileSegment_getFromBuffer((FileSegment) io, self->parameters, self->payload, self->payloadSize, 0); break; case F_DR_TA_1: /* 126 - File directory */ elementSize = 13; if (CS101_ASDU_isSequence(self)) { retVal = (InformationObject) FileDirectory_getFromBuffer((FileDirectory) io, self->parameters, self->payload, self->payloadSize, self->parameters->sizeOfIOA + (index * elementSize), true); InformationObject_setObjectAddress(retVal, InformationObject_ParseObjectAddress(self->parameters, self->payload, 0) + index); } else retVal = (InformationObject) FileDirectory_getFromBuffer((FileDirectory) io, self->parameters, self->payload, self->payloadSize, index * (self->parameters->sizeOfIOA + elementSize), false); break; case F_SC_NB_1: /* 127 - QueryLog */ retVal = (InformationObject) QueryLog_getFromBuffer((QueryLog) io, self->parameters, self->payload, self->payloadSize, 0); break; default: printf("type %d not supported\n", CS101_ASDU_getTypeID(self)); break; } return retVal; } const char* TypeID_toString(TypeID self) { switch (self) { case M_SP_NA_1: return "M_SP_NA_1"; case M_SP_TA_1: return "M_SP_TA_1"; case M_DP_NA_1: return "M_DP_NA_1"; case M_DP_TA_1: return "M_DP_TA_1"; case M_ST_NA_1: return "M_ST_NA_1"; case M_ST_TA_1: return "M_ST_TA_1"; case M_BO_NA_1: return "M_BO_NA_1"; case M_BO_TA_1: return "M_BO_TA_1"; case M_ME_NA_1: return "M_ME_NA_1"; case M_ME_TA_1: return "M_ME_TA_1"; case M_ME_NB_1: return "M_ME_NB_1"; case M_ME_TB_1: return "M_ME_TB_1"; case M_ME_NC_1: return "M_ME_NC_1"; case M_ME_TC_1: return "M_ME_TC_1"; case M_IT_NA_1: return "M_IT_NA_1"; case M_IT_TA_1: return "M_IT_TA_1"; case M_EP_TA_1: return "M_EP_TA_1"; case M_EP_TB_1: return "M_EP_TB_1"; case M_EP_TC_1: return "M_EP_TC_1"; case M_PS_NA_1: return "M_PS_NA_1"; case M_ME_ND_1: return "M_ME_ND_1"; case M_SP_TB_1: return "M_SP_TB_1"; case M_DP_TB_1: return "M_DP_TB_1"; case M_ST_TB_1: return "M_ST_TB_1"; case M_BO_TB_1: return "M_BO_TB_1"; case M_ME_TD_1: return "M_ME_TD_1"; case M_ME_TE_1: return "M_ME_TE_1"; case M_ME_TF_1: return "M_ME_TF_1"; case M_IT_TB_1: return "M_IT_TB_1"; case M_EP_TD_1: return "M_EP_TD_1"; case M_EP_TE_1: return "M_EP_TE_1"; case M_EP_TF_1: return "M_EP_TF_1"; case C_SC_NA_1: return "C_SC_NA_1"; case C_DC_NA_1: return "C_DC_NA_1"; case C_RC_NA_1: return "C_RC_NA_1"; case C_SE_NA_1: return "C_SE_NA_1"; case C_SE_NB_1: return "C_SE_NB_1"; case C_SE_NC_1: return "C_SE_NC_1"; case C_BO_NA_1: return "C_BO_NA_1"; case C_SC_TA_1: return "C_SC_TA_1"; case C_DC_TA_1: return "C_DC_TA_1"; case C_RC_TA_1: return "C_RC_TA_1"; case C_SE_TA_1: return "C_SE_TA_1"; case C_SE_TB_1: return "C_SE_TB_1"; case C_SE_TC_1: return "C_SE_TC_1"; case C_BO_TA_1: return "C_BO_TA_1"; case M_EI_NA_1: return "M_EI_NA_1"; case C_IC_NA_1: return "C_IC_NA_1"; case C_CI_NA_1: return "C_CI_NA_1"; case C_RD_NA_1: return "C_RD_NA_1"; case C_CS_NA_1: return "C_CS_NA_1"; case C_TS_NA_1: return "C_TS_NA_1"; case C_RP_NA_1: return "C_RP_NA_1"; case C_CD_NA_1: return "C_CD_NA_1"; case C_TS_TA_1: return "C_TS_TA_1"; case P_ME_NA_1: return "P_ME_NA_1"; case P_ME_NB_1: return "P_ME_NB_1"; case P_ME_NC_1: return "P_ME_NC_1"; case P_AC_NA_1: return "P_AC_NA_1"; case F_FR_NA_1: return "F_FR_NA_1"; case F_SR_NA_1: return "F_SR_NA_1"; case F_SC_NA_1: return "F_SC_NA_1"; case F_LS_NA_1: return "F_LS_NA_1"; case F_AF_NA_1: return "F_AF_NA_1"; case F_SG_NA_1: return "F_SG_NA_1"; case F_DR_TA_1: return "F_DR_TA_1"; case F_SC_NB_1: return "F_SC_NB_1"; default: return "unknown"; } } const char* CS101_CauseOfTransmission_toString(CS101_CauseOfTransmission self) { switch (self) { case CS101_COT_PERIODIC: return "PERIODIC"; case CS101_COT_BACKGROUND_SCAN: return "BACKGROUND_SCAN"; case CS101_COT_SPONTANEOUS: return "SPONTANEOUS"; case CS101_COT_INITIALIZED: return "INITIALIZED"; case CS101_COT_REQUEST: return "REQUEST"; case CS101_COT_ACTIVATION: return "ACTIVATION"; case CS101_COT_ACTIVATION_CON: return "ACTIVATION_CON"; case CS101_COT_DEACTIVATION: return "DEACTIVATION"; case CS101_COT_DEACTIVATION_CON: return "DEACTIVATION_CON"; case CS101_COT_ACTIVATION_TERMINATION: return "ACTIVATION_TERMINATION"; case CS101_COT_RETURN_INFO_REMOTE: return "RETURN_INFO_REMOTE"; case CS101_COT_RETURN_INFO_LOCAL: return "RETURN_INFO_LOCAL"; case CS101_COT_FILE_TRANSFER: return "FILE_TRANSFER"; case CS101_COT_AUTHENTICATION: return "AUTHENTICATION"; case CS101_COT_MAINTENANCE_OF_AUTH_SESSION_KEY: return "MAINTENANCE_OF_AUTH_SESSION_KEY"; case CS101_COT_MAINTENANCE_OF_USER_ROLE_AND_UPDATE_KEY: return "MAINTENANCE_OF_USER_ROLE_AND_UPDATE_KEY"; case CS101_COT_INTERROGATED_BY_STATION: return "INTERROGATED_BY_STATION"; case CS101_COT_INTERROGATED_BY_GROUP_1: return "INTERROGATED_BY_GROUP_1"; case CS101_COT_INTERROGATED_BY_GROUP_2: return "INTERROGATED_BY_GROUP_2"; case CS101_COT_INTERROGATED_BY_GROUP_3: return "INTERROGATED_BY_GROUP_3"; case CS101_COT_INTERROGATED_BY_GROUP_4: return "INTERROGATED_BY_GROUP_4"; case CS101_COT_INTERROGATED_BY_GROUP_5: return "INTERROGATED_BY_GROUP_5"; case CS101_COT_INTERROGATED_BY_GROUP_6: return "INTERROGATED_BY_GROUP_6"; case CS101_COT_INTERROGATED_BY_GROUP_7: return "INTERROGATED_BY_GROUP_7"; case CS101_COT_INTERROGATED_BY_GROUP_8: return "INTERROGATED_BY_GROUP_8"; case CS101_COT_INTERROGATED_BY_GROUP_9: return "INTERROGATED_BY_GROUP_9"; case CS101_COT_INTERROGATED_BY_GROUP_10: return "INTERROGATED_BY_GROUP_10"; case CS101_COT_INTERROGATED_BY_GROUP_11: return "INTERROGATED_BY_GROUP_11"; case CS101_COT_INTERROGATED_BY_GROUP_12: return "INTERROGATED_BY_GROUP_12"; case CS101_COT_INTERROGATED_BY_GROUP_13: return "INTERROGATED_BY_GROUP_13"; case CS101_COT_INTERROGATED_BY_GROUP_14: return "INTERROGATED_BY_GROUP_14"; case CS101_COT_INTERROGATED_BY_GROUP_15: return "INTERROGATED_BY_GROUP_15"; case CS101_COT_INTERROGATED_BY_GROUP_16: return "INTERROGATED_BY_GROUP_16"; case CS101_COT_REQUESTED_BY_GENERAL_COUNTER: return "REQUESTED_BY_GENERAL_COUNTER"; case CS101_COT_REQUESTED_BY_GROUP_1_COUNTER: return "REQUESTED_BY_GROUP_1_COUNTER"; case CS101_COT_REQUESTED_BY_GROUP_2_COUNTER: return "REQUESTED_BY_GROUP_2_COUNTER"; case CS101_COT_REQUESTED_BY_GROUP_3_COUNTER: return "REQUESTED_BY_GROUP_3_COUNTER"; case CS101_COT_REQUESTED_BY_GROUP_4_COUNTER: return "REQUESTED_BY_GROUP_4_COUNTER"; case CS101_COT_UNKNOWN_TYPE_ID: return "UNKNOWN_TYPE_ID"; case CS101_COT_UNKNOWN_COT: return "UNKNOWN_CAUSE_OF_TRANSMISSION"; case CS101_COT_UNKNOWN_CA: return "UNKNOWN_COMMON_ADDRESS_OF_ASDU"; case CS101_COT_UNKNOWN_IOA: return "UNKNOWN_INFORMATION_OBJECT_ADDRESS"; default: return "UNKNOWN_COT"; } }