bufr2synop 0.24.0
Functions
bufr2tac_utils.c File Reference

file with the utility routines for binary bufr2tac More...

#include "bufr2tac.h"
Include dependency graph for bufr2tac_utils.c:

Go to the source code of this file.

Functions

unsigned int three_bytes_to_uint (const unsigned char *source)
 returns the integer value from an array of three bytes, most significant first More...
 
int integer_to_descriptor (struct bufr_descriptor *d, int id)
 parse an integer with a descriptor fom bufr ECWMF libary More...
 
int descriptor_to_integer (int *id, struct bufr_descriptor *d)
 parse a descriptor and sets an integer in the decimal formas fxxyyy More...
 
uint32_t get_flag_value (uint8_t width, uint8_t index)
 
char * charray_to_string (char *s, unsigned char *buf, size_t size)
 get a null termitated c-string from an array of unsigned chars More...
 
char * adjust_string (char *s)
 Supress trailing blanks of a string. More...
 
size_t tokenize_string (char *tk[], size_t ntk, char *target, size_t len, char *blanks)
 Split the report string into tokens. More...
 
int YYYYMMDDHHmm_to_met_datetime (struct met_datetime *t, const char *source)
 Parse the string YYYYMMDDHHmm[ss] and set a struct met_datetime. More...
 
char * met_datetime_to_YYGG (char *target, struct met_datetime *t)
 Get YYGG from a struct met_datetime. More...
 
int round_met_datetime_to_hour (struct met_datetime *target, struct met_datetime *source)
 
char * guess_WMO_region (char *A1, char *Reg, const char *II, const char *iii)
 get WMO region A1 and Reg items from II and iii (WMO index) More...
 
int check_date_from_future (struct metreport *m)
 Check a estructure metreport not from future. More...
 
int guess_gts_header (struct gts_header *h, const char *f)
 Guess the WMO GTS header from filename. More...
 

Detailed Description

file with the utility routines for binary bufr2tac

Definition in file bufr2tac_utils.c.

Function Documentation

◆ adjust_string()

char * adjust_string ( char *  s)

Supress trailing blanks of a string.

Parameters
sstring to process

Definition at line 99 of file bufr2tac_utils.c.

100{
101 size_t l;
102 l = strlen ( s );
103 while ( l && s[--l] == ' ' )
104 s[l] = '\0';
105 return s;
106}

Referenced by buoy_parse_x01(), climat_parse_x01(), syn_parse_x01(), and temp_parse_x01().

Here is the caller graph for this function:

◆ charray_to_string()

char * charray_to_string ( char *  s,
unsigned char *  buf,
size_t  size 
)

get a null termitated c-string from an array of unsigned chars

Parameters
sresulting string
bufpointer to first element in array
sizenumber of chars in array

Definition at line 85 of file bufr2tac_utils.c.

86{
87 // copy
88 memcpy ( s , buf, size );
89 // add final string mark
90 s[size] = '\0';
91 return s;
92}

◆ check_date_from_future()

int check_date_from_future ( struct metreport m)

Check a estructure metreport not from future.

Parameters
mpointer to a struct metreport to check about date and time

It resturns 1 if date/time is from future, and likely wrong Returns 0 otherwise

Definition at line 292 of file bufr2tac_utils.c.

293{
294 time_t now;
295
296 now = time ( NULL );
297 if ( m->t.t > ( now + 1800 ) ) // Still 1/2 hour courtesy
298 return 1;
299 else
300 return 0;
301}
time_t t
Definition: metcommon.h:61
struct met_datetime t
Definition: bufr2tac.h:314

References metreport::t, and met_datetime::t.

Referenced by parse_subset_as_climat(), and parse_subset_as_synop().

Here is the caller graph for this function:

◆ descriptor_to_integer()

int descriptor_to_integer ( int *  id,
struct bufr_descriptor d 
)

parse a descriptor and sets an integer in the decimal formas fxxyyy

Parameters
idpointer to target integer
dpointer to a struct bufr_descriptor with the source

Definition at line 58 of file bufr2tac_utils.c.

59{
60 if ( d == NULL )
61 return 1;
62 *id = 100000 * d->f + 1000 * d->x + d->y;
63 return 0;
64}

