1 | 1 | simandl | /* |
2 | 2 | simandl | * crusader100_read_rss |
3 | 1 | simandl | * |
4 | 2 | simandl | * compile: gcc -Wall -D_DEBUG crusader100_read_rss.c -o crusader100_read_rss |
5 | | | * |
6 | 1 | simandl | * Licence: GNU GPL ver.2 |
7 | | | * |
8 | | | * Changelog: |
9 | | | * 2007-01-27/Libor oprava cteni RSS<100, tj. dvoucifernych |
10 | 2 | simandl | * 2008-05-23/Libor zacatek prace na podpore Crusader Aggregator 100M |
11 | | | * 2008-06-07/Libor prvni verze se zakladni funkcnosti |
12 | | | * 2008-07-10/Libor cte krome hodnot registru vsechny veliciny |
13 | | | * 2008-07-13/Libor oprava neinicializovane promenne pro soucet RSS |
14 | 1 | simandl | * |
15 | | | */ |
16 | | | |
17 | | | |
18 | 2 | simandl | #include <assert.h> |
19 | 1 | simandl | #include <stdio.h> /* Standard input/output definitions */ |
20 | | | #include <sys/types.h> |
21 | | | #include <sys/stat.h> |
22 | | | #include <fcntl.h> /* File control definitions */ |
23 | 2 | simandl | #include <termios.h> |
24 | 1 | simandl | #include <unistd.h> /* UNIX standard function definitions */ |
25 | | | #include <stdlib.h> |
26 | | | #include <limits.h> /* INT_MAX and others */ |
27 | 2 | simandl | #include <string.h> |
28 | | | #include <errno.h> |
29 | | | #include <assert.h> |
30 | | | #include <ctype.h> /* isdigit() a.s.o. */ |
31 | | | #include <time.h> |
32 | 1 | simandl | |
33 | | | |
34 | | | static char *jmeno_seriaku = ""; |
35 | | | static time_t cilovy_cas = 0; |
36 | | | static time_t cas_startu = 0; |
37 | | | |
38 | 2 | simandl | /* baudrate settings are defined in <asm/termbits.h>, which is |
39 | | | included by <termios.h> */ |
40 | | | #define BAUDRATE B38400 |
41 | | | /* change this definition for the correct port */ |
42 | | | //#define MODEMDEVICE "/dev/ttyS1" |
43 | | | //#define MODEMDEVICE "crusader.log" |
44 | | | #define _POSIX_SOURCE 1 /* POSIX compliant source */ |
45 | | | |
46 | | | #define FALSE 0 |
47 | | | #define TRUE 1 |
48 | | | |
49 | | | #ifdef _DEBUG |
50 | | | # define DEBUG(level, fmt, args...) fprintf(stderr, fmt, ## args) |
51 | | | # define DBG(fmt, args...) DEBUG(L_DBG, "DEBUG: " fmt, ## args) |
52 | | | #else |
53 | | | # define DEBUG(level, fmt, args...) |
54 | | | # define DBG(fmt, args...) |
55 | | | #endif |
56 | | | |
57 | | | #define L_ALERT -3 |
58 | | | #define L_CRIT -2 |
59 | | | #define L_ERR -1 |
60 | | | #define L_DEFAULT 0 |
61 | | | #define L_WARN 1 |
62 | | | #define L_NOTICE 2 |
63 | | | #define L_INFO 3 |
64 | | | #define L_DBG 4 |
65 | | | |
66 | | | int otevri_seriak(char *devname) |
67 | | | { |
68 | | | int fd; |
69 | | | /* |
70 | | | Open modem device for reading and writing and not as controlling tty |
71 | | | because we don't want to get killed if linenoise sends CTRL-C. |
72 | | | */ |
73 | | | fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY); |
74 | | | if (fd < 0) { perror(devname); } |
75 | | | return fd; |
76 | | | } |
77 | | | |
78 | | | |
79 | | | int nastav_seriak(int fd, struct termios *oldtio) |
80 | | | { |
81 | | | struct termios newtio; |
82 | | | |
83 | | | tcgetattr(fd, oldtio); /* save current serial port settings */ |
84 | | | memset(&newtio, 0, sizeof(newtio)); /* clear struct for new port settings */ |
85 | | | |
86 | | | /* |
87 | | | BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed. |
88 | | | CRTSCTS : output hardware flow control (only used if the cable has |
89 | | | all necessary lines. See sect. 7 of Serial-HOWTO) |
90 | | | CS8 : 8n1 (8bit,no parity,1 stopbit) |
91 | | | CLOCAL : local connection, no modem contol |
92 | | | CREAD : enable receiving characters |
93 | | | */ |
94 | | | newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD; |
95 | | | |
96 | | | /* |
97 | | | IGNPAR : ignore bytes with parity errors |
98 | | | ICRNL : map CR to NL (otherwise a CR input on the other computer |
99 | | | will not terminate input) |
100 | | | otherwise make device raw (no other input processing) |
101 | | | */ |
102 | | | newtio.c_iflag = IGNPAR | ICRNL; |
103 | | | |
104 | | | /* |
105 | | | Raw output. |
106 | | | */ |
107 | | | newtio.c_oflag = 0; |
108 | | | |
109 | | | /* |
110 | | | ICANON : enable canonical input |
111 | | | disable all echo functionality, and don't send signals to calling program |
112 | | | */ |
113 | | | newtio.c_lflag = ICANON; |
114 | | | |
115 | | | /* |
116 | | | initialize all control characters |
117 | | | default values can be found in /usr/include/termios.h, and are given |
118 | | | in the comments, but we don't need them here |
119 | | | */ |
120 | | | newtio.c_cc[VINTR] = 0; /* Ctrl-c */ |
121 | | | newtio.c_cc[VQUIT] = 0; /* Ctrl-\ */ |
122 | | | newtio.c_cc[VERASE] = 0; /* del */ |
123 | | | newtio.c_cc[VKILL] = 0; /* @ */ |
124 | | | newtio.c_cc[VEOF] = 4; /* Ctrl-d */ |
125 | | | newtio.c_cc[VTIME] = 0; /* inter-character timer unused */ |
126 | | | newtio.c_cc[VMIN] = 1; /* blocking read until 1 character arrives */ |
127 | | | newtio.c_cc[VSWTC] = 0; /* '\0' */ |
128 | | | newtio.c_cc[VSTART] = 0; /* Ctrl-q */ |
129 | | | newtio.c_cc[VSTOP] = 0; /* Ctrl-s */ |
130 | | | newtio.c_cc[VSUSP] = 0; /* Ctrl-z */ |
131 | | | newtio.c_cc[VEOL] = 0; /* '\0' */ |
132 | | | newtio.c_cc[VREPRINT] = 0; /* Ctrl-r */ |
133 | | | newtio.c_cc[VDISCARD] = 0; /* Ctrl-u */ |
134 | | | newtio.c_cc[VWERASE] = 0; /* Ctrl-w */ |
135 | | | newtio.c_cc[VLNEXT] = 0; /* Ctrl-v */ |
136 | | | newtio.c_cc[VEOL2] = 0; /* '\0' */ |
137 | | | |
138 | | | /* |
139 | | | now clean the modem line and activate the settings for the port |
140 | | | */ |
141 | | | tcflush(fd, TCIFLUSH); |
142 | | | tcsetattr(fd,TCSANOW, &newtio); |
143 | | | |
144 | | | return 0; |
145 | | | } |
146 | | | |
147 | | | int restore_seriak(int fd, struct termios *stored_tio) |
148 | | | { |
149 | | | /* restore the old port settings */ |
150 | | | tcsetattr(fd, TCSANOW, stored_tio); |
151 | | | return 0; |
152 | | | } |
153 | | | |
154 | 1 | simandl | void print_usage() |
155 | | | { |
156 | 2 | simandl | printf("\nusage: seriak <jmeno seriaku> {<cilovy cas> | +<offset>}\n\n"); |
157 | 1 | simandl | } |
158 | | | |
159 | | | void check_params( int argc, char *argv[]) |
160 | | | { |
161 | | | int relative = 0; |
162 | | | char *nptr = NULL, *endptr = NULL; |
163 | | | |
164 | | | if ( argc != 3 || (argc == 3 && ( strcmp("-h", argv[1])==0 || strcmp("--help", argv[1])==0 )) ) { |
165 | | | print_usage(); |
166 | | | exit(EXIT_FAILURE); |
167 | | | } |
168 | | | jmeno_seriaku = argv[1]; |
169 | | | |
170 | | | nptr = argv[2]; |
171 | | | if ( argv[2][0] == '+' ) { /* relativni cas */ |
172 | | | if ( strlen(argv[2]) < 1 ) { |
173 | | | print_usage(); |
174 | | | exit(EXIT_FAILURE); |
175 | | | } |
176 | | | nptr++; |
177 | | | relative = 1; |
178 | | | } |
179 | | | cilovy_cas = strtol(argv[2], &endptr, 10); |
180 | | | |
181 | | | #ifdef _DEBUG |
182 | | | fprintf (stderr, "arg[2]: %s, endptr: %p, cilovy_cas: %ld\n", argv[2], endptr, cilovy_cas); |
183 | | | #endif |
184 | | | |
185 | | | if ( !(argv[2] != '\0' && *endptr == '\0') ) |
186 | | | { |
187 | | | fprintf(stderr, "ERROR: spatny tvar ciloveho casu"); |
188 | | | print_usage(); |
189 | | | exit(EXIT_FAILURE); |
190 | | | } |
191 | | | |
192 | | | if (relative) { |
193 | | | cilovy_cas += cas_startu; |
194 | | | } |
195 | | | } |
196 | | | |
197 | 2 | simandl | /** |
198 | | | * Hleda zda se v prijimacim bufferu buff naleza ocekavany retezec exp_res. |
199 | | | * @param buf pointer na prijimaci buffer |
200 | | | * @param buflen delka prijimaciho bufferu |
201 | | | * @param exp_res ocekavany vysledek, ktery hledame ve vstupnim bufferu |
202 | | | * @return 0 kdyz je to OK, jinak 1. |
203 | | | * |
204 | | | */ |
205 | | | int check_response(char *buf, int buflen, char *exp_res) |
206 | | | { |
207 | | | return 0; |
208 | | | } |
209 | | | |
210 | | | /** |
211 | | | * vypise na stderr obsah daneho bufferu jako text i jako hexakody. |
212 | | | * misto tisknutelnych znaku se vypisuje tecka |
213 | | | * @param buf ukazatel na buffer |
214 | | | * @param bufsize velikost bufferu |
215 | | | * @param pocet pocet bajtu, ktere se maji vypsat |
216 | | | */ |
217 | | | void print_debug_buffer(char *buf, size_t bufsize, size_t pocet) |
218 | | | { |
219 | | | time_t cas; |
220 | | | int i; |
221 | | | |
222 | | | assert(bufsize >= 0); |
223 | | | assert(buf != NULL); |
224 | | | |
225 | | | DBG("print_debug_buffer(bufsize=%d, pocet=%d)\n", bufsize, pocet); |
226 | | | cas = time(0); |
227 | | | if (pocet > bufsize) { |
228 | | | fprintf(stderr, "prilis maly buffer, snizuji pocet = bufsize\n"); |
229 | | | pocet = bufsize; |
230 | | | } |
231 | | | |
232 | | | fprintf(stderr, "DEBUG: cas: %ld, buf: '", cas); |
233 | | | for ( i = 0; i < pocet; ++i ) |
234 | | | { |
235 | | | if (buf[i] >= ' ') { |
236 | | | fprintf(stderr, "%c", buf[i]); |
237 | | | } else { |
238 | | | fprintf(stderr, "."); |
239 | | | } |
240 | | | } |
241 | | | fprintf(stderr, "' hex: "); |
242 | | | for ( i = 0; i < pocet; ++i ) { |
243 | | | fprintf(stderr, "%02x ", buf[i]); |
244 | | | } |
245 | | | fprintf(stderr, "\n"); |
246 | | | } |
247 | | | |
248 | | | // TODO check HUGE_VAL, ERANGE, see strtod(3) |
249 | | | int get_double(char *str, int len, double *value) |
250 | | | { |
251 | | | double v; |
252 | | | char *eptr; |
253 | | | |
254 | | | DBG("get_double(str='%.*s', len=%d)\n", len, str, len); |
255 | | | eptr = NULL; |
256 | | | v = strtod(str, &eptr); |
257 | | | if (*eptr == '\0') { |
258 | | | DBG("get_double: value = %6.2f\n", v); |
259 | | | *value = v; |
260 | | | return 0; |
261 | | | } |
262 | | | else { |
263 | | | DBG("get_double: error in conversion\n"); |
264 | | | *value = 0; |
265 | | | return -1; |
266 | | | } |
267 | | | } |
268 | | | int get_long(char *str, int len, long *value) |
269 | | | { |
270 | | | long v; |
271 | | | char *eptr; |
272 | | | |
273 | | | DBG("get_long(str='%.*s', len=%d)\n", len, str, len); |
274 | | | eptr = NULL; |
275 | | | v = strtol(str, &eptr, 10); |
276 | | | if (*eptr == '\0') { |
277 | | | DBG("get_long: value = %ld\n", v); |
278 | | | *value = v; |
279 | | | return 0; |
280 | | | } |
281 | | | else { |
282 | | | DBG("get_long: error in conversion\n"); |
283 | | | *value = 0; |
284 | | | return -1; |
285 | | | } |
286 | | | } |
287 | | | |
288 | | | #define CRS_NAMERENO_RSS 1 << 0 |
289 | | | #define CRS_NAMERENO_P_LSR 1 << 1 |
290 | | | #define CRS_NAMERENO_I_BIAS 1 << 2 |
291 | | | #define CRS_NAMERENO_U_APD 1 << 3 |
292 | | | #define CRS_NAMERENO_T_APD 1 << 4 |
293 | | | #define CRS_NAMERENO_T_CPU 1 << 5 |
294 | | | #define CRS_NAMERENO_L 1 << 6 |
295 | | | #define CRS_NAMERENO_HEAT 1 << 7 |
296 | | | |
297 | | | typedef enum { |
298 | | | RSS_MIN, |
299 | | | RSS_MAX, |
300 | | | RSS_SUM, |
301 | | | RSS_CNT, |
302 | | | RSS_LAST |
303 | | | } rss_names_t; |
304 | | | |
305 | | | /** |
306 | | | * Struktura obsahujici prectene udaje. Pokud byl behem merici periody nektery udaj precten vicekrat, |
307 | | | * obsahuje naposledy prectenou hodnotu. To se netyka RSS (Received Signal Strength), kde se uchovava |
308 | | | * ctene minimum, maximim, soucet a pocet ctenych hodnot. Ze souctu se pak pocita prumerna hodnota. |
309 | | | * |
310 | | | */ |
311 | | | typedef struct { |
312 | | | int namereno; /// bitove pole obsahujici informaci o tom, ktere hodnoty jsou skutecne zmerene |
313 | | | long rss[RSS_LAST]; /// bez prefixu |
314 | | | double laser_power; /// Pl [mW], vykon laseru |
315 | | | double laser_bias; /// Ib [mA], bias proud laserem |
316 | | | double apd_voltage; /// Ua [V] |
317 | | | double apd_temp; /// Ta [C] |
318 | | | double apd_ureg; /// Ur bezrozmerne, hodnota registru menice APD |
319 | | | double cpu_temp; /// T [C] |
320 | | | int da_reg[2]; /// L bezrozmerne, hodnoty registru D/A prevodniku |
321 | | | } crusader_meas_t; |
322 | | | |
323 | | | void clear_value(char* varr, size_t va_size) |
324 | | | { |
325 | | | memset(varr, 0, va_size); |
326 | | | } |
327 | | | |
328 | | | #define KONECNY_STAV 0x1000 |
329 | | | |
330 | 1 | simandl | /* |
331 | 2 | simandl | * Stavy prijimaciho automatu |
332 | 1 | simandl | */ |
333 | 2 | simandl | typedef enum { |
334 | | | ST_START, /// pocatecni stav automatu, zacina parsovani radky, obvykle po ST_NL nebo kdyz se ocekavaji dalsi hodnoty na radce |
335 | | | ST_NL, /// '\n' new line, synchronizuje automat, prechoazi do ST_START |
336 | | | ST_KOMENTAR, /// NL -> '!', oznacuje komentar do dalsiho NL. Komentar '!OK' ma specialni vyznam |
337 | | | ST_PLUS, |
338 | | | ST_RSS, /// NL -> ' ', zacina cteni RSS, akceptuje cislice 0-9, jiny znak trigruje prechod do ST_KOMENTAR, |
339 | | | /// tj. ignorujeme RSS protistrany a bargraf |
340 | | | ST_U, |
341 | | | ST_U_A, |
342 | | | ST_U_APD, |
343 | | | ST_U_R, |
344 | | | ST_U_REG, |
345 | | | ST_T, |
346 | | | ST_T_A, |
347 | | | ST_T_APD, |
348 | | | ST_T_CPU, |
349 | | | ST_P, |
350 | | | ST_PL, |
351 | | | ST_PLASER, |
352 | | | ST_I, |
353 | | | ST_IB, |
354 | | | ST_IBIAS, |
355 | | | ST_H, |
356 | | | ST_L, |
357 | | | ST_L1, |
358 | | | ST_L2, |
359 | | | ST_ERROR = KONECNY_STAV | 500 |
360 | | | |
361 | | | } state_t; |
362 | | | |
363 | | | int sezer_seriak(int seriak) |
364 | 1 | simandl | { |
365 | 2 | simandl | ssize_t precteno; |
366 | | | time_t cas = 0; |
367 | | | int chyba; |
368 | | | static char buf[129]; |
369 | | | static size_t bufsize = sizeof(buf); |
370 | | | int i = 0; |
371 | | | char *p; |
372 | 1 | simandl | |
373 | 2 | simandl | DBG("sezer_seriak(fd=%d)\n", seriak); |
374 | | | precteno = read(seriak, buf, bufsize-1); |
375 | | | DBG("sezer_seriak: precteno = %d\n", precteno); |
376 | | | DBG("sezer_seriak: cas = %lu, cilovy_cas = %lu\n", cas, cilovy_cas); |
377 | | | while (precteno && cas < cilovy_cas) { |
378 | | | i++; |
379 | | | cas = time(0); |
380 | | | DBG("sezer_seriak: i=%2d precteno = %d\n", i, precteno); |
381 | | | DBG("sezer_seriak: i=%2d cas = %lu, cilovy_cas = %lu\n", i, cas, cilovy_cas); |
382 | | | if (precteno < 0) { |
383 | | | DBG("if (precteno < 0)...\n"); |
384 | | | chyba = errno; |
385 | | | if (chyba == EAGAIN) { |
386 | | | fprintf(stderr, "continuing...\n"); |
387 | | | sleep(1); |
388 | | | goto loop_end; |
389 | | | } |
390 | | | perror("chyba cteni: "); |
391 | | | fprintf(stderr, "chyba = %d\n", chyba); |
392 | | | fprintf(stderr, "EAGAIN = %d\n", EAGAIN); |
393 | | | goto err; |
394 | | | } |
395 | | | if (precteno > 0) { |
396 | | | for (p = buf; p < buf+precteno; p++) { |
397 | | | if (*p == '+') goto end; |
398 | | | } |
399 | | | } |
400 | | | #ifdef _DEBUG |
401 | | | print_debug_buffer(buf, bufsize, precteno); |
402 | | | #endif |
403 | | | loop_end: |
404 | | | precteno = read(seriak, buf, bufsize-1); |
405 | | | } |
406 | | | end: |
407 | | | DBG("sezer_seriak(), done\n"); |
408 | | | return 0; |
409 | | | err: |
410 | | | DBG("sezer_seriak(), fail\n"); |
411 | | | return -1; |
412 | 1 | simandl | } |
413 | | | |
414 | | | int main(int argc, char *argv[]) |
415 | | | { |
416 | 2 | simandl | struct termios old_tio; |
417 | | | int seriak = -1; |
418 | | | int chyba; |
419 | | | ssize_t precteno; |
420 | | | ssize_t ibuflen; |
421 | | | char buf[129]; |
422 | | | size_t bufsize = sizeof(buf); |
423 | | | time_t cas = 0; |
424 | | | char *p; |
425 | 1 | simandl | |
426 | 2 | simandl | crusader_meas_t mereni; |
427 | | | mereni.rss[RSS_MIN] = INT_MAX; |
428 | | | mereni.rss[RSS_MAX] = 0; |
429 | | | mereni.rss[RSS_CNT] = 0; |
430 | | | mereni.rss[RSS_SUM] = 0; |
431 | | | mereni.laser_power = 0; |
432 | | | mereni.laser_bias = 0; |
433 | | | mereni.apd_voltage = 0; |
434 | | | mereni.apd_temp = 0; |
435 | | | mereni.cpu_temp = 0; |
436 | | | long rss_avg; |
437 | | | |
438 | | | state_t state, next_state; |
439 | | | int vidx; /// index cislice hodnoty (value) |
440 | | | char val_arr[16]; |
441 | | | char state_text[128]; |
442 | | | int state_text_len; |
443 | | | int clear_state_text = 1; |
444 | | | long int long_val; |
445 | | | double double_val; |
446 | | | long long loopcnt = 0; |
447 | | | int posledni_kus = 0; |
448 | 1 | simandl | |
449 | 2 | simandl | cas_startu = time(0); |
450 | | | DEBUG(L_INFO, "Cas startu: %ld - %s", cas_startu, ctime(&cas_startu)); |
451 | 1 | simandl | |
452 | 2 | simandl | check_params(argc, argv); |
453 | 1 | simandl | |
454 | 2 | simandl | DEBUG(L_INFO, "Cilovy cas: %ld - %s", cilovy_cas, ctime(&cilovy_cas)); |
455 | | | |
456 | | | seriak = otevri_seriak(jmeno_seriaku); |
457 | | | if ( seriak == -1 ) |
458 | | | { |
459 | | | char msg[256]; |
460 | | | snprintf(msg, sizeof(msg)-1, "Nejde otevrit seriak (%s)", jmeno_seriaku); |
461 | | | msg[255] = '\0'; |
462 | | | perror(msg); |
463 | | | free(msg); |
464 | | | goto error1; |
465 | | | } |
466 | | | nastav_seriak(seriak, &old_tio); |
467 | | | DBG("MAIN: write 'Z'\n"); |
468 | | | write(seriak, "Z\r", 2); |
469 | | | sezer_seriak(seriak); |
470 | | | |
471 | | | DBG("MAIN: write 'E0'\n"); |
472 | | | write(seriak, "E0\r", 3); |
473 | | | sezer_seriak(seriak); |
474 | | | |
475 | | | write(seriak, "#1\r", 3); |
476 | | | |
477 | | | clear_value(val_arr, sizeof(val_arr)); |
478 | | | |
479 | | | state_text_len = 0; |
480 | | | memset(state_text, 0, sizeof(state_text)); |
481 | | | clear_state_text = 1; |
482 | | | for ( ; cas < cilovy_cas && posledni_kus == 0; cas = time(0) ) |
483 | | | { |
484 | | | precteno = read(seriak, buf, bufsize-1); /* one character less for terminating '\0' */ |
485 | | | if (precteno < 0) { |
486 | | | chyba = errno; |
487 | | | if (chyba == EAGAIN) { |
488 | | | DEBUG(L_INFO, "continuing...\n"); |
489 | | | sleep(1); |
490 | | | continue; |
491 | | | } |
492 | | | perror("chyba cteni: "); |
493 | | | fprintf(stderr, "chyba = %d\n", chyba); |
494 | | | fprintf(stderr, "EAGAIN = %d\n", EAGAIN); |
495 | | | goto error1; |
496 | | | } |
497 | | | |
498 | | | // pouze pri cteni souboru |
499 | | | // if (precteno != bufsize-1) |
500 | | | // posledni_kus = 1; |
501 | | | |
502 | 1 | simandl | #ifdef _DEBUG |
503 | 2 | simandl | fprintf(stderr, "Precteno: %d\n", precteno); |
504 | | | print_debug_buffer(buf, bufsize, precteno); |
505 | 1 | simandl | #endif |
506 | 2 | simandl | |
507 | | | ibuflen = precteno; |
508 | | | p = buf; |
509 | | | state = ST_START; /// zaciname s cistym stitem, tj. jakoby na novem radku |
510 | | | next_state = ST_ERROR; /// pokud se nic nestane, skoncime s chybou |
511 | | | while (ibuflen > 0) |
512 | | | { |
513 | | | loopcnt++; |
514 | | | assert(state_text_len >= 0); |
515 | | | assert(state_text_len < sizeof(state_text)); |
516 | | | |
517 | | | state_text[state_text_len] = *p; |
518 | | | state_text_len++; |
519 | | | |
520 | | | switch (state) { |
521 | | | case ST_START: |
522 | | | DBG("ST_START\n"); |
523 | | | case ST_NL: |
524 | | | DBG("ST_NL\n"); |
525 | | | vidx = 0; |
526 | | | switch (*p) { |
527 | | | case '!': |
528 | | | next_state = ST_KOMENTAR; |
529 | | | break; |
530 | | | case '+': |
531 | | | next_state = ST_PLUS; |
532 | | | break; |
533 | | | case 0x0a: |
534 | | | next_state = ST_NL; |
535 | | | break; |
536 | | | default: |
537 | | | next_state = ST_ERROR; |
538 | | | } |
539 | | | break; |
540 | | | case ST_ERROR: |
541 | | | DBG("ST_ERROR\n"); |
542 | | | case ST_KOMENTAR: |
543 | | | DBG("ST_KOMENTAR\n"); |
544 | | | if (*p == 0x0a) |
545 | | | next_state = ST_NL; |
546 | | | else |
547 | | | next_state = ST_KOMENTAR; |
548 | | | break; |
549 | | | case ST_PLUS: |
550 | | | DBG("ST_PLUS\n"); |
551 | | | switch (*p) { |
552 | | | case ' ': |
553 | | | next_state = ST_RSS; |
554 | | | break;; |
555 | | | case 'U': |
556 | | | next_state = ST_U; |
557 | | | break; |
558 | | | case 'P': |
559 | | | next_state = ST_P; |
560 | | | break; |
561 | | | case 'T': |
562 | | | next_state = ST_T; |
563 | | | break; |
564 | | | case 'I': |
565 | | | next_state = ST_I; |
566 | | | break; |
567 | | | case 'L': |
568 | | | next_state = ST_L; |
569 | | | break; |
570 | | | case 'H': |
571 | | | next_state = ST_H; |
572 | | | break; |
573 | | | default: |
574 | | | next_state = ST_ERROR; |
575 | | | } |
576 | | | break; |
577 | | | case ST_RSS: |
578 | | | DBG("ST_RSS\n"); |
579 | | | // ignore spaces |
580 | | | if (*p == ' ' && state_text_len == 1) { |
581 | | | clear_state_text = 1; |
582 | | | break; |
583 | | | } |
584 | | | // do not read rss yet, wait for space, grr!!! |
585 | | | // TODO je potreba vyresit cteni RSS, ktera ma na obou stranach mezeru |
586 | | | // takze ji neni mozne jednoduse bezstavove parsovat |
587 | | | // resenim bude asi dat nove stavy RSSM, M jako mezera, |
588 | | | // RSSMC, C jako cifra a RSSMCM, M jako mezera. |
589 | | | // kdyz se precte druha mezera, prevede se state_text string na cislo |
590 | | | if (isdigit(*p)) break; |
591 | | | |
592 | | | DBG("ST_RSS: *p = '%c'\n", *p); |
593 | | | state_text[state_text_len-1] = '\0'; |
594 | | | if (get_long(state_text, state_text_len, &long_val) < 0) { |
595 | | | fprintf(stderr, "ERROR in conversion, exiting.\n"); |
596 | | | exit(1); |
597 | | | } |
598 | | | mereni.rss[RSS_SUM] += long_val; |
599 | | | mereni.rss[RSS_CNT]++; |
600 | | | if (long_val < mereni.rss[RSS_MIN]) mereni.rss[RSS_MIN] = long_val; |
601 | | | if (long_val > mereni.rss[RSS_MAX]) mereni.rss[RSS_MAX] = long_val; |
602 | | | DBG("RSS: cnt=%ld curr=%ld min=%ld max=%ld sum=%ld\n", mereni.rss[RSS_CNT], long_val, mereni.rss[RSS_MIN], mereni.rss[RSS_MAX], mereni.rss[RSS_SUM]); |
603 | | | next_state = ST_KOMENTAR; |
604 | | | break; |
605 | | | case ST_PLASER: |
606 | | | DBG("ST_PLASER\n"); |
607 | | | // ignore spaces |
608 | | | if (*p == ' ' && state_text_len == 1) { |
609 | | | clear_state_text = 1; |
610 | | | break; |
611 | | | } |
612 | | | // hodnota je float |
613 | | | // TODO kontrolovat pritomnost pouze jedne tecky |
614 | | | if (isdigit(*p) || *p == '.') break; |
615 | | | |
616 | | | DBG("ST_PLASER: *p = '%c'\n", *p); |
617 | | | state_text[state_text_len-1] = '\0'; |
618 | | | if (get_double(state_text, state_text_len, &double_val) < 0) { |
619 | | | fprintf(stderr, "ERROR in conversion, exiting.\n"); |
620 | | | exit(1); |
621 | | | } |
622 | | | mereni.laser_power = double_val; |
623 | | | // jednotky ignorujeme, stejne to jsou vzdy mW |
624 | | | next_state = ST_KOMENTAR; |
625 | | | break; |
626 | | | case ST_IBIAS: |
627 | | | DBG("ST_IBIAS\n"); |
628 | | | // ignore spaces |
629 | | | if (*p == ' ' && state_text_len == 1) { |
630 | | | clear_state_text = 1; |
631 | | | break; |
632 | | | } |
633 | | | // hodnota je float |
634 | | | // TODO kontrolovat pritomnost pouze jedne tecky |
635 | | | if (isdigit(*p) || *p == '.') break; |
636 | | | |
637 | | | DBG("ST_IBIAS: *p = '%c'\n", *p); |
638 | | | state_text[state_text_len-1] = '\0'; |
639 | | | if (get_double(state_text, state_text_len, &double_val) < 0) { |
640 | | | fprintf(stderr, "ERROR in conversion, exiting.\n"); |
641 | | | exit(1); |
642 | | | } |
643 | | | mereni.laser_bias = double_val; |
644 | | | // jednotky ignorujeme, stejne to jsou vzdy mA |
645 | | | next_state = ST_KOMENTAR; |
646 | | | break; |
647 | | | case ST_T_APD: |
648 | | | DBG("ST_T_APD\n"); |
649 | | | // ignore spaces |
650 | | | if (*p == ' ' && state_text_len == 1) { |
651 | | | clear_state_text = 1; |
652 | | | break; |
653 | | | } |
654 | | | // hodnota je float |
655 | | | if (isdigit(*p) || *p == '.') break; |
656 | | | |
657 | | | DBG("ST_T_APD: *p = '%c'\n", *p); |
658 | | | state_text[state_text_len-1] = '\0'; |
659 | | | if (get_double(state_text, state_text_len, &double_val) < 0) { |
660 | | | fprintf(stderr, "ERROR in conversion, exiting.\n"); |
661 | | | exit(1); |
662 | | | } |
663 | | | mereni.apd_temp = double_val; |
664 | | | // jednotky ignorujeme, stejne to jsou vzdy mA |
665 | | | next_state = ST_KOMENTAR; |
666 | | | break; |
667 | | | case ST_T_CPU: |
668 | | | DBG("ST_T_CPU\n"); |
669 | | | // ignore spaces |
670 | | | if (*p == ' ' && state_text_len == 1) { |
671 | | | clear_state_text = 1; |
672 | | | break; |
673 | | | } |
674 | | | // hodnota je float |
675 | | | if (isdigit(*p) || *p == '.') break; |
676 | | | |
677 | | | DBG("ST_T_CPU: *p = '%c'\n", *p); |
678 | | | state_text[state_text_len-1] = '\0'; |
679 | | | if (get_double(state_text, state_text_len, &double_val) < 0) { |
680 | | | fprintf(stderr, "ERROR in conversion, exiting.\n"); |
681 | | | exit(1); |
682 | | | } |
683 | | | mereni.cpu_temp = double_val; |
684 | | | // jednotky ignorujeme, stejne to jsou vzdy mA |
685 | | | next_state = ST_KOMENTAR; |
686 | | | break; |
687 | | | case ST_U_APD: |
688 | | | DBG("ST_U_APD\n"); |
689 | | | // ignore spaces |
690 | | | if (*p == ' ' && state_text_len == 1) { |
691 | | | clear_state_text = 1; |
692 | | | break; |
693 | | | } |
694 | | | // hodnota je float |
695 | | | if (isdigit(*p) || *p == '.') break; |
696 | | | |
697 | | | DBG("ST_U_APD: *p = '%c'\n", *p); |
698 | | | state_text[state_text_len-1] = '\0'; |
699 | | | if (get_double(state_text, state_text_len, &double_val) < 0) { |
700 | | | fprintf(stderr, "ERROR in conversion, exiting.\n"); |
701 | | | exit(1); |
702 | | | } |
703 | | | mereni.apd_voltage = double_val; |
704 | | | // jednotky ignorujeme, stejne to jsou vzdy mA |
705 | | | next_state = ST_KOMENTAR; |
706 | | | break; |
707 | | | case ST_U: |
708 | | | DBG("ST_U\n"); |
709 | | | switch (*p) { |
710 | | | case 'a': |
711 | | | next_state = ST_U_A; |
712 | | | break; |
713 | | | case 'r': |
714 | | | next_state = ST_U_R; |
715 | | | break; |
716 | | | default: |
717 | | | next_state = ST_ERROR; |
718 | | | } |
719 | | | break; |
720 | | | case ST_P: |
721 | | | DBG("ST_P\n"); |
722 | | | switch (*p) { |
723 | | | case 'l': |
724 | | | next_state = ST_PL; |
725 | | | break; |
726 | | | default: |
727 | | | next_state = ST_ERROR; |
728 | | | } |
729 | | | break; |
730 | | | case ST_PL: |
731 | | | DBG("ST_PL\n"); |
732 | | | switch (*p) { |
733 | | | case '=': |
734 | | | next_state = ST_PLASER; |
735 | | | break; |
736 | | | default: |
737 | | | next_state = ST_ERROR; |
738 | | | } |
739 | | | break; |
740 | | | case ST_T: |
741 | | | DBG("ST_T\n"); |
742 | | | switch (*p) { |
743 | | | case '=': |
744 | | | next_state = ST_T_CPU; |
745 | | | break; |
746 | | | case 'a': |
747 | | | next_state = ST_T_A; |
748 | | | break; |
749 | | | default: |
750 | | | next_state = ST_ERROR; |
751 | | | } |
752 | | | break; |
753 | | | case ST_T_A: |
754 | | | DBG("ST_T_TA\n"); |
755 | | | switch (*p) { |
756 | | | case '=': |
757 | | | next_state = ST_T_APD; |
758 | | | break; |
759 | | | default: |
760 | | | next_state = ST_ERROR; |
761 | | | } |
762 | | | break; |
763 | | | case ST_I: |
764 | | | DBG("ST_I\n"); |
765 | | | switch (*p) { |
766 | | | case 'b': |
767 | | | next_state = ST_IB; |
768 | | | break; |
769 | | | default: |
770 | | | next_state = ST_ERROR; |
771 | | | } |
772 | | | break; |
773 | | | case ST_IB: |
774 | | | DBG("ST_IB\n"); |
775 | | | switch (*p) { |
776 | | | case '=': |
777 | | | next_state = ST_IBIAS; |
778 | | | break; |
779 | | | default: |
780 | | | next_state = ST_ERROR; |
781 | | | } |
782 | | | break; |
783 | | | case ST_U_A: |
784 | | | DBG("ST_U_A\n"); |
785 | | | switch (*p) { |
786 | | | case '=': |
787 | | | next_state = ST_U_APD; |
788 | | | break; |
789 | | | default: |
790 | | | next_state = ST_ERROR; |
791 | | | } |
792 | | | break; |
793 | | | case ST_U_R: |
794 | | | DBG("ST_U_R\n"); |
795 | | | switch (*p) { |
796 | | | case '=': |
797 | | | next_state = ST_U_REG; |
798 | | | break; |
799 | | | default: |
800 | | | next_state = ST_ERROR; |
801 | | | } |
802 | | | break; |
803 | | | case ST_L: |
804 | | | DBG("ST_L\n"); |
805 | | | case ST_H: |
806 | | | DBG("ST_H\n"); |
807 | | | next_state = ST_KOMENTAR; |
808 | | | break; |
809 | | | default: |
810 | | | DBG("default\n"); |
811 | | | /* nyni H, L */ |
812 | | | next_state = ST_ERROR; |
813 | | | } |
814 | | | if (state != next_state || clear_state_text == 1) { |
815 | | | state_text_len = 0; |
816 | | | clear_state_text = 0; |
817 | | | } |
818 | | | state = next_state; |
819 | | | ibuflen--; |
820 | | | p++; |
821 | | | #ifdef _DEBUG |
822 | | | fprintf(stderr, "state_text: "); |
823 | | | print_debug_buffer(state_text, sizeof(state_text), state_text_len); |
824 | | | #endif |
825 | 1 | simandl | |
826 | | | } |
827 | 2 | simandl | loopcnt++; |
828 | 1 | simandl | } |
829 | 2 | simandl | // restore_seriak(seriak, &old_tio); |
830 | | | close(seriak); |
831 | 1 | simandl | |
832 | | | |
833 | 2 | simandl | rss_avg = mereni.rss[RSS_CNT]>0 ? mereni.rss[RSS_SUM]/mereni.rss[RSS_CNT] : -1; |
834 | 1 | simandl | |
835 | 2 | simandl | fprintf(stderr, "Number of received valid values: %ld\n", mereni.rss[RSS_CNT]); |
836 | | | fprintf(stderr, "Total sum of RSS: %ld\n", mereni.rss[RSS_SUM]); |
837 | | | fprintf(stderr, "Average RSS: %ld\n", rss_avg); |
838 | | | fprintf(stderr, "Maximum RSS: %ld\n", mereni.rss[RSS_MAX]); |
839 | | | fprintf(stderr, "Minimum RSS: %ld\n", mereni.rss[RSS_MIN]); |
840 | | | fprintf(stderr, "LASER power: %6.2f\n", mereni.laser_power); |
841 | | | fprintf(stderr, "LASER bias: %6.2f\n", mereni.laser_bias); |
842 | | | fprintf(stderr, "APD voltage: %6.2f\n", mereni.apd_voltage); |
843 | | | fprintf(stderr, "APD temp: %6.2f\n", mereni.apd_temp); |
844 | | | fprintf(stderr, "CPU temp: %6.2f\n", mereni.cpu_temp); |
845 | | | fprintf(stderr, "loops: %lld\n", loopcnt); |
846 | | | printf("%ld %ld %ld %ld %6.2f %6.2f %6.2f %6.2f %6.2f\n", mereni.rss[RSS_CNT], rss_avg, mereni.rss[RSS_MAX], mereni.rss[RSS_MIN], mereni.laser_power, mereni.laser_bias, mereni.apd_voltage, mereni.apd_temp, mereni.cpu_temp); |
847 | | | |
848 | | | return EXIT_SUCCESS; |
849 | | | |
850 | 1 | simandl | error1: |
851 | 2 | simandl | if (seriak >= 0) { |
852 | | | restore_seriak(seriak, &old_tio); |
853 | | | close(seriak); |
854 | | | } |
855 | | | return EXIT_FAILURE; |
856 | 1 | simandl | } |