Return to clock.awk CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / scripts / stats |
1.1 ! misho 1: # awk program to scan clockstat files and report errors/statistics ! 2: # ! 3: # usage: awk -f check.awk clockstats ! 4: # ! 5: # This program works for the following radios: ! 6: # PST/Traconex 1020 WWV reciever ! 7: # Arbiter 1088 GPS receiver ! 8: # Spectracom 8170/Netclock-2 WWVB receiver ! 9: # IRIG audio decoder ! 10: # Austron 2200A/2201A GPS receiver (see README.austron file) ! 11: # ! 12: BEGIN { ! 13: etf_min = osc_vmin = osc_tmin = 1e9 ! 14: etf_max = osc_vmax = osc_tmax = -1e9 ! 15: } ! 16: # ! 17: # scan all records in file ! 18: # ! 19: { ! 20: # ! 21: # select PST/Traconex WWV records ! 22: # 00:00:37.234 96/07/08/190 O6@0:5281825C07510394 ! 23: # ! 24: if (NF >= 4 && $3 == "127.127.3.1") { ! 25: if (substr($6, 14, 4) > "0010") ! 26: wwv_sync++ ! 27: if (substr($6, 13, 1) == "C") ! 28: wwv_wwv++ ! 29: if (substr($6, 13, 1) == "H") ! 30: wwv_wwvh++ ! 31: x = substr($6, 12, 1) ! 32: if (x == "1") ! 33: wwv_2.5++ ! 34: else if (x == "2") ! 35: wwv_5++ ! 36: else if (x == "3") ! 37: wwv_10++ ! 38: else if (x == "4") ! 39: wwv_15++ ! 40: else if (x == "5") ! 41: wwv_20++ ! 42: continue ! 43: } ! 44: # ! 45: # select Arbiter GPS records ! 46: # 96 190 00:00:37.000 0 V=08 S=44 T=3 P=10.6 E=00 ! 47: # N39:42:00.951 W075:46:54.880 210.55 2.50 0.00 ! 48: # ! 49: if (NF >= 4 && $3 == "127.127.11.1") { ! 50: if (NF > 8) { ! 51: arb_count++ ! 52: if ($7 != 0) ! 53: arb_sync++ ! 54: x = substr($10, 3, 1) ! 55: if (x == "0") ! 56: arb_0++ ! 57: else if (x == "1") ! 58: arb_1++ ! 59: else if (x == "2") ! 60: arb_2++ ! 61: else if (x == "3") ! 62: arb_3++ ! 63: else if (x == "4") ! 64: arb_4++ ! 65: else if (x == "5") ! 66: arb_5++ ! 67: else if (x == "6") ! 68: arb_6++ ! 69: } else if (NF == 8) { ! 70: arbn++ ! 71: arb_mean += $7 ! 72: arb_rms += $7 * $7 ! 73: if (arbn > 0) { ! 74: x = $7 - arb_val ! 75: arb_var += x * x ! 76: } ! 77: arb_val = $7 ! 78: } ! 79: continue ! 80: } ! 81: # ! 82: # select Spectracom WWVB records ! 83: # see summary for decode ! 84: # 96 189 23:59:32.248 D ! 85: # ! 86: if (NF >= 4 && $3 == "127.127.4.1") { ! 87: if ($4 == "SIGNAL" || NF > 7) ! 88: printf "%s\n", $0 ! 89: else { ! 90: wwvb_count++ ! 91: if ($4 ~ /\?/) ! 92: wwvb_x++ ! 93: else if ($4 ~ /A/) ! 94: wwvb_a++ ! 95: else if ($4 ~ /B/) ! 96: wwvb_b++ ! 97: else if ($4 ~ /C/) ! 98: wwvb_c++ ! 99: else if ($4 ~ /D/) ! 100: wwvb_d++ ! 101: } ! 102: continue ! 103: } ! 104: # ! 105: # select IRIG audio decoder records ! 106: # see summary for decode ! 107: # ! 108: if (NF >= 4 && $3 == "127.127.6.0") { ! 109: irig_count++ ! 110: if ($5 ~ /\?/) ! 111: irig_error++ ! 112: continue ! 113: } ! 114: # ! 115: # select Austron GPS LORAN ENSEMBLE records ! 116: # see summary for decode ! 117: # ! 118: else if (NF >= 13 && $6 == "ENSEMBLE") { ! 119: ensemble_count++ ! 120: if ($9 <= 0) ! 121: ensemble_badgps++ ! 122: else if ($12 <= 0) ! 123: ensemble_badloran++ ! 124: else { ! 125: if ($13 > 200e-9 || $13 < -200e-9) ! 126: ensemble_200++ ! 127: else if ($13 > 100e-9 || $13 < -100e-9) ! 128: ensemble_100++ ! 129: ensemble_mean += $13 ! 130: ensemble_rms += $13 * $13 ! 131: } ! 132: continue ! 133: } ! 134: # ! 135: # select Austron LORAN TDATA records ! 136: # see summary for decode; note that signal quality log is simply ! 137: # copied to output ! 138: # ! 139: else if (NF >= 7 && $6 == "TDATA") { ! 140: tdata_count++ ! 141: for (i = 7; i < NF; i++) { ! 142: if ($i == "M" && $(i+1) == "OK") { ! 143: i += 5 ! 144: m += $i ! 145: tdata_m++ ! 146: } ! 147: else if ($i == "W" && $(i+1) == "OK") { ! 148: i += 5 ! 149: w += $i ! 150: tdata_w++ ! 151: } ! 152: else if ($i == "X" && $(i+1) == "OK") { ! 153: i += 5 ! 154: x += $i ! 155: tdata_x++ ! 156: } ! 157: else if ($i == "Y" && $(i+1) == "OK") { ! 158: i += 5 ! 159: y += $i ! 160: tdata_y++ ! 161: } ! 162: else if ($i == "Z" && $(i+1) == "OK") { ! 163: i += 5 ! 164: z += $i ! 165: tdata_z++ ! 166: } ! 167: } ! 168: continue ! 169: } ! 170: # ! 171: # select Austron ITF records ! 172: # see summary for decode ! 173: # ! 174: else if (NF >= 13 && $5 == "ITF" && $12 >= 100) { ! 175: itf_count++ ! 176: if ($9 > 200e-9 || $9 < -200e-9) ! 177: itf_200++ ! 178: else if ($9 > 100e-9 || $9 < -100e-9) ! 179: itf_100++ ! 180: itf_mean += $9 ! 181: itf_rms += $9 * $9 ! 182: itf_var += $10 * $10 ! 183: continue ! 184: } ! 185: # ! 186: # select Austron ETF records ! 187: # see summary for decode ! 188: # ! 189: else if (NF >= 13 && $5 == "ETF" && $13 >= 100) { ! 190: etf_count++ ! 191: if ($6 > etf_max) ! 192: etf_max = $6 ! 193: else if ($6 < etf_min) ! 194: etf_min = $6 ! 195: etf_mean += $6 ! 196: etf_rms += $6 * $6 ! 197: etf_var += $9 * $9 ! 198: continue ! 199: } ! 200: # ! 201: # select Austron TRSTAT records ! 202: # see summary for decode ! 203: # ! 204: else if (NF >= 5 && $5 == "TRSTAT") { ! 205: trstat_count++ ! 206: j = 0 ! 207: for (i = 6; i <= NF; i++) ! 208: if ($i == "T") ! 209: j++ ! 210: trstat_sat[j]++ ! 211: continue ! 212: } ! 213: # ! 214: # select Austron ID;OPT;VER records ! 215: # ! 216: # config GPS 2201A TTY1 TC1 LORAN IN OUT1 B.00 B.00 28-Apr-93 ! 217: # ! 218: # GPS 2201A receiver model ! 219: # TTY1 rs232 moduel ! 220: # TC1 IRIG module ! 221: # LORAN LORAN assist module ! 222: # IN input module ! 223: # OUT1 output module ! 224: # B.00 B.00 firmware revision ! 225: # 28-Apr-9 firmware date3 ! 226: # ! 227: else if (NF >= 5 && $5 == "ID;OPT;VER") { ! 228: id_count++ ! 229: id_temp = "" ! 230: for (i = 6; i <= NF; i++) ! 231: id_temp = id_temp " " $i ! 232: if (id_string != id_temp) ! 233: printf "config%s\n", id_temp ! 234: id_string = id_temp ! 235: continue ! 236: } ! 237: # ! 238: # select Austron POS;PPS;PPSOFF records ! 239: # ! 240: # position +39:40:48.425 -075:45:02.392 +74.09 Stored UTC 0 200 0 ! 241: # ! 242: # +39:40:48.425 position north latitude ! 243: # -075:45:02.392 position east longitude ! 244: # +74.09 elevation (meters) ! 245: # Stored position is stored ! 246: # UTC time is relative to UTC ! 247: # 0 200 0 PPS offsets ! 248: # ! 249: else if (NF >= 5 && $5 == "POS;PPS;PPSOFF") { ! 250: pos_count++ ! 251: pos_temp = "" ! 252: for (i = 6; i <= NF; i++) ! 253: pos_temp = pos_temp " " $i ! 254: if (pos_string != pos_temp) ! 255: printf "position%s\n", pos_temp ! 256: pos_string = pos_temp ! 257: continue ! 258: } ! 259: # ! 260: # select Austron OSC;ET;TEMP records ! 261: # ! 262: # loop 1121 Software Control Locked ! 263: # ! 264: # 1121 oscillator type ! 265: # Software Control loop is under software control ! 266: # Locked loop is locked ! 267: # ! 268: else if (NF >= 5 && $5 == "OSC;ET;TEMP") { ! 269: osc_count++ ! 270: osc_temp = $6 " " $7 " " $8 " " $9 ! 271: if (osc_status != osc_temp) ! 272: printf "loop %s\n", osc_temp ! 273: osc_status = osc_temp ! 274: if ($10 > osc_vmax) ! 275: osc_vmax = $10 ! 276: if ($10 < osc_vmin) ! 277: osc_vmin = $10 ! 278: if ($11 > osc_tmax) ! 279: osc_tmax = $11 ! 280: if ($11 < osc_tmin) ! 281: osc_tmin = $11 ! 282: continue ! 283: } ! 284: # ! 285: # select Austron UTC records ! 286: # these ain't ready yet ! 287: # ! 288: else if (NF >= 5 && $5 == "UTC") { ! 289: utc_count++ ! 290: utc_temp = "" ! 291: for (i = 6; i <= NF; i++) ! 292: utc_temp = utc_temp " " $i ! 293: if (utc_string != utc_temp) ! 294: # printf "utc%s\n", utc_temp ! 295: utc_string = utc_temp ! 296: continue ! 297: } ! 298: } END { ! 299: # ! 300: # PST/Traconex WWV summary data ! 301: # ! 302: if (wwv_wwv + wwv_wwvh > 0) ! 303: printf "wwv %d, wwvh %d, err %d, MHz (2.5) %d, (5) %d, (10) %d, (15) %d, (20) %d\n", wwv_wwv, wwv_wwvh, wwv_sync, wwv_2.5, wwv_5, wwv_10, wwv_15, wwv_20 ! 304: # ! 305: # Arbiter 1088 summary data ! 306: # ! 307: # gps record count ! 308: # err error count ! 309: # sats(0-6) satellites tracked ! 310: # mean 1 PPS mean (us) ! 311: # rms 1 PPS rms error (us) ! 312: # var 1 PPS Allan variance ! 313: # ! 314: if (arb_count > 0) { ! 315: printf "gps %d, err %d, sats(0-6) %d %d %d %d %d %d %d", arb_count, arb_sync, arb_0, arb_1, arb_2, arb_3, arb_4, arb_5, arb_6 ! 316: if (arbn > 1) { ! 317: arb_mean /= arbn ! 318: arb_rms = sqrt(arb_rms / arbn - arb_mean * arb_mean) ! 319: arb_var = sqrt(arb_var / (2 * (arbn - 1))) ! 320: printf ", mean %.2f, rms %.2f, var %.2e\n", arb_mean, arb_rms, arb_var * 1e-6 ! 321: } else { ! 322: printf "\n" ! 323: } ! 324: } ! 325: # ! 326: # ensemble summary data ! 327: # ! 328: # ensemble record count ! 329: # badgps gps data unavailable ! 330: # badloran loran data unavailable ! 331: # rms ensemble rms error (ns) ! 332: # >200 ensemble error >200 ns ! 333: # >100 100 ns < ensemble error < 200 ns ! 334: # ! 335: if (ensemble_count > 0) { ! 336: ensemble_mean /= ensemble_count ! 337: ensemble_rms = sqrt(ensemble_rms / ensemble_count - ensemble_mean * ensemble_mean) * 1e9 ! 338: printf "ensemble %d, badgps %d, badloran %d, rms %.1f, >200 %d, >100 %d\n", ensemble_count, ensemble_badgps, ensemble_badloran, ensemble_rms, ensemble_200, ensemble_100 ! 339: } ! 340: # ! 341: # wwvb summary data ! 342: # ! 343: # wwvb record count ! 344: # ? unsynchronized ! 345: # >1 error > 1 ms ! 346: # >10 error > 10 ms ! 347: # >100 error > 100 ms ! 348: # >500 error > 500 ms ! 349: # ! 350: if (wwvb_count > 0) ! 351: printf "wwvb %d, ? %d, >1 %d, >10 %d, >100 %d, >500 %d\n", wwvb_count, wwvb_x, wwvb_a, wwvb_b, wwvb_c, wwvb_d ! 352: # ! 353: # irig summary data ! 354: # ! 355: # irig record count ! 356: # err error count ! 357: # ! 358: if (irig_count > 0) ! 359: printf "irig %d, err %d\n", irig_count, irig_error ! 360: # ! 361: # tdata summary data ! 362: # ! 363: # tdata record count ! 364: # m M master OK-count, mean level (dB) ! 365: # w W slave OK-count, mean level (dB) ! 366: # x X slave OK-count, mean level (dB) ! 367: # y Y slave OK-count, mean level (dB) ! 368: # z Z slave OK-count, mean level (dB) ! 369: # ! 370: if (tdata_count > 0 ) { ! 371: if (tdata_m > 0) ! 372: m /= tdata_count ! 373: if (tdata_x > 0) ! 374: w /= tdata_count ! 375: if (tdata_x > 0) ! 376: x /= tdata_count ! 377: if (tdata_y > 0) ! 378: y /= tdata_count ! 379: if (tdata_z > 0) ! 380: z /= tdata_count ! 381: printf "tdata %d, m %d %.1f, w %d %.1f, x %d %.1f, y %d %.1f, z %d %.1f\n", tdata_count, tdata_m, m, tdata_w, w, tdata_x, x, tdata_y, y, tdata_z, z ! 382: } ! 383: # ! 384: # itf summary data ! 385: # ! 386: # itf record count ! 387: # rms itf rms error (ns) ! 388: # >200 itf error > 200 ns ! 389: # >100 itf error > 100 ns ! 390: # var Allan variance ! 391: # ! 392: if (itf_count > 1) { ! 393: itf_mean /= itf_count ! 394: itf_rms = sqrt(itf_rms / itf_count - itf_mean * itf_mean) * 1e9 ! 395: itf_var = sqrt(itf_var / (2 * (itf_count - 1))) ! 396: printf "itf %d, rms %.1f, >200 %d, >100 %d, var %.2e\n", itf_count, itf_rms, itf_200, itf_100, itf_var ! 397: } ! 398: # ! 399: # etf summary data ! 400: # ! 401: # etf record count ! 402: # mean etf mean (ns) ! 403: # rms etf rms error (ns) ! 404: # max etf maximum (ns) ! 405: # min etf minimum (ns) ! 406: # var Allan variance ! 407: # ! 408: if (etf_count > 0) { ! 409: etf_mean /= etf_count ! 410: etf_rms = sqrt(etf_rms / etf_count - etf_mean * etf_mean) ! 411: etf_var = sqrt(etf_var / (2 * (etf_count - 1))) ! 412: printf "etf %d, mean %.1f, rms %.1f, max %d, min %d, var %.2e\n", etf_count, etf_mean, etf_rms, etf_max, etf_min, etf_var ! 413: } ! 414: # ! 415: # trstat summary data ! 416: # ! 417: # trstat record count ! 418: # sat histogram of tracked satellites (0 - 7) ! 419: # ! 420: if (trstat_count > 0) ! 421: printf "trstat %d, sat %d %d %d %d %d %d %d %d\n", trstat_count, trstat_sat[0], trstat_sat[1], trstat_sat[2], trstat_sat[2], trstat_sat[3], trstat_sat[4], trstat_sat[5], trstat_sat[6], trstat_sat[7] ! 422: # ! 423: # osc summary data ! 424: # ! 425: # osc record count ! 426: # control control midrange (V) +/- deviation (mV) ! 427: # temp oven temperature midrange +/- deviation (deg C) ! 428: # ! 429: if (osc_count > 0) ! 430: printf "osc %d, control %.3f+/-%.3f, temp %.1f+/-%.2f\n", osc_count, (osc_vmax + osc_vmin) / 2, (osc_vmax - osc_vmin) / 2 * 1e3, (osc_tmax + osc_tmin) / 2, (osc_tmax - osc_tmin) / 2 ! 431: }