References bufr_descriptor::f, bufr_descriptor::x, and bufr_descriptor::y.

Referenced by bufrtotac_parse_subset_sequence().

Here is the caller graph for this function:

◆ get_flag_value()

uint32_t get_flag_value ( uint8_t  width,
uint8_t  index 
)

Definition at line 66 of file bufr2tac_utils.c.

67{
68 if ( width == index )
69 return ( uint32_t ) 1;
70 else if ( width < index )
71 return ( uint32_t ) 0;
72 else if ( width <= 32 )
73 return ( ( ( uint32_t ) 1 ) << ( width - index ) );
74 else
75 return ( uint32_t ) 0;
76}

◆ guess_gts_header()

int guess_gts_header ( struct gts_header h,
const char *  f 
)

Guess the WMO GTS header from filename.

Parameters
hpointer to a struct gts_header where to set the results
fpathname of bufrfile

It returns 1 if guessed, 0 otherwise

This routine assume the filename format of a bufr file is

  YYYYMMDDHHmmss_BULLNN_ICAO_YYGGgg_ORD.bufr

where

 YYYYMMDDHHmmss

is the timestamp (UTC) of the file in GTS (as example, in NOAA gateway)

BULLNN is the bulletin identifier in GTS. It is a six chars lenght in the form T1 T2 A1 A2 N1 N2

  For observations, T1 is 'I'
  Possible values of T2 for T1 = 'I' are
     O   Oceanographic/limnographic (water properties)
     P   Pictorial
     S   Surface/sea level
     T   Text (plain language information)
     U   Upper air
     X   Other data types
     Z   Mixed data types


  For T1T2 = 'IS' Then A1:

     IS A 01–29 Routinely scheduled observations for n/a 000/006
                distribution from automatic (fixed or mobile)
                land stations (e.g. 0000, 0100, … or 0220, 0240,
                0300, …, or 0715, 0745, ... UTC)
     IS A 30–59 N-minute observations from automatic (fixed n/a 000/007
                or mobile) land stations
     IS B   Radar reports (parts A and B) RADOB 006/003
     IS C 01–45 Climatic observations from land stations CLIMAT 000/020
     IS C 46–59 Climatic observations from marine stations CLIMAT SHIP 001/0202009 edition
                ATTACHmENT II-5 I
     IS D   Radiological observation RADREP 010/001
     IS E   Ozone measurement at surface n/a 008/000
     IS F   Source of atmospherics SFAZI, SFLOC, SFAZU 000/030
     IS I 01–45 Intermediate synoptic observations from fixed SYNOP (SIxx) 000/001
            land stations 000/051
     IS I 46–59 Intermediate synoptic observations from mobile SYNOP mOBIL 000/004
            land stations
     IS M 01–45 Main synoptic observations from fixed land SYNOP (SMxx) 000/002
            stations 000/052
     IS M 46–59 Main synoptic observations from mobile land SYNOP mOBIL 000/005
             stations
     IS N 01–45 Synoptic observations from fixed land stations SYNOP (SNxx) 000/000
            at non-standard time (i.e. 0100, 0200, 0400,   000/050
            0500, ... UTC)
     IS N 46–59 Synoptic observations from mobile land stations SYNOP mOBIL 000/003
            at non-standard time (i.e. 0100, 0200, 0400,
            0500, ... UTC)
     IS R   Hydrologic reports HYDRA 000/040
     IS S 01–19 Synoptic observations from marine stations SHIP 001/000
     IS S 20–39 One-hour observations from automatic marine n/a 001/006
           stations
     IS S 40–59 N-minute observations from automatic marine n/a 001/007
           stations
     IS T 01–19 Tide gauge observations n/a 001/030
     IS T 20–39 Observed water level time series n/a 001/031
     IS V   Special aeronautical observations (SPECI) SPECI 000/011
     IS W   Aviation routine weather observations (mETAR) mETAR 000/010
     IS X   Other surface data IAC, IAC FLEET

  For T1T2 = 'IU'  then A1:
     IU A   Single level aircraft reports (automatic) AmDAR 004/000
     IU A   Single level aircraft reports (manual) AIREP/PIREP 004/001
     IU B   Single level balloon reports n/a
     IU C   (used for single level satellite-derived SAREP/SATOB 005/000
             reports – see Note 3)
     IU D   Dropsonde/Dropwindsondes TEmP DROP 002/007
     IU E   Ozone vertical sounding n/a 008/001
     IU I   Dispersal and transport analysis n/a 009/000
     IU J 01–19 Upper wind from fixed land stations (entire PILOT (parts A, 002/001
            sounding) B, C, D)
     IU J 20–39 Upper wind from mobile land stations (entire PILOT mOBIL 002/003
            sounding) (parts A, B, C, D)
     IU J 40–59 Upper wind from marine stations (entire PILOT SHIP 002/002
           sounding) (parts A, B, C, D)
     IU K 01–19 Radio soundings from fixed land stations TEmP (parts A, B) 002/004
           (up to 100 hPa)
     IU K 20–39 Radio soundings from mobile land stations TEmP mOBIL 002/006
          (up to 100 hPa) (parts A, B)
     IU K 40–59 Radio soundings from marine stations TEmP SHIP (parts A, B) 002/005
           (up to 100 hPa)
     IU M   Model derived sondes
     IU N   Rocketsondes
     IU O   Profiles of aircraft observations in ascending/ AmDAR 002/020
            descending
     IU P   Profilers PILOT 002/010
     IU Q   RASS temperature profilers TEmP 002/011
     IU R   (used for radiance data – see Note 3)
     IU S   01–19 Radiosondes/pibal reports from fixed land TEmP (parts A, B, C, D) 002/004
             stations (entire sounding)
     IU S 20–39 Radio soundings from mobile land stations TEmP mOBIL (parts A, 002/006
             (entire sounding) B, C, D)
     IU S 40–59 Radio soundings from marine stations TEmP SHIP (parts A, 002/005
             (entire sounding) B, C, D)
     IU T   (used for satellite-derived sondes – see Note 3) SATEm, SARAD, SATOB
     IU U 01–45 Monthly statistics of data from upper-air stations CLImAT TEmP 002/025
     IU U 46–59 Monthly statistics of data from marine stations CLImAT TEmP, SHIP 002/026
     IU W 01–19 Upper wind from fixed land stations (up to PILOT (parts A, B) 002/001
             100 hPa)
     IU W 20–39 Upper wind from mobile land stations (up to PILOT mOBIL 002/003
             100 hPa) (parts A, B)
     IU W 40–59 Upper wind from marine stations (up to PILOT SHIP 002/002
             100 hPa) (parts A, B)
     IU X   Other upper-air reports

  for T1T2 = 'IO' then  A1:
     IO B   Buoy observations BUOY 001/025
     IO I   Sea ice
     IO P   Sub-surface profiling floats TESAC 031/004
     IO R   Sea surface observations TRACKOB 031/001
     IO S   Sea surface and below soundings BATHY, TESAC 031/005
     IO T   Sea surface temperature
     IO W   Sea surface waves WAVEOB 031/002
     IO X   Other sea environmental

  About A2
     A   0 - 90W northern hemisphere
     B   90W - 180 northern hemisphere
     C   180 - 90E northern hemisphere
     D   90E - 0 northern hemisphere
     E   0 - 90W tropical belt
     F   90W - 180 tropical belt
     G   180 - 90E tropical belt
     H   90E - 0 tropical belt
     I   0 - 90W southern hemisphere
     J   90W - 180 southern hemisphere
     K   180 - 90E southern hemisphere
     L   90E - 0 southern hemisphere
     M   Lower left 10S 100E/upper right 70N 110W
     N   Northern hemisphere
     P   Area between 64.69N - 136.76W, 55.61N - 13.43W
     64.69N - 156.76W, 55.61N - 33.43W
     S   Southern hemisphere
     T   45W - 180 northern hemisphere
     U   Area between 21.0N - 128.1W, 36.0N - 130.9W
               21.1N - 113.0W, 36.2N - 110.5W
     V   Area between 30.3N - 83.7W, 51.0N - 68.9W
               19.8N - 64.5W, 33.3N - 47.1W
     X   Global Area (area not definable)


 ICAO is the ICAO index for release center.

 YYGGgg is the nominal release time (day, hour, minute) UTC

 ORD is the order sequence as RRA, RRB, CCA .... is optional

