35 return n->
data[offset];
45 int8_t v = (u & 0x7F);
46 if (u & 0x80) { v = -1 * ((1 << 7) - v); }
57 int16_t v = (u & 0x7FFF);
58 if (u & 0x8000) { v = -1 * ((1 << 15) - v); }
68 return n->
data[offset] + (n->
data[offset + 1] << 8);
78 int32_t v = (u & 0x7FFFFFFFUL);
79 if (u & 0x80000000UL) { v = -1 * ((1UL << 31) - v); }
89 uint32_t v = n->
data[offset] + ((uint32_t)(n->
data[offset + 1]) << 8) +
90 ((uint32_t)(n->
data[offset + 2]) << 16) + ((uint32_t)(n->
data[offset + 3]) << 24);
101 int64_t v = (u & 0x7FFFFFFFFFFFFFFFULL);
102 if (u & 0x8000000000000000ULL) { v = -1 * ((1ULL << 63) - v); }
112 uint64_t v = n->
data[offset] + ((uint64_t)(n->
data[offset + 1]) << 8) +
113 ((uint64_t)(n->
data[offset + 2]) << 16) + ((uint64_t)(n->
data[offset + 3]) << 24) +
114 ((uint64_t)(n->
data[offset + 4]) << 32) + ((uint64_t)(n->
data[offset + 5]) << 40) +
115 ((uint64_t)(n->
data[offset + 6]) << 48) + ((uint64_t)(n->
data[offset + 7]) << 56);
129 if (v == INT8_MAX || v == INT8_MIN) {
return NAN; }
131 }
else if (size == 16) {
133 if (v == INT16_MAX || v == INT16_MIN) {
return NAN; }
135 }
else if (size == 32) {
137 if (v == INT32_MAX || v == INT32_MIN) {
return NAN; }
139 }
else if (size == 64) {
141 if (v == INT64_MAX || v == INT64_MIN) {
return NAN; }
157 if (v == UINT8_MAX) {
return NAN; }
159 }
else if (size == 16) {
161 if (v == UINT16_MAX) {
return NAN; }
163 }
else if (size == 32) {
165 if (v == UINT32_MAX) {
return NAN; }
167 }
else if (size == 64) {
169 if (v == UINT64_MAX) {
return NAN; }
188 uint8_t *sys, uint8_t *ind,
bool *cfg) {
189 if (!n || n->
PGN != 60928 || !n->
data || n->
datalen < 8) {
return false; }
197 if (cfg) { (*cfg) = (si & 0x80) == 0x80; }
198 if (ind) { (*ind) = (si & 0x70) >> 4; }
199 if (sys) { (*sys) = (si & 0x0F); }
213 if (!n || n->
PGN != 127250 || !n->
data || n->
datalen < 8) {
return false; }
220 success &= isfinite((*hdg));
225 success &= isfinite((*dev));
229 success &= isfinite((*var));
244 if (!n || n->
PGN != 127251 || !n->
data || n->
datalen < 8) {
return false; }
250 if (!isfinite((*rate))) {
return false; }
265 if (!n || n->
PGN != 127257 || !n->
data || n->
datalen < 7) {
return false; }
270 success &= isfinite(*yaw);
274 success &= isfinite(*pitch);
278 success &= isfinite(*roll);
292 if (!n || n->
PGN != 128267 || !n->
data || n->
datalen < 8) {
return false; }
299 success &= isfinite((*depth));
304 success &= isfinite((*offset));
308 success &= isfinite((*range));
321 if (!n || n->
PGN != 129025 || !n->
data || n->
datalen < 8) {
return false; }
325 success &= isfinite((*lat));
329 success &= isfinite((*lon));
343 if (!n || n->
PGN != 129026 || !n->
data || n->
datalen < 8) {
return false; }
350 success &= isfinite((*course));
354 success &= isfinite((*speed));
381 double *lon,
double *alt, uint8_t *type, uint8_t *method, uint8_t *integ, uint8_t *nsv,
382 double *hdop,
double *pdop,
double *geos, uint8_t *rs, uint8_t *rst, uint16_t *rsid,
384 if (!n || n->
PGN != 129029 || !n->
data || n->
datalen < 43) {
return false; }
390 success &= isfinite((*seconds));
395 success &= isfinite((*lat));
400 success &= isfinite((*lon));
405 success &= isfinite((*alt));
409 if (type) { (*type) = (tm & 0x0F); }
410 if (method) { (*method) = (tm & 0xF0) >> 4; }
411 if (integ) { (*integ) = (
n2k_get_uint8(n, 32) & 0xC0) >> 12; }
416 success &= isfinite((*hdop));
421 success &= isfinite((*pdop));
426 success &= isfinite((*geos));
431 if (rst) { (*rst) = rsdetails & 0x000F; }
432 if (rsid) { (*rsid) = (rsdetails & 0xFFF0) >> 4; }
434 if (dgnssa && n->
datalen >= 45) {
436 success &= isfinite((*dgnssa));
449 if (!n || n->
PGN != 129033 || !n->
data || n->
datalen < 8) {
return false; }
454 if ((*utcMins >= 1440) || (*utcMins <= -1440)) {
471 if (!n || n->
PGN != 130306 || !n->
data || n->
datalen < 8) {
return false; }
480 success &= isfinite((*speed));
485 success &= isfinite((*angle));
503 if (!n || n->
PGN != 130311 || !n->
data || n->
datalen < 8) {
return false; }
509 if (tid) { (*tid) = ids & 0x3F; }
510 if (hid) { (*hid) = (ids & 0xC0) >> 6; }
513 success &= isfinite((*temp));
517 success &= (isfinite((*humid)) || ((*hid) == 3));
521 success &= isfinite((*press));
531 uint8_t instance = 0;
532 uint8_t
function = 0;
535 uint8_t industry = 0;
536 bool configurable =
false;
538 fprintf(stdout,
"%.3f\t", (
float)(n->
timestamp / 1000.0));
539 if (!
n2k_60928_values(n, &
id, &mfr, &instance, &
function, &
class, &system, &industry, &configurable)) {
540 fprintf(stdout,
"[!] ");
542 fprintf(stdout,
"Address claim - ID: %08u, Manufacturer: %05u\n",
id, mfr);
551 if (d) { delim = d; }
552 fprintf(stdout,
"%.3f\t", (
float)(n->
timestamp / 1000.0));
554 fprintf(stdout,
"PGN %06d broadcast from %03d%c", n->
PGN, n->
src, delim);
556 fprintf(stdout,
"PGN %06d sent from %03d to %03d%c", n->
PGN, n->
src, n->
dst, delim);
566 fprintf(stdout,
"-- Not parsed --\n");
582 if (!
n2k_127250_values(n, &seq, &hdg, &dev, &var, &ref)) { fprintf(stdout,
"[!] "); }
593 magStr =
"Unknown Reference";
597 fprintf(stdout,
"Heading: %.3lf [%s], Deviation: %+.3lf, Variation: %+.3lf. Seq. ID %03d\n", hdg, magStr, dev,
612 fprintf(stdout,
"Rate of turn: %+.3lf. Seq. ID %03d\n", rot, seq);
627 if (!
n2k_127257_values(n, &seq, &yaw, &pitch, &roll)) { fprintf(stdout,
"[!] "); }
629 fprintf(stdout,
"Pitch: %.3lf, Roll: %.3lf, Yaw: %.3lf. Seq. ID: %03d\n", pitch, roll, yaw, seq);
644 if (!
n2k_128267_values(n, &seq, &depth, &offset, &range)) { fprintf(stdout,
"[!] "); }
646 fprintf(stdout,
"Water Depth: %.2lfm (Offset: %.2lf, Range: %.0lf) Seq. ID %03d\n", depth, offset, range, seq);
661 fprintf(stdout,
"GPS Position: %lf, %lf\n", lat, lon);
671 uint8_t magnetic = 0;
676 if (!
n2k_129026_values(n, &seq, &magnetic, &course, &speed)) { fprintf(stdout,
"[!] "); }
687 magStr =
"Unknown Reference";
691 fprintf(stdout,
"Speed: %.2lf @ %.3lf degrees [%s]. Seq. ID %03d\n", speed, course, magStr, seq);
710 uint8_t integrity = 0;
725 if (!
n2k_129029_values(n, &seq, &days, &secs, &lat, &lon, &alt, &type, &method, &integrity, &numSV, &hdop,
726 &pdop, &geos, &rs, &rsType, &rsID, &dgnssa)) {
727 fprintf(stdout,
"[!] ");
730 "Position: (%+.10lf,%+.10lf), Altitude: %.4lf m. %d SVs in use. HDOP %+.2lf, PDOP %+.2lf, Geoid Sep. %+.2lf m\n",
731 lat, lon, alt, numSV, hdop, pdop, geos);
747 long timetemp = (long)(86400 * days + secs);
749 gmtime_r(&timetemp, &dt);
751 char timeS[30] = {0};
752 strftime(timeS,
sizeof(timeS),
"%F %T", &dt);
753 fprintf(stdout,
"%s %+02.2f\n", timeS, utcOff / 60.0);
768 if (!
n2k_130306_values(n, &seq, &ref, &speed, &angle)) { fprintf(stdout,
"[!] "); }
773 refStr =
"Relative to North";
782 refStr =
"Relative to boat";
785 refStr =
"Unknown reference";
789 fprintf(stdout,
"Wind Speed: %.2lf @ %.3lf degrees [%s]. Seq. ID %03d\n", speed, angle, refStr, seq);
806 if (!
n2k_130311_values(n, &seq, &tid, &hid, &t, &h, &p)) { fprintf(stdout,
"[!] "); }
820 tSrc =
"Engine Room";
839 hSrc =
"Unavailable";
846 fprintf(stdout,
"Environmental data: %+.2lfC (%s), %+.3lf%% RH (%s), %.0lf mbar. Seq ID %03d\n", t, tSrc, h,
bool n2k_127251_values(const n2k_act_message *n, uint8_t *seq, double *rate)
Extract values from PGN 127251: Rate of Turn.
void n2k_basic_print(const n2k_act_message *n)
Print basic PGN details to standard output.
void n2k_128267_print(const n2k_act_message *n)
Print PGN 128267 (Water depth) to standard output.
void n2k_129029_print(const n2k_act_message *n)
Print PGN 129029 (GNSS Position) to standard output.
void n2k_130311_print(const n2k_act_message *n)
Print PGN 130311 (Environmental data) to standard output.
void n2k_129026_print(const n2k_act_message *n)
Print PGN 129026 (Course and Speed) to standard output.
void n2k_129025_print(const n2k_act_message *n)
Print PGN 129025 (Device position) to standard output.
void n2k_130306_print(const n2k_act_message *n)
Print PGN 130306 (Wind speed and direction) to standard output.
bool n2k_130311_values(const n2k_act_message *n, uint8_t *seq, uint8_t *tid, uint8_t *hid, double *temp, double *humid, double *press)
Extract values from PGN 130311: Environmental data.
void n2k_60928_print(const n2k_act_message *n)
Print PGN 60928 (Address claim) to standard output.
bool n2k_129025_values(const n2k_act_message *n, double *lat, double *lon)
Extract values from PGN 129025: Device position.
bool n2k_130306_values(const n2k_act_message *n, uint8_t *seq, uint8_t *ref, double *speed, double *angle)
Extract values from PGN 130306: Wind speed and direction.
void n2k_127250_print(const n2k_act_message *n)
Print PGN 127250 (Vessel Heading) to standard output.
void n2k_header_print(const n2k_act_message *n, const char d)
Print common message elements.
bool n2k_129029_values(const n2k_act_message *n, uint8_t *seq, uint16_t *epochDays, double *seconds, double *lat, double *lon, double *alt, uint8_t *type, uint8_t *method, uint8_t *integ, uint8_t *nsv, double *hdop, double *pdop, double *geos, uint8_t *rs, uint8_t *rst, uint16_t *rsid, double *dgnssa)
Extract values from PGN 129029: GNSS Position.
void n2k_127251_print(const n2k_act_message *n)
Print PGN 127251 (Rate of Turn) to standard output.
bool n2k_127250_values(const n2k_act_message *n, uint8_t *seq, double *hdg, double *dev, double *var, uint8_t *ref)
Extract values from PGN 127250: Vessel Heading.
bool n2k_127257_values(const n2k_act_message *n, uint8_t *seq, double *yaw, double *pitch, double *roll)
Extract values from PGN 127257: Device orientation.
bool n2k_129033_values(const n2k_act_message *n, uint16_t *epochDays, double *seconds, int16_t *utcMins)
Extract values from PGN 129033: Date/Time.
bool n2k_128267_values(const n2k_act_message *n, uint8_t *seq, double *depth, double *offset, double *range)
Extract values from PGN 128267: Water depth.
void n2k_127257_print(const n2k_act_message *n)
Print PGN 127257 (Device orientation) to standard output.
bool n2k_129026_values(const n2k_act_message *n, uint8_t *seq, uint8_t *mag, double *course, double *speed)
Extract values from PGN 129026: Course and speed.
bool n2k_60928_values(const n2k_act_message *n, uint32_t *id, uint16_t *mfr, uint8_t *inst, uint8_t *fn, uint8_t *class, uint8_t *sys, uint8_t *ind, bool *cfg)
Extract values from PGN 60928: ISO Adddress Claim.
void n2k_129033_print(const n2k_act_message *n)
Print PGN 129033 (Date and Time) to standard output.
#define N2K_TO_DEGREES
Convert raw angular value to degrees.
uint16_t n2k_get_uint16(const n2k_act_message *n, size_t offset)
Extract unsigned 16-bit integer from N2K Message.
int16_t n2k_get_int16(const n2k_act_message *n, size_t offset)
Extract signed 16-bit integer from N2K Message.
double n2k_get_double(const n2k_act_message *n, size_t offset, uint8_t size)
Extract double from underlying integer data.
double n2k_get_udouble(const n2k_act_message *n, size_t offset, uint8_t size)
Extract double from underlying unsigned integer data.
int8_t n2k_get_int8(const n2k_act_message *n, size_t offset)
Extract signed byte from N2K Message.
uint32_t n2k_get_uint32(const n2k_act_message *n, size_t offset)
Extract unsigned 32-bit integer from N2K Message.
uint64_t n2k_get_uint64(const n2k_act_message *n, size_t offset)
Extract unsigned 64-bit integer from N2K Message.
int64_t n2k_get_int64(const n2k_act_message *n, size_t offset)
Extract signed 64-bit integer from N2K Message.
int32_t n2k_get_int32(const n2k_act_message *n, size_t offset)
Extract signed 32-bit integer from N2K Message.
uint8_t n2k_get_uint8(const n2k_act_message *n, size_t offset)
Extract unsigned byte from N2K Message.
uint32_t PGN
24 bit PGN identifier
uint8_t * data
Message payload.
uint8_t datalen
Length of *data.
uint8_t dst
Message destination.
uint32_t timestamp
Message timestamp.
uint8_t src
Message source.