bufr2synop 0.24.0
bufr2tac_synop.c
Go to the documentation of this file.
1/***************************************************************************
2 * Copyright (C) 2013-2022 by Guillermo Ballester Valor *
3 * gbv@ogimet.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20/*!
21 \file bufr2tac_synop.c
22 \brief file with the code to parse a sequence as a SYNOP FM-12, FM-13 and FM-14
23 */
24#include "bufr2tac.h"
25
26/*!
27 \fn int synop_YYYYMMDDHHmm_to_YYGG(struct synop_chunks *syn)
28 \brief Sets YYGG from YYYYMMDDHHmm extended group
29 \param syn pointer to the target struct \ref synop_chunks
30*/
32{
33 char aux[20];
34 char tz[256], *c;
35 time_t t;
36 struct tm tim;
37
38 if ( strlen ( syn->e.YYYY ) &&
39 strlen ( syn->e.MM ) &&
40 strlen ( syn->e.DD ) &&
41 strlen ( syn->e.HH ) &&
42 strlen ( syn->e.mm ) )
43 {
44 sprintf ( aux,"%s%s%s%s%s", syn->e.YYYY, syn->e.MM, syn->e.DD, syn->e.HH, syn->e.mm );
45 }
46
47 if ( strlen ( aux ) != 12 )
48 {
49 return 1;
50 }
51
52 // Get current TZ
53 tz[0] = '\0';
54 c = getenv ( "TZ" );
55 if ( c != NULL && c[0] && strlen ( c ) < 256 )
56 {
57 strcpy ( tz, c );
58 }
59
60 // Set TZ to UTC
61 setenv ( "TZ", "UTC", 1 );
62 tzset();
63
64 memset ( &tim, 0, sizeof ( struct tm ) );
65 strptime ( aux, "%Y%m%d%H%M", &tim );
66
67 t = mktime ( &tim ) + 1799 ; // rounding trick
68 gmtime_r ( &t, &tim );
69 sprintf ( syn->s0.YY, "%02d", tim.tm_mday );
70 sprintf ( syn->s0.GG, "%02d", tim.tm_hour );
71
72 // Revert TZ changes
73 if ( tz[0] )
74 {
75 setenv ( "TZ", tz, 1 );
76 tzset();
77 }
78 else
79 {
80 unsetenv ( "TZ" );
81 }
82
83 return 0;
84}
85
86/*!
87 \fn char *guess_WMO_region_synop(struct synop_chunks *syn)
88 \brief Try to find WMO region if it is not already set and WMO Block and number index are known
89 \param syn pointer to the struct \ref synop_chunks with all known data for a synop
90
91 It returns a pointer to the string with WMO region
92*/
94{
95 if ( syn->s0.A1[0] )
96 {
97 return syn->s0.A1;
98 }
99
100 if ( syn->s0.II[0] == 0 || syn->s0.iii[0] == 0 )
101 {
102 return syn->s0.A1;
103 }
104
105 return guess_WMO_region ( syn->s0.A1, syn->s0.Reg, syn->s0.II, syn->s0.iii );
106}
107
108
109/*!
110 \fn int parse_subset_as_synop (struct metreport *m, struct bufr2tac_subset_state *s, struct bufr_subset_sequence_data *sq, char *err )
111 \brief parses a subset sequence as an Land fixed SYNOP FM-12, SHIP FM-13 or SYNOP-mobil FM-14 report
112 \param m pointer to a struct \ref metreport where set some results
113 \param s pointer to a struct \ref bufr2tac_subset_state
114 \param sq pointer to a struct \ref bufr_subset_sequence_data with the parsed sequence on input
115 \param err string with detected errors, if any
116
117 It return 0 if all is OK. Otherwise returns 1 and it also fills the \a err string
118*/
119int parse_subset_as_synop ( struct metreport *m, struct bufr2tac_subset_state *s, struct bufr_subset_sequence_data *sq, char *err )
120{
121 size_t is;
122 char aux[32];
123 struct synop_chunks *syn;
124
125 // An auxiliar pointer
126 syn = &m->synop;
127
128 // clean data
130
131 // reject if still not coded type
132 if ( strcmp ( s->type_report,"AAXX" ) && strcmp ( s->type_report,"BBXX" ) && strcmp ( s->type_report,"OOXX" ) )
133 {
134 sprintf ( err,"bufr2tac: parse_subset_as_synop(): '%s' reports still not decoded in this software", s->type_report );
135 return 1;
136 }
137
138 syn->s0.MiMi[0] = s->type_report[0];
139 syn->s0.MiMi[1] = s->type_report[1];
140 syn->s0.MjMj[0] = s->type_report[2];
141 syn->s0.MjMj[1] = s->type_report[3];
142
143 strcpy ( m->type, s->type_report );
144
145 /**** First pass, sequential analysis *****/
146 for ( is = 0; is < sq->nd; is++ )
147 {
148 // check if is a significance qualifier
149 if ( sq->sequence[is].desc.x == 8 )
150 {
151 s->i = is;
152 s->a = &sq->sequence[is];
153 s->ival = ( int ) sq->sequence[is].val;
154 s->val = sq->sequence[is].val;
155 syn_parse_x08 ( syn, s );
156 }
157 if ( s->isq ) // case of a significance qualifier
158 {
159 continue;
160 }
161
162 s->i = is;
163 s->ival = ( int ) ( sq->sequence[is].val );
164 s->val = sq->sequence[is].val;
165 s->a = &sq->sequence[is];
166 if ( is > 0 )
167 {
168 s->a1 = &sq->sequence[is - 1];
169 }
170
171 switch ( sq->sequence[is].desc.x )
172 {
173 case 1: //localization descriptors
174 syn_parse_x01 ( syn, s );
175 break;
176
177 case 2: //Type of station descriptors
178 syn_parse_x02 ( syn, s );
179 break;
180
181 case 4: //Date and time descriptors
182 syn_parse_x04 ( syn, s );
183 break;
184
185 case 5: // Horizontal position. Latitude
186 syn_parse_x05 ( syn, s );
187 break;
188
189 case 6: // Horizontal position. Longitude
190 syn_parse_x06 ( syn, s );
191 break;
192
193 case 7: // Vertical position
194 syn_parse_x07 ( syn, s );
195 break;
196
197 case 10: // Air Pressure descriptors
198 syn_parse_x10 ( syn, s );
199 break;
200
201 case 11: // wind data
202 syn_parse_x11 ( syn, s );
203 break;
204
205 case 12: //Temperature descriptors
206 syn_parse_x12 ( syn, s );
207 break;
208
209 case 13: // Humidity and precipitation data
210 syn_parse_x13 ( syn, s );
211 break;
212
213 case 14: // Radiation
214 syn_parse_x14 ( syn, s );
215 break;
216
217 case 20: // Cloud data
218 syn_parse_x20 ( syn, s );
219 break;
220
221 case 22: // Oceanographic data
222 syn_parse_x22 ( syn, s );
223 break;
224
225 case 31: // Replicators
226 syn_parse_x31 ( syn, s );
227 break;
228
229
230 default:
231 break;
232 }
233 }
234
235 /* Check about needed descriptors */
236 if ( ( ( s->mask & SUBSET_MASK_HAVE_LATITUDE ) == 0 ) ||
237 ( ( s->mask & SUBSET_MASK_HAVE_LONGITUDE ) == 0 ) ||
238 ( ( s->mask & SUBSET_MASK_HAVE_YEAR ) == 0 ) ||
239 ( ( s->mask & SUBSET_MASK_HAVE_MONTH ) == 0 ) ||
240 ( ( s->mask & SUBSET_MASK_HAVE_DAY ) == 0 ) ||
241 ( ( s->mask & SUBSET_MASK_HAVE_HOUR ) == 0 ) ||
242 ( ( s->mask & SUBSET_MASK_HAVE_MINUTE ) == 0 )
243 )
244 {
245 sprintf ( err,"bufr2tac: %s(): lack of mandatory descriptor in sequence", __func__ );
246 return 1;
247 }
248
249 // copy WIGOS ID
250 memcpy(&m->g.wid, &m->synop.wid, sizeof (struct wigos_id) );
251
252 if ( strcmp ( s->type_report, "AAXX" ) == 0 && ( syn->s0.II[0] == 0 || syn->s0.iii[0] == 0 ) )
253 {
255 ( syn->wid.issuer != 0 || syn->wid.issue != 0 ) &&
256 syn->wid.local_id[0] )
257 {
258 strcpy ( syn->s0.II, "00" );
259 strcpy ( syn->s0.iii, "000" );
260 }
261 else
262 {
263 sprintf ( err,"bufr2tac: %s(): lack of mandatory index station for AAXX report", __func__ );
264 return 1;
265 }
266 }
267
268
269 /****** Second pass. Global results and consistence analysis ************/
270 // set ir
271 if ( syn->s1.RRR[0] == 0 && syn->s3.RRR[0] == 0 && syn->s3.RRRR24[0] == 0 )
272 {
273 // no prec data case
274 syn->s1.ir[0] = '4';
275 }
276 else if ( syn->s1.RRR[0] == 0 && syn->s3.RRR[0] != 0 )
277 {
278 syn->s1.ir[0] = '2';
279 }
280 else if ( syn->s1.RRR[0] != 0 && syn->s3.RRR[0] == 0 )
281 {
282 syn->s1.ir[0] = '1';
283 }
284 else
285 {
286 syn->s1.ir[0] = '0';
287 }
288
289 // Supress 7wwW1W2 if no significant weather
290 if ( ( syn->s1.ww[0] || syn->s1.W1[0] || syn->s1.W2[0] ) &&
291 ( syn->s1.ww[0] == 0 || syn->s1.ww[0] == '/' || ( strcmp ( syn->s1.ww,"04" ) < 0 ) ) &&
292 ( syn->s1.W1[0] == 0 || syn->s1.W1[0] == '/' || ( strcmp ( syn->s1.W1,"3" ) < 0 ) ) &&
293 ( syn->s1.W2[0] == 0 || syn->s1.W2[0] == '/' || ( strcmp ( syn->s1.W2,"3" ) < 0 ) ) )
294 {
295 syn->s1.ww[0] = 0;
296 syn->s1.W1[0] = 0;
297 syn->s1.W2[0] = 0;
299 if ( syn->s1.ix[0] == '1' )
300 {
301 syn->s1.ix[0] = '2';
302 }
303 }
304
305 // adjust iw
306 if ( syn->s0.iw[0] == '/' && syn->s1.ff[0] != '/' )
307 {
308 syn->s0.iw[0] = '1';
309 }
310
311 // adjust ix
312 if ( syn->s1.ix[0] == '/' /*&& syn->s1.ww[0] == 0*/ )
313 {
317 )
318 {
320 {
321 if ( s->type == 1 || s->type == 2 )
322 {
323 strcpy ( syn->s1.ix,"2" );
324 }
325 else if ( s->type == 0 )
326 {
327 strcpy ( syn->s1.ix,"5" );
328 }
329 }
330 else
331 {
332 strcpy ( syn->s1.ix,"6" ); //NOTE: here we assume an automatic station without W data
333 }
334 }
335 else if ( s->mask & SUBSET_MASK_HAVE_TYPE_STATION )
336 {
337 if ( s->type == 1 )
338 {
339 strcpy ( syn->s1.ix,"3" );
340 }
341 else if ( s->type == 0 )
342 {
343 strcpy ( syn->s1.ix,"6" );
344 }
345 }
346 else
347 {
348 strcpy ( syn->s1.ix,"6" ); //NOTE: here we assume an automatic station without W data
349 }
350 }
351
352 // adjust radiation
353 if ( ( syn->mask & SYNOP_SEC3 ) && ( syn->s3.SS[0] == '\0' ) &&
354 ( syn->s3.j5[0][0] || syn->s3.j5[1][0] ||
355 syn->s3.j5[2][0] || syn->s3.j5[3][0] ||
356 syn->s3.j5[4][0] || syn->s3.j5[5][0] ||
357 syn->s3.j5[6][0] ) )
358 {
359 sprintf ( syn->s3.SS, "//" );
360 }
361
362 if ( ( syn->mask & SYNOP_SEC3 ) && ( syn->s3.SSS[0] == '\0' ) &&
363 ( syn->s3.j524[0][0] || syn->s3.j524[1][0] ||
364 syn->s3.j524[2][0] || syn->s3.j524[3][0] ||
365 syn->s3.j524[4][0] || syn->s3.j524[5][0] ||
366 syn->s3.j524[6][0] ) )
367 {
368 sprintf ( syn->s3.SSS, "///" );
369 }
370
371 /****** Final Adjust ***********/
372
373 // fix YYGG according with YYYYMMDDHHmm
374 if ( syn->e.mm[0] == 0 )
375 sprintf ( syn->e.mm, "00" );
377 if ( strcmp ( syn->e.mm,"00" ) )
378 {
379 strcpy ( syn->s1.GG, syn->e.HH );
380 strcpy ( syn->s1.gg, syn->e.mm );
381 }
382 syn->mask |= SYNOP_EXT;
383
384 // Marc as a synop from bufr
385 syn->mask |= SYNOP_BUFR;
386
387 // Fill some metreport fields
388 if ( strlen ( syn->s0.II ) )
389 {
390 strcpy ( m->g.index, syn->s0.II );
391 strcat ( m->g.index, syn->s0.iii );
392 }
393 else if ( strlen ( syn->s0.D_D ) )
394 {
395 strcpy ( m->g.index, syn->s0.D_D );
396 }
397 else if ( strlen ( syn->s0.IIIII ) )
398 {
399 strcpy ( m->g.index, syn->s0.IIIII );
400 }
401
403 {
404 m->g.lat = s->lat;
405 }
407 {
408 m->g.lon = s->lon;
409 }
411 {
412 m->g.alt = s->alt;
413 }
414 if ( s->mask & SUBSET_MASK_HAVE_NAME )
415 {
416 strcpy ( m->g.name, s->name );
417 }
419 {
420 strcpy ( m->g.country, s->country );
421 }
422
423 sprintf ( aux,"%s%s%s%s%s", syn->e.YYYY, syn->e.MM, syn->e.DD, syn->e.HH, syn->e.mm );
424 YYYYMMDDHHmm_to_met_datetime ( &m->t, aux );
425
426 if ( check_date_from_future ( m ) )
427 {
428 return 1; // Bad date/time . Is a report from future!
429 }
430
431 // If finally we arrive here, It succeded
432 return 0;
433}
434
Include header file for binary bufr2tac.
void bufr2tac_clean_synop_chunks(struct synop_chunks *s)
#define SUBSET_MASK_HAVE_MONTH
Bit mask to mark a struct bufr_subset_sequence_data having observation month.
Definition: bufr2tac.h:146
int check_date_from_future(struct metreport *m)
Check a estructure metreport not from future.
#define SUBSET_MASK_HAVE_COUNTRY
Bit mask to mark a struct bufr_subset_sequence_data having country name.
Definition: bufr2tac.h:134
int syn_parse_x04(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 04.
Definition: bufr2tac_x04.c:110
int syn_parse_x31(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 31.
Definition: bufr2tac_x31.c:35
int syn_parse_x11(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 11.
Definition: bufr2tac_x11.c:116
#define SUBSET_MASK_HAVE_NO_SIGNIFICANT_WW
Bit mask to mark a struct bufr_subset_sequence_data without WW information.
Definition: bufr2tac.h:92
int syn_parse_x13(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 13.
Definition: bufr2tac_x13.c:201
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)
#define SUBSET_MASK_HAVE_MINUTE
Bit mask to mark a struct bufr_subset_sequence_data having observation minute.
Definition: bufr2tac.h:164
#define SUBSET_MASK_HAVE_NAME
Bit mask to mark a struct bufr_subset_sequence_data having station name.
Definition: bufr2tac.h:128
#define bufr_subset_sequence_data
To use bufrdeco library with legacy old code using ECMWF library which is not used currently.
Definition: bufr2tac.h:220
int syn_parse_x06(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 06.
Definition: bufr2tac_x06.c:67
int syn_parse_x02(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 02.
Definition: bufr2tac_x02.c:34
#define SUBSET_MASK_HAVE_TYPE_STATION
Bit mask to mark a struct bufr_subset_sequence_data having type station information.
Definition: bufr2tac.h:86
int syn_parse_x20(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 20.
Definition: bufr2tac_x20.c:298
#define SUBSET_MASK_HAVE_ALTITUDE
Bit mask to mark a struct bufr_subset_sequence_data having altitude.
Definition: bufr2tac.h:122
int syn_parse_x01(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 01.
Definition: bufr2tac_x01.c:54
int syn_parse_x12(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 12.
Definition: bufr2tac_x12.c:220
int syn_parse_x10(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 10.
Definition: bufr2tac_x10.c:87
int syn_parse_x08(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 08.
Definition: bufr2tac_x08.c:37
int syn_parse_x14(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 14.
Definition: bufr2tac_x14.c:59
#define SUBSET_MASK_HAVE_WIGOS_ID
Bit mask to mark if a subset has a WIGOS ID.
Definition: bufr2tac.h:188
int syn_parse_x22(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 01.
Definition: bufr2tac_x22.c:35
#define SUBSET_MASK_HAVE_YEAR
Bit mask to mark a struct bufr_subset_sequence_data having observation year.
Definition: bufr2tac.h:140
int YYYYMMDDHHmm_to_met_datetime(struct met_datetime *t, const char *source)
Parse the string YYYYMMDDHHmm[ss] and set a struct met_datetime.
#define SUBSET_MASK_HAVE_LONGITUDE
Bit mask to mark a struct bufr_subset_sequence_data having longitude.
Definition: bufr2tac.h:116
int syn_parse_x05(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 05.
Definition: bufr2tac_x05.c:66
#define SUBSET_MASK_HAVE_LATITUDE
Bit mask to mark a struct bufr_subset_sequence_data having latitude.
Definition: bufr2tac.h:110
#define SUBSET_MASK_HAVE_NO_SIGNIFICANT_W1
Bit mask to mark a struct bufr_subset_sequence_data without W1 information.
Definition: bufr2tac.h:98
#define SUBSET_MASK_HAVE_DAY
Bit mask to mark a struct bufr_subset_sequence_data having observation day in a month.
Definition: bufr2tac.h:152
#define SUBSET_MASK_HAVE_NO_SIGNIFICANT_W2
Bit mask to mark a struct bufr_subset_sequence_data without W1 information.
Definition: bufr2tac.h:104
int syn_parse_x07(struct synop_chunks *syn, struct bufr2tac_subset_state *s)
Parse a expanded descriptor with X = 07.
Definition: bufr2tac_x07.c:65
#define SUBSET_MASK_HAVE_HOUR
Bit mask to mark a struct bufr_subset_sequence_data having observation hour.
Definition: bufr2tac.h:158
int parse_subset_as_synop(struct metreport *m, struct bufr2tac_subset_state *s, struct bufr_subset_sequence_data *sq, char *err)
parses a subset sequence as an Land fixed SYNOP FM-12, SHIP FM-13 or SYNOP-mobil FM-14 report
char * guess_WMO_region_synop(struct synop_chunks *syn)
Try to find WMO region if it is not already set and WMO Block and number index are known.
int synop_YYYYMMDDHHmm_to_YYGG(struct synop_chunks *syn)
Sets YYGG from YYYYMMDDHHmm extended group.
#define SYNOP_SEC3
mask bit meaning section 3 or synop is solicited to or parsed with success
Definition: metsynop.h:49
#define SYNOP_EXT
mask bit meaning date extension is parsed with success
Definition: metsynop.h:64
#define SYNOP_BUFR
mask bit meaning date synop is decoded from a BUFR
Definition: metsynop.h:74
stores information needed to parse a sequential list of expanded descriptors for a subset
Definition: bufr2tac.h:246
struct bufr_atom_data * a1
Definition: bufr2tac.h:250
struct bufr_atom_data * a
Definition: bufr2tac.h:249
char type_report[16]
Definition: bufr2tac.h:247
double lat
Definition: bufr2tac.h:299
double lon
Definition: bufr2tac.h:300
double alt
Definition: bufr2tac.h:301
struct wigos_id wid
Definition: bufr2tac.h:295
char index[16]
Definition: bufr2tac.h:296
char name[80]
Definition: bufr2tac.h:297
char country[80]
Definition: bufr2tac.h:298
all the information for a meteorological report in WMO text format from a BUFR file
Definition: bufr2tac.h:309
struct synop_chunks synop
Definition: bufr2tac.h:316
char type[8]
Definition: bufr2tac.h:320
struct met_datetime t
Definition: bufr2tac.h:314
struct met_geo g
Definition: bufr2tac.h:315
char mm[4]
Definition: metcommon.h:37
char HH[4]
Definition: metcommon.h:36
char DD[4]
Definition: metcommon.h:35
char MM[4]
Definition: metcommon.h:34
char YYYY[6]
Definition: metcommon.h:33
contains all possible substrings from a synop report is parsed with success
Definition: metsynop.h:293
struct synop_sec1 s1
Definition: metsynop.h:298
struct synop_sec3 s3
Definition: metsynop.h:300
struct wigos_id wid
Definition: metsynop.h:296
struct report_date_ext e
Definition: metsynop.h:295
struct synop_sec0 s0
Definition: metsynop.h:297
char D_D[10]
Definition: metsynop.h:97
char iii[4]
Definition: metsynop.h:102
char iw[2]
Definition: metsynop.h:100
char Reg[4]
Definition: metsynop.h:103
char II[4]
Definition: metsynop.h:101
char MiMi[4]
Definition: metsynop.h:92
char A1[2]
Definition: metsynop.h:94
char MjMj[4]
Definition: metsynop.h:93
char GG[4]
Definition: metsynop.h:99
char YY[4]
Definition: metsynop.h:98
char IIIII[10]
Definition: metsynop.h:104
char ix[2]
Definition: metsynop.h:124
char ff[4]
Definition: metsynop.h:129
char ir[2]
Definition: metsynop.h:123
char GG[4]
Definition: metsynop.h:152
char ww[4]
Definition: metsynop.h:144
char gg[4]
Definition: metsynop.h:153
char RRR[4]
Definition: metsynop.h:142
char W1[2]
Definition: metsynop.h:146
char W2[2]
Definition: metsynop.h:147
char RRRR24[6]
Definition: metsynop.h:257
char SSS[4]
Definition: metsynop.h:237
char j5[7][2]
Definition: metsynop.h:243
char RRR[4]
Definition: metsynop.h:255
char SS[4]
Definition: metsynop.h:238
char j524[7][2]
Definition: metsynop.h:245
WIGOS station identifier.
Definition: metcommon.h:46
uint16_t issue
Definition: metcommon.h:49
uint16_t issuer
Definition: metcommon.h:48
char local_id[24]
Definition: metcommon.h:50