Definition at line 466 of file bufr2tac_utils.c.

467{
468 size_t nt;
469 char aux[256], *tk[16], *c;
470
471 // parse file name
472 strcpy ( h->filename, f );
473 strcpy ( aux, f );
474
475 // check latest '/' in filename
476 if ( ( c = strrchr ( aux,'/' ) ) == NULL )
477 c = &aux[0];
478 else
479 c++;
480
481 nt = tokenize_string ( tk, 16, c, strlen ( c ), "_. " );
482 // parse filenames with format as example 'AAAAMMDDHHmmss_ISIE06_SBBR_012100_RRB.bufr'
483
484 // 5 or 6 items
485 if ( nt < 5 || nt > 6 )
486 return 0;
487
488 // extension bufr
489 if ( strcmp ( tk[nt - 1],"bufr" ) )
490 return 0;
491
492 // item 0 the timestamp of file in NOAA GTS gateway
493 if ( strlen ( tk[0] ) != 14 || strspn ( tk[0], "0123456789" ) != 14 )
494 return 0;
495 strcpy ( h->timestamp, tk[0] );
496
497 // item 1
498 if ( strlen ( tk[1] ) != 6 || strspn ( &tk[1][4],"0123456789" ) != 2 )
499 return 0;
500 strcpy ( h->bname, tk[1] );
501
502 // item 2
503 if ( strlen ( tk[2] ) != 4 )
504 return 0;
505 strcpy ( h->center, tk[2] );
506
507 if ( strlen ( tk[3] ) != 6 || strspn ( tk[3], "0123456789" ) != 6 )
508 return 0;
509 strcpy ( h->dtrel, tk[3] );
510
511 if ( nt == 5 )
512 {
513 strcpy ( h->order, "BBB" );
514 }
515 else
516 {
517 if ( strlen ( tk[4] ) == 3 )
518 strcpy ( h->order, tk[4] );
519 else
520 return 0;
521 }
522
523 return 1;
524}
size_t tokenize_string(char *tk[], size_t ntk, char *target, size_t len, char *blanks)
Split the report string into tokens.
char center[8]
Definition: bufrdeco.h:709
char dtrel[16]
Definition: bufrdeco.h:710
char order[8]
Definition: bufrdeco.h:711
char bname[16]
Definition: bufrdeco.h:708
char filename[BUFRDECO_PATH_LENGTH]
Definition: bufrdeco.h:712
char timestamp[16]
Definition: bufrdeco.h:713

