00001 00002 /* 00003 * THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE 00004 * CHECKED IT OUT USING THE COMMAND CHECKOUT. 00005 * 00006 * $Id: rw__strongmotion_8c-source.html 2161 2006-05-19 16:55:03Z paulf $ 00007 * 00008 * Revision history: 00009 * $Log$ 00009 * Revision 1.1 2006/05/19 16:55:02 paulf 00009 * first inclusion 00009 * 00010 * Revision 1.2 2000/02/25 18:07:56 dietz 00011 * kludged to ensure that vendor an serialnumber are never null strings 00012 * 00013 * Revision 1.1 2000/02/14 18:51:48 lucky 00014 * Initial revision 00015 * 00016 * 00017 */ 00018 00019 /* rw_strongmotion.c 00020 * 00021 * Contains functions in that convert from a 00022 * TYPE_STRONGMOTION message to a structure and visa versa. 00023 * 00024 * written by Lynn Dietz October, 1999 00025 */ 00026 00027 #include <stdio.h> 00028 #include <string.h> 00029 #include <time.h> 00030 #include <chron3.h> 00031 #include <time_ew.h> 00032 #include <rw_strongmotion.h> 00033 00034 void logit( char *, char *, ... ); /* logit.c sys-independent */ 00035 static int strappend( char *s1, int s1max, char *s2 ); 00036 static int tokenlength( char *begtok, char c ); 00037 00038 static char *sNullDate = "0000/00/00 00:00:00.00"; 00039 00040 /******************************************************************** 00041 * rd_strongmotion() * 00042 * Reads an ascii TYPE_STRONGMOTION message and fills in a SM_DATA * 00043 * structure. * 00044 * Returns 0 on success, -1 on failure * 00045 ********************************************************************/ 00046 int rd_strongmotion( char *msg, int msglen, SM_DATA *sm ) 00047 { 00048 char line[256]; 00049 char *nextline; /* working pointer into msg */ 00050 char *begtok; /* points to the beginning of this token */ 00051 char *endtok; /* points to the end of this token */ 00052 char *endline; /* points at end of line */ 00053 int len; /* length (bytes) of the next token */ 00054 int nline; /* number of lines read from msg so far */ 00055 int nchan; 00056 int nfreq; 00057 int i,j; 00058 struct tm stm; /* time structure for timestamp */ 00059 time_t tsec; /* timestamp in whole sec since 1970 */ 00060 int hsec; /* hundredths of seconds field of timestamp */ 00061 00062 00063 memset( sm, 0, sizeof(SM_DATA) ); /* zero output structure */ 00064 nextline = msg; 00065 nline = 0; 00066 nfreq = 0; 00067 00068 00069 /* Read next line from the message into working buffer */ 00070 while( nextline < (msg+msglen-1) ) 00071 { 00072 len = tokenlength( nextline, '\n' ); 00073 if( len >= 256 ) return( -1 ); 00074 strncpy( line, nextline, len ); 00075 line[len] = 0; /* null terminate the line */ 00076 endline = line + strlen(line); 00077 nline++; 00078 nextline += len + 1; 00079 00080 /* First line = Vendor */ 00081 if( nline == 1 ) 00082 { 00083 if( strncmp(line,"Vendor:", 7) != 0 ) return( -1 ); 00084 begtok = line + 7; 00085 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00086 len = strlen(begtok); 00087 if( len > SM_VENDOR_LEN ) return( -1 ); 00088 strncpy( sm->vendor, begtok, len ); 00089 } 00090 00091 /* Second line = Serial number */ 00092 else if( nline == 2 ) 00093 { 00094 if( strncmp(line,"SerialNo:", 9) != 0 ) return( -1 ); 00095 begtok = line + 9; 00096 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00097 len = strlen(begtok); 00098 if( len > SM_VENDOR_LEN ) return( -1 ); 00099 strncpy( sm->sn, begtok, len ); 00100 } 00101 00102 /* Third line = number of channels */ 00103 else if( nline == 3 ) 00104 { 00105 if( strncmp(line,"nchan:", 5) != 0 ) return( -1 ); 00106 if( sscanf( line, "nchan: %d", &(sm->nch) ) != 1 ) return( -1 ); 00107 } 00108 00109 /* Fourth line = timestamp from field unit */ 00110 else if( nline == 4 ) 00111 { 00112 if( strncmp(line,"Field Time:", 11) != 0 ) return( -1 ); 00113 memset( &stm, 0, sizeof(struct tm) ); /* zero the time structure */ 00114 if( sscanf( line, "Field Time: %d/%d/%d %d:%d:%d.%d", 00115 &stm.tm_year, &stm.tm_mon, &stm.tm_mday, &stm.tm_hour, 00116 &stm.tm_min, &stm.tm_sec, &hsec ) != 7 ) return( -1 ); 00117 stm.tm_year -= 1900; /* to convert to definition of struct tm */ 00118 stm.tm_mon -= 1; /* to convert to definition of struct tm */ 00119 tsec = timegm( &stm ); 00120 sm->tfield = (double)tsec + 0.01*(double)hsec; 00121 } 00122 00123 /* Fifth line = alternate timestamp and its code */ 00124 else if( nline == 5 ) 00125 { 00126 if( strncmp(line,"Alternate Time:", 15) != 0 ) return( -1 ); 00127 memset( &stm, 0, sizeof(struct tm) ); /* zero the time structure */ 00128 if( sscanf( line, "Alternate Time: %d/%d/%d %d:%d:%d.%d code: %d", 00129 &stm.tm_year, &stm.tm_mon, &stm.tm_mday, &stm.tm_hour, 00130 &stm.tm_min, &stm.tm_sec, &hsec, &(sm->altcode) ) != 8 ) 00131 return( -1 ); 00132 if( stm.tm_year == 0 ) { 00133 sm->talt = 0.0; 00134 } else { 00135 stm.tm_year -= 1900; /* to convert to definition of struct tm */ 00136 stm.tm_mon -= 1; /* to convert to definition of struct tm */ 00137 tsec = timegm( &stm ); 00138 sm->talt = (double)tsec + 0.01*(double)hsec; 00139 } 00140 } 00141 00142 /* Sixth line = timestamp from DBMS (or other system) */ 00143 else if( nline == 6 ) 00144 { 00145 if( strncmp(line,"DBMS Load Time:", 15) != 0 ) return( -1 ); 00146 memset( &stm, 0, sizeof(struct tm) ); /* zero the time structure */ 00147 if( sscanf( line, "DBMS Load Time: %d/%d/%d %d:%d:%d.%d", 00148 &stm.tm_year, &stm.tm_mon, &stm.tm_mday, &stm.tm_hour, 00149 &stm.tm_min, &stm.tm_sec, &hsec ) != 7 ) return( -1 ); 00150 if( stm.tm_year == 0 ) { 00151 sm->tload = 0.0; 00152 } else { 00153 stm.tm_year -= 1900; /* to convert to definition of struct tm */ 00154 stm.tm_mon -= 1; /* to convert to definition of struct tm */ 00155 tsec = timegm( &stm ); 00156 sm->tload = (double)tsec + 0.01*(double)hsec; 00157 } 00158 } 00159 00160 /* Seventh line = SCNL names */ 00161 else if( nline == 7 ) 00162 { 00163 if( strncmp(line,"SCNL:", 5) != 0 ) return( -1 ); 00164 begtok = line + 5; 00165 for( i=0; i<sm->nch; i++ ) 00166 { 00167 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00168 if( begtok >= endline ) return( -1 ); 00169 len = tokenlength( begtok, '.' ); 00170 if( len > SM_STA_LEN ) return( -1 ); 00171 strncpy( sm->ch[i].sta, begtok, len ); 00172 begtok += len + 1; 00173 00174 if( begtok >= endline ) return( -1 ); 00175 len = tokenlength( begtok, '.' ); 00176 if( len > SM_COMP_LEN ) return( -1 ); 00177 strncpy( sm->ch[i].comp, begtok, len ); 00178 begtok += len + 1; 00179 00180 if( begtok >= endline ) return( -1 ); 00181 len = tokenlength( begtok, '.' ); 00182 if( len > SM_NET_LEN ) return( -1 ); 00183 strncpy( sm->ch[i].net, begtok, len ); 00184 begtok += len + 1; 00185 00186 if( begtok > endline ) return( -1 ); 00187 len = tokenlength( begtok, ' ' ); 00188 if( len > SM_LOC_LEN ) return( -1 ); 00189 strncpy( sm->ch[i].loc, begtok, len ); 00190 begtok += len + 1; 00191 } 00192 } 00193 00194 /* Eighth line = peak acceleration values */ 00195 else if( nline == 8 ) 00196 { 00197 if( strncmp(line,"Acc:", 4) != 0 ) return( -1 ); 00198 begtok = line + 4; 00199 for( i=0; i<sm->nch; i++ ) 00200 { 00201 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00202 if( begtok >= endline ) return( -1 ); 00203 if( sscanf( begtok, "%lf", &(sm->ch[i].acc) ) != 1 ) return( -1 ); 00204 begtok += tokenlength( begtok, ' ' ) + 1; 00205 } 00206 } 00207 00208 /* Ninth line = peak velocity values */ 00209 else if( nline == 9 ) 00210 { 00211 if( strncmp(line,"Vel:", 4) != 0 ) return( -1 ); 00212 begtok = line + 4; 00213 for( i=0; i<sm->nch; i++ ) 00214 { 00215 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00216 if( begtok >= endline ) return( -1 ); 00217 if( sscanf( begtok, "%lf", &(sm->ch[i].vel) ) != 1 ) return( -1 ); 00218 begtok += tokenlength( begtok, ' ' ) + 1; 00219 } 00220 } 00221 00222 /* Tenth line = peak displacement values */ 00223 else if( nline == 10 ) 00224 { 00225 if( strncmp(line,"Disp:", 5) != 0 ) return( -1 ); 00226 begtok = line + 5; 00227 for( i=0; i<sm->nch; i++ ) 00228 { 00229 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00230 if( begtok >= endline ) return( -1 ); 00231 if( sscanf( begtok, "%lf", &(sm->ch[i].disp) ) != 1 ) return( -1 ); 00232 begtok += tokenlength( begtok, ' ' ) + 1; 00233 } 00234 } 00235 00236 /* Eleventh line = number of points in the response spectrum */ 00237 else if( nline == 11 ) 00238 { 00239 if( strncmp(line,"nRSA:", 5) != 0 ) return( -1 ); 00240 begtok = line + 5; 00241 for( i=0; i<sm->nch; i++ ) 00242 { 00243 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00244 if( begtok >= endline ) return( -1 ); 00245 if( sscanf( begtok, "%d", &(sm->ch[i].nRSA) ) != 1 ) return( -1 ); 00246 begtok += tokenlength( begtok, ' ' ) + 1; 00247 if( sm->ch[i].nRSA > SM_MAX_RSA ) return( -1 ); 00248 } 00249 } 00250 00251 /* Remaining lines = response spectrum */ 00252 else if( nline > 11 ) 00253 { 00254 double tmp1, tmp2; 00255 if( strncmp(line,"frq/RSA:", 8) != 0 ) return( -1 ); 00256 begtok = line + 8; 00257 for( i=0; i<sm->nch; i++ ) 00258 { 00259 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00260 if( begtok >= endline ) return( -1 ); 00261 if( sscanf( begtok, "%lf/%lf", &tmp1, &tmp2 ) != 2 ) return( -1 ); 00262 if( nfreq < sm->ch[i].nRSA ) 00263 { 00264 sm->ch[i].freq[nfreq] = tmp1; 00265 sm->ch[i].RSA[nfreq] = tmp2; 00266 } 00267 begtok += tokenlength( begtok, '/' ) + 1; /* skip over freq field */ 00268 while( begtok[0] == ' ' ) begtok++; /* go to 1st non-blank char */ 00269 begtok += tokenlength( begtok, ' ' ) + 1; /* skip over RSA field */ 00270 } 00271 nfreq++; 00272 } 00273 00274 } /*end while*/ 00275 00276 00277 return( 0 ); 00278 } 00279 00280 /******************************************************************** 00281 * wr_strongmotion() * 00282 * Reads a SM_DATA structure and writes an ascii TYPE_STRONGMOTION * 00283 * message (null terminated) * 00284 * Returns 0 on success, -1 on failure (buffer overflow) * 00285 ********************************************************************/ 00286 int wr_strongmotion( SM_DATA *sm, char *buf, int buflen ) 00287 { 00288 char tmp[256]; /* working buffer */ 00289 int nchan; 00290 int nRSA; 00291 int i,j; 00292 00293 memset( buf, 0, (size_t)buflen ); /* zero output buffer */ 00294 nchan = ( sm->nch > SM_MAX_CHAN ) ? SM_MAX_CHAN : sm->nch ; 00295 00296 /* Print 3 header lines: vendor, serial number, nchan */ 00297 if( strlen(sm->vendor)==0 ) strcpy( sm->vendor, "unknown" ); /*KLUDGE*/ 00298 if( strlen(sm->sn)==0 ) strcpy( sm->sn, "unknown" ); /*KLUDGE*/ 00299 sprintf( tmp, "Vendor: %s\nSerialNo: %s\nnchan: %d\nField Time: ", 00300 sm->vendor, sm->sn, nchan ); 00301 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00302 00303 /* field time */ 00304 datestr23( sm->tfield, tmp, 256 ); 00305 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00306 00307 /* alternate time & its code */ 00308 if( strappend( buf, buflen, "\nAlternate Time: " ) ) return ( -1 ); 00309 if( sm->talt == 0.0 ) 00310 { 00311 if( strappend( buf, buflen, sNullDate ) ) return( -1 ); 00312 } else { 00313 datestr23( sm->talt, tmp, 256 ); 00314 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00315 } 00316 sprintf( tmp, " code: %d", sm->altcode ); 00317 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00318 00319 /* load time */ 00320 if( strappend( buf, buflen, "\nDBMS Load Time: " ) ) return ( -1 ); 00321 if( sm->tload == 0.0 ) 00322 { 00323 if( strappend( buf, buflen, sNullDate ) ) return( -1 ); 00324 } else { 00325 datestr23( sm->tload, tmp, 256 ); 00326 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00327 } 00328 00329 /* Print the SCNL names */ 00330 if( strappend( buf, buflen, "\nSCNL: " ) ) return( -1 ); 00331 for( i=0; i<nchan; i++ ) 00332 { 00333 sprintf( tmp, " %s.%s.%s.%s", 00334 sm->ch[i].sta, sm->ch[i].comp, sm->ch[i].net, sm->ch[i].loc ); 00335 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00336 } 00337 00338 /* Print peak acceleration values */ 00339 if( strappend( buf, buflen, "\nAcc: " ) ) return( -1 ); 00340 for( i=0; i<nchan; i++ ) 00341 { 00342 sprintf( tmp, " %15.6lf", sm->ch[i].acc ); 00343 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00344 } 00345 00346 /* Print peak velocity values */ 00347 if( strappend( buf, buflen, "\nVel: " ) ) return( -1 ); 00348 for( i=0; i<nchan; i++ ) 00349 { 00350 sprintf( tmp, " %15.6lf", sm->ch[i].vel ); 00351 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00352 } 00353 00354 /* Print peak displacement values */ 00355 if( strappend( buf, buflen, "\nDisp: " ) ) return( -1 ); 00356 for( i=0; i<nchan; i++ ) 00357 { 00358 sprintf( tmp, " %15.6lf", sm->ch[i].disp ); 00359 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00360 } 00361 00362 /* Print number of points in the response spectrum */ 00363 nRSA = 0; 00364 if( strappend( buf, buflen, "\nnRSA: " ) ) return( -1 ); 00365 for( i=0; i<nchan; i++ ) 00366 { 00367 if( sm->ch[i].nRSA < SM_MAX_RSA ) sprintf( tmp, " %15d", sm->ch[i].nRSA ); 00368 else sprintf( tmp, " %15d", SM_MAX_RSA ); 00369 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00370 if( nRSA < sm->ch[i].nRSA ) nRSA = sm->ch[i].nRSA; 00371 } 00372 00373 /* Print the response spectrum (frequency/acceleration pairs) */ 00374 if( nRSA > SM_MAX_RSA ) nRSA = SM_MAX_RSA; 00375 for( j=0; j<nRSA; j++ ) 00376 { 00377 if( strappend( buf, buflen, "\nfrq/RSA: " ) ) return( -1 ); 00378 for( i=0; i<nchan; i++ ) 00379 { 00380 if( j < sm->ch[i].nRSA ) /* print real values for this channel */ 00381 { 00382 sprintf( tmp, " %6.2lf/%.6lf", sm->ch[i].freq[j], sm->ch[i].RSA[j] ); 00383 } 00384 else /* print null values for this channel */ 00385 { 00386 sprintf( tmp, " %6.2lf/%.6lf", SM_NULL, SM_NULL ); 00387 } 00388 if( strappend( buf, buflen, tmp ) ) return( -1 ); 00389 } 00390 } 00391 if( strappend( buf, buflen, "\n" ) ) return( -1 ); 00392 00393 return( 0 ); 00394 } 00395 00396 00397 /******************************************************************** 00398 * log_strongmotion() * 00399 * Writes the contents of a SM_DATA structure to an Earthworm * 00400 * log file * 00401 ********************************************************************/ 00402 void log_strongmotion( SM_DATA *sm ) 00403 { 00404 char date[30]; 00405 int nRSA, i, j; 00406 00407 logit("", "Vendor:%s sn:%s nch:%d\n", sm->vendor, sm->sn, sm->nch ); 00408 00409 /* Log time values */ 00410 datestr23( sm->tfield, date, 30 ); 00411 logit("", "Field Time: %s (%.2lf)\n", date, sm->tfield ); 00412 if( sm->talt != 0.0 ) { 00413 datestr23( sm->talt, date, 30 ); 00414 logit("", "Alternate Time: %s (%.2lf) code: %d\n", 00415 date, sm->talt, sm->altcode ); 00416 } else { 00417 logit("", "Alternate Time: %s (%.2lf) code: %d\n", 00418 sNullDate, sm->talt, sm->altcode ); 00419 } 00420 00421 if( sm->talt != 0.0 ) { 00422 datestr23( sm->tload, date, 30 ); 00423 logit("", "DBMS Load Time: %s (%.2lf)\nSCNL:", date, sm->tload ); 00424 } else { 00425 logit("", "DBMS Load Time: %s (%.2lf)\nSCNL:", sNullDate, sm->tload ); 00426 } 00427 00428 /* Log station codes */ 00429 for( i=0; i<sm->nch; i++ ) 00430 { 00431 logit("", " %s.%s.%s.%s", 00432 sm->ch[i].sta, sm->ch[i].comp, sm->ch[i].net, sm->ch[i].loc ); 00433 } 00434 00435 /* Log peak acceleration values */ 00436 logit("", "\nAcc: "); 00437 for( i=0; i<sm->nch; i++ ) 00438 { 00439 logit("", " %15.6lf", sm->ch[i].acc ); 00440 } 00441 00442 /* Log peak velocity values */ 00443 logit("", "\nVel: "); 00444 for( i=0; i<sm->nch; i++ ) 00445 { 00446 logit("", " %15.6lf", sm->ch[i].vel ); 00447 } 00448 00449 /* Log peak displacement values */ 00450 logit("","\nDisp: "); 00451 for( i=0; i<sm->nch; i++ ) 00452 { 00453 logit("", " %15.6lf", sm->ch[i].disp ); 00454 } 00455 00456 /* Log number of points in the response spectrum */ 00457 nRSA = 0; 00458 logit("","\nnRSA: "); 00459 for( i=0; i<sm->nch; i++ ) 00460 { 00461 logit("", " %15d", sm->ch[i].nRSA ); 00462 if( nRSA < sm->ch[i].nRSA ) nRSA = sm->ch[i].nRSA; 00463 } 00464 00465 /* Log the response spectrum (frequency/acceleration pairs) */ 00466 for( j=0; j<nRSA; j++ ) 00467 { 00468 logit("", "\nfrq/RSA: " ); 00469 for( i=0; i<sm->nch; i++ ) 00470 { 00471 if( j < sm->ch[i].nRSA ) /* print real values for this channel */ 00472 { 00473 logit("", " %6.2lf/%8.6lf", sm->ch[i].freq[j], sm->ch[i].RSA[j] ); 00474 } 00475 else /* print null values for this channel */ 00476 { 00477 logit("", " %6.2lf/%8.6lf", SM_NULL, SM_NULL ); 00478 } 00479 } 00480 } 00481 logit("","\n"); 00482 00483 return; 00484 } 00485 00486 /******************************************************************** 00487 * strappend() append second null-terminated character string to * 00488 * the first as long as there's enough room in the target buffer * 00489 * for both strings an the null-byte * 00490 ********************************************************************/ 00491 int strappend( char *s1, int s1max, char *s2 ) 00492 { 00493 if( (int)strlen(s1)+(int)strlen(s2)+1 > s1max ) return( -1 ); 00494 strcat( s1, s2 ); 00495 return( 0 ); 00496 } 00497 00498 /******************************************************************** 00499 * tokenlength() given a null-terminated character string and a * 00500 * character that delimits the end of a token, tokenlength returns * 00501 * the length (in bytes) of the next token. If the character wasn't * 00502 * found, tokenlength returns the length of the string. * 00503 ********************************************************************/ 00504 int tokenlength( char *begtok, char c ) 00505 { 00506 char *endtok; /* points to the end of this token */ 00507 00508 endtok = strchr( begtok, c ); 00509 if( endtok == NULL ) return( (int)strlen(begtok) ); 00510 return( (int)(endtok-begtok) ); 00511 }