The goal of this software is to automatically generate C/C++ code which reads and writes GOOSE and Sampled Value packets. Any valid IEC 61850 Substation Configuration Description (SCD) file, describing GOOSE and/or SV communications, can be used as the input. The output code is lightweight and platform-independent, so it can run on a variety of devices, including low-cost microcontrollers. It\'s ideal for rapid-prototyping new protection and control systems that require communications. This mbed project is a simple example of this functionality. Other code: https://github.com/stevenblair/rapid61850 Project homepage: http://personal.strath.ac.uk/steven.m.blair/

Committer:
sblair
Date:
Fri Oct 07 13:41:08 2011 +0000
Revision:
0:230c10b228ea
Child:
1:9399d44c2b1a

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sblair 0:230c10b228ea 1 #include "gseDecodeBasic.h"
sblair 0:230c10b228ea 2 #include "ied.h"
sblair 0:230c10b228ea 3 #include "gseDecode.h"
sblair 0:230c10b228ea 4
sblair 0:230c10b228ea 5
sblair 0:230c10b228ea 6
sblair 0:230c10b228ea 7 int ber_decode_myAnalogValue(unsigned char *buf, struct myAnalogValue *myAnalogValue) {
sblair 0:230c10b228ea 8 int offset = 0;
sblair 0:230c10b228ea 9
sblair 0:230c10b228ea 10 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 11 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 12
sblair 0:230c10b228ea 13 offset += BER_DECODE_CTYPE_FLOAT32(&buf[offset], &myAnalogValue->f);
sblair 0:230c10b228ea 14 }
sblair 0:230c10b228ea 15
sblair 0:230c10b228ea 16 return offset;
sblair 0:230c10b228ea 17 }
sblair 0:230c10b228ea 18 int ber_decode_ScaledValueConfig(unsigned char *buf, struct ScaledValueConfig *ScaledValueConfig) {
sblair 0:230c10b228ea 19 int offset = 0;
sblair 0:230c10b228ea 20
sblair 0:230c10b228ea 21 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 22 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 23
sblair 0:230c10b228ea 24 offset += BER_DECODE_CTYPE_FLOAT32(&buf[offset], &ScaledValueConfig->scaleFactor);
sblair 0:230c10b228ea 25 offset += BER_DECODE_CTYPE_FLOAT32(&buf[offset], &ScaledValueConfig->offset);
sblair 0:230c10b228ea 26 }
sblair 0:230c10b228ea 27
sblair 0:230c10b228ea 28 return offset;
sblair 0:230c10b228ea 29 }
sblair 0:230c10b228ea 30 int ber_decode_myVector(unsigned char *buf, struct myVector *myVector) {
sblair 0:230c10b228ea 31 int offset = 0;
sblair 0:230c10b228ea 32
sblair 0:230c10b228ea 33 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 34 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 35
sblair 0:230c10b228ea 36 offset += ber_decode_myAnalogValue(&buf[offset], &myVector->mag);
sblair 0:230c10b228ea 37 offset += ber_decode_myAnalogValue(&buf[offset], &myVector->ang);
sblair 0:230c10b228ea 38 }
sblair 0:230c10b228ea 39
sblair 0:230c10b228ea 40 return offset;
sblair 0:230c10b228ea 41 }
sblair 0:230c10b228ea 42 int ber_decode_simpleVector(unsigned char *buf, struct simpleVector *simpleVector) {
sblair 0:230c10b228ea 43 int offset = 0;
sblair 0:230c10b228ea 44
sblair 0:230c10b228ea 45 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 46 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 47
sblair 0:230c10b228ea 48 offset += ber_decode_myAnalogValue(&buf[offset], &simpleVector->mag);
sblair 0:230c10b228ea 49 offset += ber_decode_myAnalogValue(&buf[offset], &simpleVector->ang);
sblair 0:230c10b228ea 50 }
sblair 0:230c10b228ea 51
sblair 0:230c10b228ea 52 return offset;
sblair 0:230c10b228ea 53 }
sblair 0:230c10b228ea 54 int ber_decode_myMod(unsigned char *buf, struct myMod *myMod) {
sblair 0:230c10b228ea 55 int offset = 0;
sblair 0:230c10b228ea 56
sblair 0:230c10b228ea 57 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 58 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 59
sblair 0:230c10b228ea 60 offset += BER_DECODE_CTYPE_ENUM(&buf[offset], (CTYPE_ENUM *) &myMod->ctlVal);
sblair 0:230c10b228ea 61 offset += BER_DECODE_CTYPE_ENUM(&buf[offset], (CTYPE_ENUM *) &myMod->stVal);
sblair 0:230c10b228ea 62 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &myMod->q);
sblair 0:230c10b228ea 63 offset += BER_DECODE_CTYPE_TIMESTAMP(&buf[offset], &myMod->t);
sblair 0:230c10b228ea 64 }
sblair 0:230c10b228ea 65
sblair 0:230c10b228ea 66 return offset;
sblair 0:230c10b228ea 67 }
sblair 0:230c10b228ea 68 int ber_decode_myHealth(unsigned char *buf, struct myHealth *myHealth) {
sblair 0:230c10b228ea 69 int offset = 0;
sblair 0:230c10b228ea 70
sblair 0:230c10b228ea 71 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 72 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 73
sblair 0:230c10b228ea 74 offset += BER_DECODE_CTYPE_ENUM(&buf[offset], (CTYPE_ENUM *) &myHealth->stVal);
sblair 0:230c10b228ea 75 }
sblair 0:230c10b228ea 76
sblair 0:230c10b228ea 77 return offset;
sblair 0:230c10b228ea 78 }
sblair 0:230c10b228ea 79 int ber_decode_myBeh(unsigned char *buf, struct myBeh *myBeh) {
sblair 0:230c10b228ea 80 int offset = 0;
sblair 0:230c10b228ea 81
sblair 0:230c10b228ea 82 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 83 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 84
sblair 0:230c10b228ea 85 offset += BER_DECODE_CTYPE_ENUM(&buf[offset], (CTYPE_ENUM *) &myBeh->stVal);
sblair 0:230c10b228ea 86 }
sblair 0:230c10b228ea 87
sblair 0:230c10b228ea 88 return offset;
sblair 0:230c10b228ea 89 }
sblair 0:230c10b228ea 90 int ber_decode_myINS(unsigned char *buf, struct myINS *myINS) {
sblair 0:230c10b228ea 91 int offset = 0;
sblair 0:230c10b228ea 92
sblair 0:230c10b228ea 93 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 94 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 95
sblair 0:230c10b228ea 96 offset += BER_DECODE_CTYPE_INT32(&buf[offset], &myINS->stVal);
sblair 0:230c10b228ea 97 }
sblair 0:230c10b228ea 98
sblair 0:230c10b228ea 99 return offset;
sblair 0:230c10b228ea 100 }
sblair 0:230c10b228ea 101 int ber_decode_myLPL(unsigned char *buf, struct myLPL *myLPL) {
sblair 0:230c10b228ea 102 int offset = 0;
sblair 0:230c10b228ea 103
sblair 0:230c10b228ea 104 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 105 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 106
sblair 0:230c10b228ea 107 offset += BER_DECODE_CTYPE_VISSTRING255(&buf[offset], &myLPL->ldNs);
sblair 0:230c10b228ea 108 offset += BER_DECODE_CTYPE_VISSTRING255(&buf[offset], &myLPL->configRev);
sblair 0:230c10b228ea 109 }
sblair 0:230c10b228ea 110
sblair 0:230c10b228ea 111 return offset;
sblair 0:230c10b228ea 112 }
sblair 0:230c10b228ea 113 int ber_decode_myDPL(unsigned char *buf, struct myDPL *myDPL) {
sblair 0:230c10b228ea 114 int offset = 0;
sblair 0:230c10b228ea 115
sblair 0:230c10b228ea 116 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 117 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 118
sblair 0:230c10b228ea 119 offset += BER_DECODE_CTYPE_VISSTRING255(&buf[offset], &myDPL->vendor);
sblair 0:230c10b228ea 120 offset += BER_DECODE_CTYPE_VISSTRING255(&buf[offset], &myDPL->hwRev);
sblair 0:230c10b228ea 121 }
sblair 0:230c10b228ea 122
sblair 0:230c10b228ea 123 return offset;
sblair 0:230c10b228ea 124 }
sblair 0:230c10b228ea 125 int ber_decode_myPos(unsigned char *buf, struct myPos *myPos) {
sblair 0:230c10b228ea 126 int offset = 0;
sblair 0:230c10b228ea 127
sblair 0:230c10b228ea 128 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 129 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 130
sblair 0:230c10b228ea 131 offset += BER_DECODE_CTYPE_DBPOS(&buf[offset], &myPos->stVal);
sblair 0:230c10b228ea 132 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &myPos->q);
sblair 0:230c10b228ea 133 offset += BER_DECODE_CTYPE_TIMESTAMP(&buf[offset], &myPos->t);
sblair 0:230c10b228ea 134 offset += BER_DECODE_CTYPE_BOOLEAN(&buf[offset], &myPos->ctlVal);
sblair 0:230c10b228ea 135 }
sblair 0:230c10b228ea 136
sblair 0:230c10b228ea 137 return offset;
sblair 0:230c10b228ea 138 }
sblair 0:230c10b228ea 139 int ber_decode_mySPS(unsigned char *buf, struct mySPS *mySPS) {
sblair 0:230c10b228ea 140 int offset = 0;
sblair 0:230c10b228ea 141
sblair 0:230c10b228ea 142 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 143 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 144
sblair 0:230c10b228ea 145 offset += BER_DECODE_CTYPE_INT32(&buf[offset], &mySPS->stVal);
sblair 0:230c10b228ea 146 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &mySPS->q);
sblair 0:230c10b228ea 147 offset += BER_DECODE_CTYPE_TIMESTAMP(&buf[offset], &mySPS->t);
sblair 0:230c10b228ea 148 }
sblair 0:230c10b228ea 149
sblair 0:230c10b228ea 150 return offset;
sblair 0:230c10b228ea 151 }
sblair 0:230c10b228ea 152 int ber_decode_myMV(unsigned char *buf, struct myMV *myMV) {
sblair 0:230c10b228ea 153 int offset = 0;
sblair 0:230c10b228ea 154
sblair 0:230c10b228ea 155 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 156 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 157
sblair 0:230c10b228ea 158 offset += ber_decode_myAnalogValue(&buf[offset], &myMV->mag);
sblair 0:230c10b228ea 159 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &myMV->q);
sblair 0:230c10b228ea 160 offset += BER_DECODE_CTYPE_TIMESTAMP(&buf[offset], &myMV->t);
sblair 0:230c10b228ea 161 offset += ber_decode_ScaledValueConfig(&buf[offset], &myMV->sVC);
sblair 0:230c10b228ea 162 }
sblair 0:230c10b228ea 163
sblair 0:230c10b228ea 164 return offset;
sblair 0:230c10b228ea 165 }
sblair 0:230c10b228ea 166 int ber_decode_simpleMV(unsigned char *buf, struct simpleMV *simpleMV) {
sblair 0:230c10b228ea 167 int offset = 0;
sblair 0:230c10b228ea 168
sblair 0:230c10b228ea 169 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 170 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 171
sblair 0:230c10b228ea 172 offset += BER_DECODE_CTYPE_FLOAT32(&buf[offset], &simpleMV->mag);
sblair 0:230c10b228ea 173 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &simpleMV->q);
sblair 0:230c10b228ea 174 offset += BER_DECODE_CTYPE_TIMESTAMP(&buf[offset], &simpleMV->t);
sblair 0:230c10b228ea 175 offset += ber_decode_ScaledValueConfig(&buf[offset], &simpleMV->sVC);
sblair 0:230c10b228ea 176 }
sblair 0:230c10b228ea 177
sblair 0:230c10b228ea 178 return offset;
sblair 0:230c10b228ea 179 }
sblair 0:230c10b228ea 180 int ber_decode_simpleCMV(unsigned char *buf, struct simpleCMV *simpleCMV) {
sblair 0:230c10b228ea 181 int offset = 0;
sblair 0:230c10b228ea 182
sblair 0:230c10b228ea 183 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 184 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 185
sblair 0:230c10b228ea 186 offset += ber_decode_simpleVector(&buf[offset], &simpleCMV->cVal);
sblair 0:230c10b228ea 187 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &simpleCMV->q);
sblair 0:230c10b228ea 188 offset += BER_DECODE_CTYPE_TIMESTAMP(&buf[offset], &simpleCMV->t);
sblair 0:230c10b228ea 189 }
sblair 0:230c10b228ea 190
sblair 0:230c10b228ea 191 return offset;
sblair 0:230c10b228ea 192 }
sblair 0:230c10b228ea 193 int ber_decode_simpleWYE(unsigned char *buf, struct simpleWYE *simpleWYE) {
sblair 0:230c10b228ea 194 int offset = 0;
sblair 0:230c10b228ea 195
sblair 0:230c10b228ea 196 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 197 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 198
sblair 0:230c10b228ea 199 offset += ber_decode_simpleCMV(&buf[offset], &simpleWYE->phsA);
sblair 0:230c10b228ea 200 offset += ber_decode_simpleCMV(&buf[offset], &simpleWYE->phsB);
sblair 0:230c10b228ea 201 offset += ber_decode_simpleCMV(&buf[offset], &simpleWYE->phsC);
sblair 0:230c10b228ea 202 }
sblair 0:230c10b228ea 203
sblair 0:230c10b228ea 204 return offset;
sblair 0:230c10b228ea 205 }
sblair 0:230c10b228ea 206 int ber_decode_myCMV(unsigned char *buf, struct myCMV *myCMV) {
sblair 0:230c10b228ea 207 int offset = 0;
sblair 0:230c10b228ea 208
sblair 0:230c10b228ea 209 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 210 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 211
sblair 0:230c10b228ea 212 offset += ber_decode_myVector(&buf[offset], &myCMV->cVal);
sblair 0:230c10b228ea 213 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &myCMV->q);
sblair 0:230c10b228ea 214 offset += BER_DECODE_CTYPE_TIMESTAMP(&buf[offset], &myCMV->t);
sblair 0:230c10b228ea 215 }
sblair 0:230c10b228ea 216
sblair 0:230c10b228ea 217 return offset;
sblair 0:230c10b228ea 218 }
sblair 0:230c10b228ea 219 int ber_decode_mySEQ(unsigned char *buf, struct mySEQ *mySEQ) {
sblair 0:230c10b228ea 220 int offset = 0;
sblair 0:230c10b228ea 221
sblair 0:230c10b228ea 222 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 223 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 224
sblair 0:230c10b228ea 225 offset += ber_decode_myCMV(&buf[offset], &mySEQ->c1);
sblair 0:230c10b228ea 226 offset += ber_decode_myCMV(&buf[offset], &mySEQ->c2);
sblair 0:230c10b228ea 227 offset += ber_decode_myCMV(&buf[offset], &mySEQ->c3);
sblair 0:230c10b228ea 228 offset += BER_DECODE_CTYPE_ENUM(&buf[offset], (CTYPE_ENUM *) &mySEQ->seqT);
sblair 0:230c10b228ea 229 }
sblair 0:230c10b228ea 230
sblair 0:230c10b228ea 231 return offset;
sblair 0:230c10b228ea 232 }
sblair 0:230c10b228ea 233 int ber_decode_mySAV(unsigned char *buf, struct mySAV *mySAV) {
sblair 0:230c10b228ea 234 int offset = 0;
sblair 0:230c10b228ea 235
sblair 0:230c10b228ea 236 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 237 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 238
sblair 0:230c10b228ea 239 offset += ber_decode_myAnalogValue(&buf[offset], &mySAV->instMag);
sblair 0:230c10b228ea 240 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &mySAV->q);
sblair 0:230c10b228ea 241 }
sblair 0:230c10b228ea 242
sblair 0:230c10b228ea 243 return offset;
sblair 0:230c10b228ea 244 }
sblair 0:230c10b228ea 245 int ber_decode_simpleSAV(unsigned char *buf, struct simpleSAV *simpleSAV) {
sblair 0:230c10b228ea 246 int offset = 0;
sblair 0:230c10b228ea 247
sblair 0:230c10b228ea 248 if (buf[offset++] == 0xA2) {
sblair 0:230c10b228ea 249 offset += getLengthFieldSize(buf[offset]);
sblair 0:230c10b228ea 250
sblair 0:230c10b228ea 251 offset += ber_decode_myAnalogValue(&buf[offset], &simpleSAV->instMag);
sblair 0:230c10b228ea 252 offset += BER_DECODE_CTYPE_QUALITY(&buf[offset], &simpleSAV->q);
sblair 0:230c10b228ea 253 }
sblair 0:230c10b228ea 254
sblair 0:230c10b228ea 255 return offset;
sblair 0:230c10b228ea 256 }
sblair 0:230c10b228ea 257 int ber_decode_Positions_RSYN_1(unsigned char *buf) {
sblair 0:230c10b228ea 258 int offset = 0;
sblair 0:230c10b228ea 259
sblair 0:230c10b228ea 260 offset += ber_decode_myAnalogValue(&buf[offset], &D1Q1SB4.S1.C1.RSYN_1.gse_inputs.instMag_1);
sblair 0:230c10b228ea 261 offset += ber_decode_myPos(&buf[offset], &D1Q1SB4.S1.C1.RSYN_1.gse_inputs.Pos_1);
sblair 0:230c10b228ea 262 offset += ber_decode_myPos(&buf[offset], &D1Q1SB4.S1.C1.RSYN_1.gse_inputs.Pos_2);
sblair 0:230c10b228ea 263 offset += BER_DECODE_CTYPE_ENUM(&buf[offset], (CTYPE_ENUM *) &D1Q1SB4.S1.C1.RSYN_1.gse_inputs.stVal_1);
sblair 0:230c10b228ea 264 offset += ber_decode_myMV(&buf[offset], &D1Q1SB4.S1.C1.RSYN_1.gse_inputs.Amps_1);
sblair 0:230c10b228ea 265 offset += ber_decode_myMV(&buf[offset], &D1Q1SB4.S1.C1.RSYN_1.gse_inputs.Volts_1);
sblair 0:230c10b228ea 266
sblair 0:230c10b228ea 267 return offset;
sblair 0:230c10b228ea 268 }
sblair 0:230c10b228ea 269
sblair 0:230c10b228ea 270 void gseDecodeDataset(unsigned char *dataset, int datasetLength, unsigned char *datSet, int datSetLength) {
sblair 0:230c10b228ea 271
sblair 0:230c10b228ea 272 if (strncmp((const char *) datSet, "E1Q1SB1C1/LLN0$Positions", datSetLength) == 0) {
sblair 0:230c10b228ea 273 ber_decode_Positions_RSYN_1(dataset);
sblair 0:230c10b228ea 274 }
sblair 0:230c10b228ea 275 }
sblair 0:230c10b228ea 276
sblair 0:230c10b228ea 277