References gts_header::bname, gts_header::center, gts_header::dtrel, gts_header::filename, gts_header::order, gts_header::timestamp, and tokenize_string().

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ guess_WMO_region()

char * guess_WMO_region ( char *  A1,
char *  Reg,
const char *  II,
const char *  iii 
)

get WMO region A1 and Reg items from II and iii (WMO index)

Parameters
A1string woth resulting A1
Regstring with resulting Reg
IIWMO block number
iiiWMO number

Definition at line 211 of file bufr2tac_utils.c.

212{
213 char aux[8];
214
215 // filter bad inputs
216 if ( II == NULL || iii == NULL )
217 return NULL;
218
219 if ( II[0] == 0 || iii[0] == 0 )
220 return NULL;
221
222 // aux string
223 sprintf ( aux,"%s%s", II, iii );
224
225 if ( ( II[0] == '0' && ( strstr ( aux,"042" ) != aux ) && ( strstr ( aux,"043" ) != aux ) &&
226 ( strstr ( aux,"044" ) != aux ) && ( strstr ( aux,"0858" ) != aux ) && ( strstr ( aux,"0859" ) != aux ) ) ||
227 II[0] == '1' || ( strstr ( aux,"201" ) == aux ) ||
228 strcmp ( II,"22" ) == 0 || strcmp ( II,"26" ) == 0 || strcmp ( II,"27" ) == 0 ||
229 strcmp ( II,"33" ) == 0 || strcmp ( II,"34" ) == 0 || strcmp ( II,"22" ) == 0 ||
230 ( strstr ( aux,"201" ) == aux ) )
231 {
232 // Reg 6. Europe
233 A1[0] = '6';
234 strcpy ( Reg,"VI" );
235 }
236 else if ( II[0] == '6' || ( strstr ( aux,"0858" ) == aux ) || ( strstr ( aux,"0859" ) == aux ) )
237 {
238 // Reg 1. Africa
239 A1[0] = '1';
240 strcpy ( Reg,"I" );
241 }
242 else if ( II[0] == '5' || ( strcmp ( II,"49" ) == 0 ) || ( strcmp ( II,"21" ) == 0 ) ||
243 ( strcmp ( II,"23" ) == 0 ) || ( strcmp ( II,"24" ) == 0 ) || ( strcmp ( II,"25" ) == 0 ) ||
244 ( strcmp ( II,"28" ) == 0 ) || ( strcmp ( II,"29" ) == 0 ) || ( strcmp ( II,"30" ) == 0 ) ||
245 ( strcmp ( II,"31" ) == 0 ) || ( strcmp ( II,"32" ) == 0 ) || ( strcmp ( II,"38" ) == 0 ) ||
246 ( strcmp ( II,"35" ) == 0 ) || ( strcmp ( II,"36" ) == 0 ) || ( strcmp ( II,"39" ) == 0 ) ||
247 ( strcmp ( aux, "20200" ) >= 0 && strcmp ( aux, "20999" ) <= 0 ) ||
248 ( strcmp ( aux, "40000" ) >= 0 && strcmp ( aux, "48599" ) <= 0 ) ||
249 ( strcmp ( aux, "48800" ) >= 0 && strcmp ( aux, "49999" ) <= 0 ) )
250 {
251 // Reg 2. Asia
252 A1[0] = '2';
253 strcpy ( Reg,"II" );
254 }
255 else if ( strcmp ( aux, "80000" ) >= 0 && strcmp ( aux, "88999" ) <= 0 )
256 {
257 // Reg 3. South america
258 A1[0] = '3';
259 strcpy ( Reg,"III" );
260 }
261 else if ( II[0] == '7' || strstr ( aux,"042" ) == aux ||
262 strstr ( aux,"043" ) == aux || strstr ( aux,"044" ) == aux )
263 {
264 // Reg 4. North and central america
265 A1[0] = '4';
266 strcpy ( Reg,"IV" );
267 }
268 else if ( ( strcmp ( aux, "48600" ) >= 0 && strcmp ( aux, "48799" ) <= 0 ) ||
269 ( strcmp ( aux, "90000" ) >= 0 && strcmp ( aux, "98999" ) <= 0 ) )
270 {
271 // Reg 5. Pacific South
272 A1[0] = '5';
273 strcpy ( Reg,"V" );
274 }
275 else if ( strcmp ( II,"89" ) == 0 )
276 {
277 // Reg 0. Antarctica
278 A1[0] = '0';
279 strcpy ( Reg,"0" );
280 }
281 return A1;
282}

