gpsutils.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. /* gpsutils.c -- code shared between low-level and high-level interfaces
  2. *
  3. * This file is Copyright 2010 by the GPSD project
  4. * SPDX-License-Identifier: BSD-2-clause
  5. */
  6. /* The strptime prototype is not provided unless explicitly requested.
  7. * We also need to set the value high enough to signal inclusion of
  8. * newer features (like clock_gettime). See the POSIX spec for more info:
  9. * http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_01_02 */
  10. #include "gpsd_config.h" /* must be before all includes */
  11. #include <ctype.h>
  12. #include <errno.h>
  13. #include <math.h>
  14. #include <stdbool.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys/select.h> /* for to have a pselect(2) prototype a la POSIX */
  19. #include <sys/time.h> /* for to have a pselect(2) prototype a la SuS */
  20. #include <time.h>
  21. #include "gps.h"
  22. #include "libgps.h"
  23. #include "os_compat.h"
  24. #include "timespec.h"
  25. #ifdef USE_QT
  26. #include <QDateTime>
  27. #include <QStringList>
  28. #endif
  29. /*
  30. * Berkeley implementation of strtod(), inlined to avoid locale problems
  31. * with the decimal point and stripped down to an atof()-equivalent.
  32. */
  33. /* Takes a decimal ASCII floating-point number, optionally
  34. * preceded by white space. Must have form "-I.FE-X",
  35. * where I is the integer part of the mantissa, F is
  36. * the fractional part of the mantissa, and X is the
  37. * exponent. Either of the signs may be "+", "-", or
  38. * omitted. Either I or F may be omitted, or both.
  39. * The decimal point isn't necessary unless F is
  40. * present. The "E" may actually be an "e". E and X
  41. * may both be omitted (but not just one).
  42. *
  43. * returns NaN if *string is zero length
  44. */
  45. double safe_atof(const char *string)
  46. {
  47. static int maxExponent = 511; /* Largest possible base 10 exponent. Any
  48. * exponent larger than this will already
  49. * produce underflow or overflow, so there's
  50. * no need to worry about additional digits.
  51. */
  52. /* Table giving binary powers of 10. Entry is 10^2^i.
  53. * Used to convert decimal exponents into floating-point numbers. */
  54. static double powersOf10[] = {
  55. 10.,
  56. 100.,
  57. 1.0e4,
  58. 1.0e8,
  59. 1.0e16,
  60. 1.0e32,
  61. 1.0e64,
  62. 1.0e128,
  63. 1.0e256
  64. };
  65. bool sign, expSign = false;
  66. double fraction, dblExp, *d;
  67. const char *p;
  68. int c;
  69. int exp = 0; /* Exponent read from "EX" field. */
  70. int fracExp = 0; /* Exponent that derives from the fractional
  71. * part. Under normal circumstatnces, it is
  72. * the negative of the number of digits in F.
  73. * However, if I is very long, the last digits
  74. * of I get dropped (otherwise a long I with a
  75. * large negative exponent could cause an
  76. * unnecessary overflow on I alone). In this
  77. * case, fracExp is incremented one for each
  78. * dropped digit. */
  79. int mantSize; /* Number of digits in mantissa. */
  80. int decPt; /* Number of mantissa digits BEFORE decimal
  81. * point. */
  82. const char *pExp; /* Temporarily holds location of exponent
  83. * in string. */
  84. /*
  85. * Strip off leading blanks and check for a sign.
  86. */
  87. p = string;
  88. while (isspace((unsigned char) *p)) {
  89. p += 1;
  90. }
  91. if (*p == '\0') {
  92. return NAN;
  93. } else if (*p == '-') {
  94. sign = true;
  95. p += 1;
  96. } else {
  97. if (*p == '+') {
  98. p += 1;
  99. }
  100. sign = false;
  101. }
  102. /*
  103. * Count the number of digits in the mantissa (including the decimal
  104. * point), and also locate the decimal point.
  105. */
  106. decPt = -1;
  107. for (mantSize = 0; ; mantSize += 1)
  108. {
  109. c = *p;
  110. if (!isdigit(c)) {
  111. if ((c != '.') || (decPt >= 0)) {
  112. break;
  113. }
  114. decPt = mantSize;
  115. }
  116. p += 1;
  117. }
  118. /*
  119. * Now suck up the digits in the mantissa. Use two integers to
  120. * collect 9 digits each (this is faster than using floating-point).
  121. * If the mantissa has more than 18 digits, ignore the extras, since
  122. * they can't affect the value anyway.
  123. */
  124. pExp = p;
  125. p -= mantSize;
  126. if (decPt < 0) {
  127. decPt = mantSize;
  128. } else {
  129. mantSize -= 1; /* One of the digits was the point. */
  130. }
  131. if (mantSize > 18) {
  132. fracExp = decPt - 18;
  133. mantSize = 18;
  134. } else {
  135. fracExp = decPt - mantSize;
  136. }
  137. if (mantSize == 0) {
  138. fraction = 0.0;
  139. //p = string;
  140. goto done;
  141. } else {
  142. int frac1, frac2;
  143. frac1 = 0;
  144. for ( ; mantSize > 9; mantSize -= 1)
  145. {
  146. c = *p;
  147. p += 1;
  148. if (c == '.') {
  149. c = *p;
  150. p += 1;
  151. }
  152. frac1 = 10*frac1 + (c - '0');
  153. }
  154. frac2 = 0;
  155. for (; mantSize > 0; mantSize -= 1)
  156. {
  157. c = *p;
  158. p += 1;
  159. if (c == '.') {
  160. c = *p;
  161. p += 1;
  162. }
  163. frac2 = 10*frac2 + (c - '0');
  164. }
  165. fraction = (1.0e9 * frac1) + frac2;
  166. }
  167. /*
  168. * Skim off the exponent.
  169. */
  170. p = pExp;
  171. if ((*p == 'E') || (*p == 'e')) {
  172. p += 1;
  173. if (*p == '-') {
  174. expSign = true;
  175. p += 1;
  176. } else {
  177. if (*p == '+') {
  178. p += 1;
  179. }
  180. expSign = false;
  181. }
  182. while (isdigit((unsigned char) *p)) {
  183. exp = exp * 10 + (*p - '0');
  184. p += 1;
  185. }
  186. }
  187. if (expSign) {
  188. exp = fracExp - exp;
  189. } else {
  190. exp = fracExp + exp;
  191. }
  192. /*
  193. * Generate a floating-point number that represents the exponent.
  194. * Do this by processing the exponent one bit at a time to combine
  195. * many powers of 2 of 10. Then combine the exponent with the
  196. * fraction.
  197. */
  198. if (exp < 0) {
  199. expSign = true;
  200. exp = -exp;
  201. } else {
  202. expSign = false;
  203. }
  204. if (exp > maxExponent) {
  205. exp = maxExponent;
  206. errno = ERANGE;
  207. }
  208. dblExp = 1.0;
  209. for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
  210. if (exp & 01) {
  211. dblExp *= *d;
  212. }
  213. }
  214. if (expSign) {
  215. fraction /= dblExp;
  216. } else {
  217. fraction *= dblExp;
  218. }
  219. done:
  220. if (sign) {
  221. return -fraction;
  222. }
  223. return fraction;
  224. }
  225. #define MONTHSPERYEAR 12 /* months per calendar year */
  226. /* stuff a fix structure with recognizable out-of-band values */
  227. void gps_clear_fix(struct gps_fix_t *fixp)
  228. {
  229. memset(fixp, 0, sizeof(struct gps_fix_t));
  230. fixp->altitude = NAN; // DEPRECATED, undefined
  231. fixp->altHAE = NAN;
  232. fixp->altMSL = NAN;
  233. fixp->climb = NAN;
  234. fixp->depth = NAN;
  235. fixp->epc = NAN;
  236. fixp->epd = NAN;
  237. fixp->eph = NAN;
  238. fixp->eps = NAN;
  239. fixp->ept = NAN;
  240. fixp->epv = NAN;
  241. fixp->epx = NAN;
  242. fixp->epy = NAN;
  243. fixp->latitude = NAN;
  244. fixp->longitude = NAN;
  245. fixp->magnetic_track = NAN;
  246. fixp->magnetic_var = NAN;
  247. fixp->mode = MODE_NOT_SEEN;
  248. fixp->sep = NAN;
  249. fixp->speed = NAN;
  250. fixp->track = NAN;
  251. /* clear ECEF too */
  252. fixp->ecef.x = NAN;
  253. fixp->ecef.y = NAN;
  254. fixp->ecef.z = NAN;
  255. fixp->ecef.vx = NAN;
  256. fixp->ecef.vy = NAN;
  257. fixp->ecef.vz = NAN;
  258. fixp->ecef.pAcc = NAN;
  259. fixp->ecef.vAcc = NAN;
  260. fixp->NED.relPosN = NAN;
  261. fixp->NED.relPosE = NAN;
  262. fixp->NED.relPosD = NAN;
  263. fixp->NED.velN = NAN;
  264. fixp->NED.velE = NAN;
  265. fixp->NED.velD = NAN;
  266. fixp->geoid_sep = NAN;
  267. fixp->dgps_age = NAN;
  268. fixp->dgps_station = -1;
  269. fixp->wanglem = NAN;
  270. fixp->wangler = NAN;
  271. fixp->wanglet = NAN;
  272. fixp->wspeedr = NAN;
  273. fixp->wspeedt = NAN;
  274. }
  275. /* stuff an attitude structure with recognizable out-of-band values */
  276. void gps_clear_att(struct attitude_t *attp)
  277. {
  278. memset(attp, 0, sizeof(struct attitude_t));
  279. attp->pitch = NAN;
  280. attp->roll = NAN;
  281. attp->yaw = NAN;
  282. attp->dip = NAN;
  283. attp->mag_len = NAN;
  284. attp->mag_x = NAN;
  285. attp->mag_y = NAN;
  286. attp->mag_z = NAN;
  287. attp->acc_len = NAN;
  288. attp->acc_x = NAN;
  289. attp->acc_y = NAN;
  290. attp->acc_z = NAN;
  291. attp->gyro_x = NAN;
  292. attp->gyro_y = NAN;
  293. attp->temp = NAN;
  294. attp->depth = NAN;
  295. }
  296. void gps_clear_dop( struct dop_t *dop)
  297. {
  298. dop->xdop = dop->ydop = dop->vdop = dop->tdop = dop->hdop = dop->pdop =
  299. dop->gdop = NAN;
  300. }
  301. /* stuff a log structure with recognizable out-of-band values */
  302. void gps_clear_log(struct gps_log_t *logp)
  303. {
  304. memset(logp, 0, sizeof(struct gps_log_t));
  305. logp->lon = NAN;
  306. logp->lat = NAN;
  307. logp->altHAE = NAN;
  308. logp->altMSL = NAN;
  309. logp->gSpeed = NAN;
  310. logp->heading = NAN;
  311. logp->tAcc = NAN;
  312. logp->hAcc = NAN;
  313. logp->vAcc = NAN;
  314. logp->sAcc = NAN;
  315. logp->headAcc = NAN;
  316. logp->velN = NAN;
  317. logp->velE = NAN;
  318. logp->velD = NAN;
  319. logp->pDOP = NAN;
  320. logp->distance = NAN;
  321. logp->totalDistance = NAN;
  322. logp->distanceStd = NAN;
  323. logp->fixType = -1;
  324. }
  325. /* merge new data (from) into current fix (to)
  326. * Being careful not to lose information */
  327. void gps_merge_fix(struct gps_fix_t *to,
  328. gps_mask_t transfer,
  329. struct gps_fix_t *from)
  330. {
  331. if ((NULL == to) || (NULL == from))
  332. return;
  333. if ((transfer & TIME_SET) != 0)
  334. to->time = from->time;
  335. if ((transfer & LATLON_SET) != 0) {
  336. to->latitude = from->latitude;
  337. to->longitude = from->longitude;
  338. }
  339. if (0 != (transfer & MODE_SET)) {
  340. /* FIXME? Maybe only upgrade mode, not downgrade it */
  341. to->mode = from->mode;
  342. }
  343. /* Some messages only report mode, some mode and status, some only status.
  344. * Only upgrade status, not downgrade it */
  345. if (0 != (transfer & STATUS_SET)) {
  346. if (to->status < from->status) {
  347. to->status = from->status;
  348. }
  349. }
  350. if ((transfer & ALTITUDE_SET) != 0) {
  351. if (0 != isfinite(from->altHAE)) {
  352. to->altHAE = from->altHAE;
  353. }
  354. if (0 != isfinite(from->altMSL)) {
  355. to->altMSL = from->altMSL;
  356. }
  357. if (0 != isfinite(from->depth)) {
  358. to->depth = from->depth;
  359. }
  360. }
  361. if ((transfer & TRACK_SET) != 0)
  362. to->track = from->track;
  363. if ((transfer & MAGNETIC_TRACK_SET) != 0) {
  364. if (0 != isfinite(from->magnetic_track)) {
  365. to->magnetic_track = from->magnetic_track;
  366. }
  367. if (0 != isfinite(from->magnetic_var)) {
  368. to->magnetic_var = from->magnetic_var;
  369. }
  370. }
  371. if ((transfer & SPEED_SET) != 0)
  372. to->speed = from->speed;
  373. if ((transfer & CLIMB_SET) != 0)
  374. to->climb = from->climb;
  375. if ((transfer & TIMERR_SET) != 0)
  376. to->ept = from->ept;
  377. if (0 != isfinite(from->epx) &&
  378. 0 != isfinite(from->epy)) {
  379. to->epx = from->epx;
  380. to->epy = from->epy;
  381. }
  382. if (0 != isfinite(from->epd)) {
  383. to->epd = from->epd;
  384. }
  385. if (0 != isfinite(from->eph)) {
  386. to->eph = from->eph;
  387. }
  388. if (0 != isfinite(from->eps)) {
  389. to->eps = from->eps;
  390. }
  391. /* spherical error probability, not geoid separation */
  392. if (0 != isfinite(from->sep)) {
  393. to->sep = from->sep;
  394. }
  395. /* geoid separation, not spherical error probability */
  396. if (0 != isfinite(from->geoid_sep)) {
  397. to->geoid_sep = from->geoid_sep;
  398. }
  399. if (0 != isfinite(from->epv)) {
  400. to->epv = from->epv;
  401. }
  402. if ((transfer & SPEEDERR_SET) != 0)
  403. to->eps = from->eps;
  404. if ((transfer & ECEF_SET) != 0) {
  405. to->ecef.x = from->ecef.x;
  406. to->ecef.y = from->ecef.y;
  407. to->ecef.z = from->ecef.z;
  408. to->ecef.pAcc = from->ecef.pAcc;
  409. }
  410. if ((transfer & VECEF_SET) != 0) {
  411. to->ecef.vx = from->ecef.vx;
  412. to->ecef.vy = from->ecef.vy;
  413. to->ecef.vz = from->ecef.vz;
  414. to->ecef.vAcc = from->ecef.vAcc;
  415. }
  416. if (0 != (transfer & NED_SET)) {
  417. to->NED.relPosN = from->NED.relPosN;
  418. to->NED.relPosE = from->NED.relPosE;
  419. to->NED.relPosD = from->NED.relPosD;
  420. if ((0 != isfinite(from->NED.relPosH)) &&
  421. (0 != isfinite(from->NED.relPosL))) {
  422. to->NED.relPosH = from->NED.relPosH;
  423. to->NED.relPosL = from->NED.relPosL;
  424. }
  425. }
  426. if ((transfer & VNED_SET) != 0) {
  427. to->NED.velN = from->NED.velN;
  428. to->NED.velE = from->NED.velE;
  429. to->NED.velD = from->NED.velD;
  430. }
  431. if ('\0' != from->datum[0]) {
  432. strlcpy(to->datum, from->datum, sizeof(to->datum));
  433. }
  434. if (0 != isfinite(from->dgps_age) &&
  435. 0 <= from->dgps_station) {
  436. /* both, or neither */
  437. to->dgps_age = from->dgps_age;
  438. to->dgps_station = from->dgps_station;
  439. }
  440. // navdata stuff. just wind angle and angle for now
  441. if (0 != (transfer & NAVDATA_SET)) {
  442. if (0 != isfinite(from->wanglem)) {
  443. to->wanglem = from->wanglem;
  444. }
  445. if (0 != isfinite(from->wangler)) {
  446. to->wangler = from->wangler;
  447. }
  448. if (0 != isfinite(from->wanglet)) {
  449. to->wanglet = from->wanglet;
  450. }
  451. if (0 != isfinite(from->wspeedr)) {
  452. to->wspeedr = from->wspeedr;
  453. }
  454. if (0 != isfinite(from->wspeedt)) {
  455. to->wspeedt = from->wspeedt;
  456. }
  457. }
  458. }
  459. /* mkgmtime(tm)
  460. * convert struct tm, as UTC, to seconds since Unix epoch
  461. * This differs from mktime() from libc.
  462. * mktime() takes struct tm as localtime.
  463. *
  464. * The inverse of gmtime(time_t)
  465. */
  466. time_t mkgmtime(struct tm * t)
  467. {
  468. int year;
  469. time_t result;
  470. static const int cumdays[MONTHSPERYEAR] =
  471. { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  472. year = 1900 + t->tm_year + t->tm_mon / MONTHSPERYEAR;
  473. result = (year - 1970) * 365 + cumdays[t->tm_mon % MONTHSPERYEAR];
  474. result += (year - 1968) / 4;
  475. result -= (year - 1900) / 100;
  476. result += (year - 1600) / 400;
  477. if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) &&
  478. (t->tm_mon % MONTHSPERYEAR) < 2)
  479. result--;
  480. result += t->tm_mday - 1;
  481. result *= 24;
  482. result += t->tm_hour;
  483. result *= 60;
  484. result += t->tm_min;
  485. result *= 60;
  486. result += t->tm_sec;
  487. /* this is UTC, no DST
  488. * if (t->tm_isdst == 1)
  489. * result -= 3600;
  490. */
  491. return (result);
  492. }
  493. timespec_t iso8601_to_timespec(char *isotime)
  494. /* ISO8601 UTC to Unix timespec, no leapsecond correction. */
  495. {
  496. timespec_t ret;
  497. #ifndef __clang_analyzer__
  498. #ifndef USE_QT
  499. char *dp = NULL;
  500. double usec = 0;
  501. struct tm tm;
  502. memset(&tm,0,sizeof(tm));
  503. #ifdef HAVE_STRPTIME
  504. dp = strptime(isotime, "%Y-%m-%dT%H:%M:%S", &tm);
  505. #else
  506. /* Fallback for systems without strptime (i.e. Windows)
  507. * This is a simplistic conversion for iso8601 strings only,
  508. * rather than embedding a full copy of strptime() that handles
  509. * all formats */
  510. double sec;
  511. /* Thus avoiding needing to test for (broken) negative date/time
  512. * numbers in token reading - only need to check the upper range */
  513. unsigned int tmp;
  514. bool failed = false;
  515. char *isotime_tokenizer = strdup(isotime);
  516. if (isotime_tokenizer) {
  517. char *tmpbuf;
  518. char *pch = strtok_r(isotime_tokenizer, "-T:", &tmpbuf);
  519. int token_number = 0;
  520. while (pch != NULL) {
  521. token_number++;
  522. // Give up if encountered way too many tokens.
  523. if (token_number > 10) {
  524. failed = true;
  525. break;
  526. }
  527. switch (token_number) {
  528. case 1: // Year token
  529. tmp = atoi(pch);
  530. if (tmp < 9999)
  531. tm.tm_year = tmp - 1900; // Adjust to tm year
  532. else
  533. failed = true;
  534. break;
  535. case 2: // Month token
  536. tmp = atoi(pch);
  537. if (tmp < 13)
  538. tm.tm_mon = tmp - 1; // Month indexing starts from zero
  539. else
  540. failed = true;
  541. break;
  542. case 3: // Day token
  543. tmp = atoi(pch);
  544. if (tmp < 32)
  545. tm.tm_mday = tmp;
  546. else
  547. failed = true;
  548. break;
  549. case 4: // Hour token
  550. tmp = atoi(pch);
  551. if (tmp < 24)
  552. tm.tm_hour = tmp;
  553. else
  554. failed = true;
  555. break;
  556. case 5: // Minute token
  557. tmp = atoi(pch);
  558. if (tmp < 60)
  559. tm.tm_min = tmp;
  560. else
  561. failed = true;
  562. break;
  563. case 6: // Seconds token
  564. sec = safe_atof(pch);
  565. // NB To handle timestamps with leap seconds
  566. if (0 == isfinite(sec) &&
  567. sec >= 0.0 && sec < 61.5 ) {
  568. tm.tm_sec = (unsigned int)sec; // Truncate to get integer value
  569. usec = sec - (unsigned int)sec; // Get the fractional part (if any)
  570. }
  571. else
  572. failed = true;
  573. break;
  574. default: break;
  575. }
  576. pch = strtok_r(NULL, "-T:", &tmpbuf);
  577. }
  578. free(isotime_tokenizer);
  579. // Split may result in more than 6 tokens if the TZ has any t's in it
  580. // So check that we've seen enough tokens rather than an exact number
  581. if (token_number < 6)
  582. failed = true;
  583. }
  584. if (failed)
  585. memset(&tm,0,sizeof(tm));
  586. else {
  587. // When successful this normalizes tm so that tm_yday is set
  588. // and thus tm is valid for use with other functions
  589. if (mktime(&tm) == (time_t)-1)
  590. // Failed mktime - so reset the timestamp
  591. memset(&tm,0,sizeof(tm));
  592. }
  593. #endif
  594. if (dp != NULL && *dp == '.')
  595. usec = strtod(dp, NULL);
  596. /*
  597. * It would be nice if we could say mktime(&tm) - timezone + usec instead,
  598. * but timezone is not available at all on some BSDs. Besides, when working
  599. * with historical dates the value of timezone after an ordinary tzset(3)
  600. * can be wrong; you have to do a redirect through the IANA historical
  601. * timezone database to get it right.
  602. */
  603. ret.tv_sec = mkgmtime(&tm);
  604. ret.tv_nsec = usec * 1e9;;
  605. #else
  606. double usec = 0;
  607. QString t(isotime);
  608. QDateTime d = QDateTime::fromString(isotime, Qt::ISODate);
  609. QStringList sl = t.split(".");
  610. if (sl.size() > 1)
  611. usec = sl[1].toInt() / pow(10., (double)sl[1].size());
  612. ret.tv_sec = d.toTime_t();
  613. ret.tv_nsec = usec * 1e9;;
  614. #endif
  615. #endif /* __clang_analyzer__ */
  616. return ret;
  617. }
  618. /* Unix timespec UTC time to ISO8601, no timezone adjustment */
  619. /* example: 2007-12-11T23:38:51.033Z */
  620. char *timespec_to_iso8601(timespec_t fixtime, char isotime[], size_t len)
  621. {
  622. struct tm when;
  623. char timestr[30];
  624. long fracsec;
  625. if (0 > fixtime.tv_sec) {
  626. // Allow 0 for testing of 1970-01-01T00:00:00.000Z
  627. return strncpy(isotime, "NaN", len);
  628. }
  629. if (999499999 < fixtime.tv_nsec) {
  630. /* round up */
  631. fixtime.tv_sec++;
  632. fixtime.tv_nsec = 0;
  633. }
  634. #ifdef HAVE_GMTIME_R
  635. (void)gmtime_r(&fixtime.tv_sec, &when);
  636. #else
  637. /* Fallback to try with gmtime_s - primarily for Windows */
  638. (void)gmtime_s(&when, &fixtime.tv_sec);
  639. #endif
  640. /*
  641. * Do not mess casually with the number of decimal digits in the
  642. * format! Most GPSes report over serial links at 0.01s or 0.001s
  643. * precision. Round to 0.001s
  644. */
  645. fracsec = (fixtime.tv_nsec + 500000) / 1000000;
  646. (void)strftime(timestr, sizeof(timestr), "%Y-%m-%dT%H:%M:%S", &when);
  647. (void)snprintf(isotime, len, "%s.%03ldZ",timestr, fracsec);
  648. return isotime;
  649. }
  650. /* return time now as ISO8601, no timezone adjustment */
  651. /* example: 2007-12-11T23:38:51.033Z */
  652. char *now_to_iso8601(char *tbuf, size_t tbuf_sz)
  653. {
  654. timespec_t ts_now;
  655. (void)clock_gettime(CLOCK_REALTIME, &ts_now);
  656. return timespec_to_iso8601(ts_now, tbuf, tbuf_sz);
  657. }
  658. #define Deg2Rad(n) ((n) * DEG_2_RAD)
  659. /* Distance in meters between two points specified in degrees, optionally
  660. * with initial and final bearings. */
  661. double earth_distance_and_bearings(double lat1, double lon1,
  662. double lat2, double lon2,
  663. double *ib, double *fb)
  664. {
  665. /*
  666. * this is a translation of the javascript implementation of the
  667. * Vincenty distance formula by Chris Veness. See
  668. * http://www.movable-type.co.uk/scripts/latlong-vincenty.html
  669. */
  670. double a, b, f; // WGS-84 ellipsoid params
  671. double L, L_P, U1, U2, s_U1, c_U1, s_U2, c_U2;
  672. double uSq, A, B, d_S, lambda;
  673. // cppcheck-suppress variableScope
  674. double s_L, c_L, s_A, C;
  675. double c_S, S, s_S, c_SqA, c_2SM;
  676. int i = 100;
  677. a = WGS84A;
  678. b = WGS84B;
  679. f = 1 / WGS84F;
  680. L = Deg2Rad(lon2 - lon1);
  681. U1 = atan((1 - f) * tan(Deg2Rad(lat1)));
  682. U2 = atan((1 - f) * tan(Deg2Rad(lat2)));
  683. s_U1 = sin(U1);
  684. c_U1 = cos(U1);
  685. s_U2 = sin(U2);
  686. c_U2 = cos(U2);
  687. lambda = L;
  688. do {
  689. s_L = sin(lambda);
  690. c_L = cos(lambda);
  691. s_S = sqrt((c_U2 * s_L) * (c_U2 * s_L) +
  692. (c_U1 * s_U2 - s_U1 * c_U2 * c_L) *
  693. (c_U1 * s_U2 - s_U1 * c_U2 * c_L));
  694. if (s_S == 0)
  695. return 0;
  696. c_S = s_U1 * s_U2 + c_U1 * c_U2 * c_L;
  697. S = atan2(s_S, c_S);
  698. s_A = c_U1 * c_U2 * s_L / s_S;
  699. c_SqA = 1 - s_A * s_A;
  700. c_2SM = c_S - 2 * s_U1 * s_U2 / c_SqA;
  701. if (0 == isfinite(c_2SM))
  702. c_2SM = 0;
  703. C = f / 16 * c_SqA * (4 + f * (4 - 3 * c_SqA));
  704. L_P = lambda;
  705. lambda = L + (1 - C) * f * s_A *
  706. (S + C * s_S * (c_2SM + C * c_S * (2 * c_2SM * c_2SM - 1)));
  707. } while ((fabs(lambda - L_P) > 1.0e-12) && (--i > 0));
  708. if (i == 0)
  709. return NAN; // formula failed to converge
  710. uSq = c_SqA * ((a * a) - (b * b)) / (b * b);
  711. A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
  712. B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
  713. d_S = B * s_S * (c_2SM + B / 4 *
  714. (c_S * (-1 + 2 * c_2SM * c_2SM) - B / 6 * c_2SM *
  715. (-3 + 4 * s_S * s_S) * (-3 + 4 * c_2SM * c_2SM)));
  716. if (ib != NULL)
  717. *ib = atan2(c_U2 * sin(lambda), c_U1 * s_U2 - s_U1 * c_U2 * cos(lambda));
  718. if (fb != NULL)
  719. *fb = atan2(c_U1 * sin(lambda), c_U1 * s_U2 * cos(lambda) - s_U1 * c_U2);
  720. return (WGS84B * A * (S - d_S));
  721. }
  722. /* Distance in meters between two points specified in degrees. */
  723. double earth_distance(double lat1, double lon1, double lat2, double lon2)
  724. {
  725. return earth_distance_and_bearings(lat1, lon1, lat2, lon2, NULL, NULL);
  726. }
  727. // Wait for data until timeout, ignoring signals.
  728. bool nanowait(int fd, struct timespec *to)
  729. {
  730. fd_set fdset;
  731. FD_ZERO(&fdset);
  732. FD_SET(fd, &fdset);
  733. TS_NORM(to); // just in case
  734. // sigmask is NULL, so equivalent to select()
  735. return pselect(fd + 1, &fdset, NULL, NULL, to, NULL) == 1;
  736. }
  737. /* Accept a datum code, return matching string
  738. *
  739. * There are a ton of these, only a few are here
  740. *
  741. */
  742. void datum_code_string(int code, char *buffer, size_t len)
  743. {
  744. const char *datum_str;
  745. switch (code) {
  746. case 0:
  747. datum_str = "WGS84";
  748. break;
  749. case 21:
  750. datum_str = "WGS84";
  751. break;
  752. case 178:
  753. datum_str = "Tokyo Mean";
  754. break;
  755. case 179:
  756. datum_str = "Tokyo-Japan";
  757. break;
  758. case 180:
  759. datum_str = "Tokyo-Korea";
  760. break;
  761. case 181:
  762. datum_str = "Tokyo-Okinawa";
  763. break;
  764. case 182:
  765. datum_str = "PZ90.11";
  766. break;
  767. case 999:
  768. datum_str = "User Defined";
  769. break;
  770. default:
  771. datum_str = NULL;
  772. break;
  773. }
  774. if (NULL == datum_str) {
  775. /* Fake it */
  776. snprintf(buffer, len, "%d", code);
  777. } else {
  778. strlcpy(buffer, datum_str, len);
  779. }
  780. }
  781. /* end */
  782. // vim: set expandtab shiftwidth=4