Referenced by guess_WMO_region_synop(), guess_WMO_region_temp(), and syn_parse_x01().

Here is the caller graph for this function:

◆ integer_to_descriptor()

int integer_to_descriptor ( struct bufr_descriptor d,
int  id 
)

parse an integer with a descriptor fom bufr ECWMF libary

Parameters
dpointer to a struct bufr_descriptor where to set the result on output
idinteger with the descriptor from ewcwf

Definition at line 41 of file bufr2tac_utils.c.

42{
43 if ( d == NULL )
44 return 1;
45 d->f = id / 100000;
46 d->x = ( id % 100000 ) / 1000;
47 d->y = id % 1000;
48 sprintf ( d->c, "%06d", id );
49 return 0;
50}
char c[12]
Definition: bufrdeco.h:414

References bufr_descriptor::c, bufr_descriptor::f, bufr_descriptor::x, and bufr_descriptor::y.

◆ met_datetime_to_YYGG()

char * met_datetime_to_YYGG ( char *  target,
struct met_datetime t 
)

Get YYGG from a struct met_datetime.

Parameters
targetstring with result as output
tpointer to source struct met_datetime

Definition at line 180 of file bufr2tac_utils.c.

181{
182 time_t tx;
183 struct tm tim;
184
185 tx = ( ( t->t + 1800 ) / 3600 ) * 3600 ; // rounding to next whole hour
186 memset ( &tim, 0, sizeof ( struct tm ) );
187 gmtime_r ( &tx, &tim );
188
189 strftime ( target, 8, "%d%H", &tim );
190
191 return target;
192}

References met_datetime::t.

Referenced by parse_subset_as_temp().

Here is the caller graph for this function:

◆ round_met_datetime_to_hour()

int round_met_datetime_to_hour ( struct met_datetime target,
struct met_datetime source 
)

Definition at line 194 of file bufr2tac_utils.c.

195{
196 target->t = ( ( source->t + 1800 ) / 3600 ) * 3600 ; // rounding to next whole hour
197 memset ( &target->tim, 0, sizeof ( struct tm ) );
198 gmtime_r ( &target->t, &target->tim );
199 strftime ( target->datime, 16, "%Y%m%d%H%M", &target->tim );
200 return 0;
201}
char datime[16]
Definition: metcommon.h:63
struct tm tim
Definition: metcommon.h:62

References met_datetime::datime, met_datetime::t, and met_datetime::tim.

Referenced by parse_subset_as_temp().

Here is the caller graph for this function:

◆ three_bytes_to_uint()

unsigned int three_bytes_to_uint ( const unsigned char *  source)

returns the integer value from an array of three bytes, most significant first

Definition at line 30 of file bufr2tac_utils.c.

31{
32 return ( source[2] + source[1] * 256 + source[0] * 65536 );
33}

Referenced by read_bufr().

Here is the caller graph for this function:

◆ tokenize_string()

int tokenize_string ( char *  tk[],
size_t  ntk,
char *  target,
size_t  len,
char *  blanks 
)

Split the report string into tokens.

Parameters
tkarray of strings. Memory have to be allocated previously by caller
ntkmax amount of elements in tk array.
targetstring which is the report to split
lenlenght of target string
blanksstring with the character considered as blanks. If null the default " =\n\r\v\t" is considered Returns the number of tokens target has been splitted into. Retuns 0 in case of a void or too large target. NOTE: target is changed after calling this routine. In fact, the pointers in tk[] are linking to some char in string target

Definition at line 121 of file bufr2tac_utils.c.

122{
123 size_t i = 1, n;
124 char d[] = " =\n\r\v\t", *b, *aux;
125
126 // set the blanks array
127 if ( blanks == NULL )
128 b = &d[0];
129 else
130 b = blanks;
131
132 // check target string limits
133 n = strlen ( target );
134 if ( n == 0 || n > len )
135 return 0;
136
137 // the split loop
138 tk[0] = strtok_r ( target, b, &aux );
139 while ( i < ntk &&
140 ( ( tk[i] = strtok_r ( NULL, b, &aux ) ) != NULL ) &&
141 strlen ( tk[i] ) > 2 &&
142 strlen ( tk[i] ) < 10 )
143 i++;
144 if ( i < ntk )
145 return i;
146 else
147 return ntk - 1;
148}

Referenced by guess_gts_header().

Here is the caller graph for this function:

◆ YYYYMMDDHHmm_to_met_datetime()

int YYYYMMDDHHmm_to_met_datetime ( struct met_datetime t,
const char *  source 
)

Parse the string YYYYMMDDHHmm[ss] and set a struct met_datetime.

Parameters
sourcestring with date in YYYYMMDDHHmm[ss] format
tpointer to a struct met_datetime where to set the results

Definition at line 156 of file bufr2tac_utils.c.

157{
158 if ( strlen ( source ) != 12 && strlen ( source ) != 14 )
159 return 1;
160 memset ( &t->tim, 0, sizeof ( struct tm ) );
161 if ( strlen ( source ) == 12 )
162 {
163 strptime ( source, "%Y%m%d%H%M", &t->tim );
164 }
165 else
166 {
167 strptime ( source, "%Y%m%d%H%M%S", &t->tim );
168 }
169 strcpy ( t->datime, source );
170 t->t = mktime ( &t->tim );
171 return 0;
172}

References met_datetime::datime, met_datetime::t, and met_datetime::tim.

Referenced by parse_subset_as_buoy(), parse_subset_as_climat(), parse_subset_as_synop(), and parse_subset_as_temp().

Here is the caller graph for this function: