123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328 |
- /*
- * Encode AIS messages.
- *
- * See the file AIVDM.txt on the GPSD website for documentation and references.
- *
- * This file is build from driver_ais.c
- *
- * This file is Copyright 2013 by the GPSD project
- * SPDX-License-Identifier: BSD-2-clause
- */
- #include "gpsd_config.h" /* must be before all includes */
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "gpsd.h"
- #include "bits.h"
- #include <stdint.h>
- #ifdef AIVDM_ENABLE
- #define AIS_MSG_PART2_FLAG 0x100
- static unsigned char convtab[] = {"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW`abcdefghijklmnopqrstuvw"};
- static unsigned char contab1[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
- 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
- static void ais_addbits(unsigned char *bits,
- unsigned int start,
- unsigned int len,
- uint64_t data)
- {
- unsigned int l;
- unsigned int pos;
- uint64_t mask;
- unsigned int mask1;
- mask = 0x1;
- pos = (start+len-1) / 6;
- mask1 = 0x20;
- mask1 = mask1 >> ((start+len-1) % 6);
- if (len == 0) {
- return;
- }
- for(l=0;l<len;l++) {
- if (data & mask) {
- bits[pos] |= mask1;
- }
- mask <<= 1;
- mask1 <<= 1;
- if (mask1 == 0x40) {
- pos -= 1;
- mask1 = 0x1;
- }
- }
- return;
- }
- static void ais_addchar(unsigned char *bits,
- unsigned int start,
- unsigned int len,
- char *data)
- {
- unsigned int l;
- unsigned int flag;
- for(l=0,flag=0;l<len;l++) {
- unsigned char a, b;
- a = (unsigned char) data[l];
- if (a == (unsigned char)'\0') {
- flag = 1;
- }
- if (flag == 0) {
- b = contab1[a & 0x7f];
- } else {
- b = (unsigned char) '\0';
- }
- ais_addbits(bits, start+6*l, 6, (uint64_t)b);
- }
- return;
- }
- static void ais_adddata(unsigned char *bits,
- unsigned int start,
- unsigned int len,
- char *data)
- {
- unsigned int l;
- for(l=0;l<len;l++) {
- ais_addbits(bits, start+6*l, 6, (uint64_t)data[l]);
- }
- return;
- }
- static void ais_binary_to_ascii(unsigned char *bits, unsigned int len)
- {
- unsigned int l;
- if (len == 0) {
- bits[0] = '\0';
- return;
- }
- for (l=0;l<len;l+=6) {
- bits[l/6] = convtab[bits[l/6] & 0x3f];
- }
- return;
- }
- unsigned int ais_binary_encode(struct ais_t *ais,
- unsigned char *bits,
- int flag)
- {
- unsigned int len;
- len = 0;
- if (flag != 0) {
- flag = AIS_MSG_PART2_FLAG;
- }
- ais_addbits(bits, 0, 6, (uint64_t)ais->type);
- ais_addbits(bits, 6, 2, (uint64_t)ais->repeat);
- ais_addbits(bits, 8, 30, (uint64_t)ais->mmsi);
- switch (flag | ais->type) {
- case 1: /* Position Report */
- case 2:
- case 3:
- ais_addbits(bits, 38, 4, (uint64_t)ais->type1.status);
- ais_addbits(bits, 42, 8, (uint64_t)ais->type1.turn);
- ais_addbits(bits, 50, 10, (uint64_t)ais->type1.speed);
- ais_addbits(bits, 60, 1, (uint64_t)ais->type1.accuracy);
- ais_addbits(bits, 61, 28, (uint64_t)ais->type1.lon);
- ais_addbits(bits, 89, 27, (uint64_t)ais->type1.lat);
- ais_addbits(bits, 116, 12, (uint64_t)ais->type1.course);
- ais_addbits(bits, 128, 9, (uint64_t)ais->type1.heading);
- ais_addbits(bits, 137, 6, (uint64_t)ais->type1.second);
- ais_addbits(bits, 143, 2, (uint64_t)ais->type1.maneuver);
- /* ais_addbits(bits, 145, 3, (uint64_t)ais->type1.spare); */
- ais_addbits(bits, 148, 1, (uint64_t)ais->type1.raim);
- ais_addbits(bits, 149, 19, (uint64_t)ais->type1.radio);
- len = 149 + 19;
- break;
- case 4: /* Base Station Report */
- case 11: /* UTC/Date Response */
- ais_addbits(bits, 38, 14, (uint64_t)ais->type4.year);
- ais_addbits(bits, 52, 4, (uint64_t)ais->type4.month);
- ais_addbits(bits, 56, 5, (uint64_t)ais->type4.day);
- ais_addbits(bits, 61, 5, (uint64_t)ais->type4.hour);
- ais_addbits(bits, 66, 6, (uint64_t)ais->type4.minute);
- ais_addbits(bits, 72, 6, (uint64_t)ais->type4.second);
- ais_addbits(bits, 78, 1, (uint64_t)ais->type4.accuracy);
- ais_addbits(bits, 79, 28, (uint64_t)ais->type4.lon);
- ais_addbits(bits, 107, 27, (uint64_t)ais->type4.lat);
- ais_addbits(bits, 134, 4, (uint64_t)ais->type4.epfd);
- /* ais_addbits(bits, 138, 10, (uint64_t)ais->type4.spare); */
- ais_addbits(bits, 148, 1, (uint64_t)ais->type4.raim);
- ais_addbits(bits, 149, 19, (uint64_t)ais->type4.radio);
- len = 149 + 19;
- break;
- case 5: /* Ship static and voyage related data */
- ais_addbits(bits, 38, 2, (uint64_t)ais->type5.ais_version);
- ais_addbits(bits, 40, 30, (uint64_t)ais->type5.imo);
- ais_addchar(bits, 70, 7, ais->type5.callsign);
- ais_addchar(bits, 112, 20, ais->type5.shipname);
- ais_addbits(bits, 232, 8, (uint64_t)ais->type5.shiptype);
- ais_addbits(bits, 240, 9, (uint64_t)ais->type5.to_bow);
- ais_addbits(bits, 249, 9, (uint64_t)ais->type5.to_stern);
- ais_addbits(bits, 258, 6, (uint64_t)ais->type5.to_port);
- ais_addbits(bits, 264, 6, (uint64_t)ais->type5.to_starboard);
- ais_addbits(bits, 270, 4, (uint64_t)ais->type5.epfd);
- ais_addbits(bits, 274, 4, (uint64_t)ais->type5.month);
- ais_addbits(bits, 278, 5, (uint64_t)ais->type5.day);
- ais_addbits(bits, 283, 5, (uint64_t)ais->type5.hour);
- ais_addbits(bits, 288, 6, (uint64_t)ais->type5.minute);
- ais_addbits(bits, 294, 8, (uint64_t)ais->type5.draught);
- ais_addchar(bits, 302, 20, ais->type5.destination);
- ais_addbits(bits, 422, 1, (uint64_t)ais->type5.dte);
- /* ais_addbits(bits, 423, 1, (uint64_t)ais->type5.spare); */
- len = 423 + 1;
- break;
- case 9: /* Standard SAR Aircraft Position Report */
- ais_addbits(bits, 38, 12, (uint64_t)ais->type9.alt);
- ais_addbits(bits, 50, 10, (uint64_t)ais->type9.speed);
- ais_addbits(bits, 60, 1, (uint64_t)ais->type9.accuracy);
- ais_addbits(bits, 61, 28, (uint64_t)ais->type9.lon);
- ais_addbits(bits, 89, 27, (uint64_t)ais->type9.lat);
- ais_addbits(bits, 116, 12, (uint64_t)ais->type9.course);
- ais_addbits(bits, 128, 6, (uint64_t)ais->type9.second);
- ais_addbits(bits, 134, 8, (uint64_t)ais->type9.regional);
- ais_addbits(bits, 142, 1, (uint64_t)ais->type9.dte);
- /* ais_addbits(bits, 143, 3, (uint64_t)ais->type9.spare); */
- ais_addbits(bits, 146, 1, (uint64_t)ais->type9.assigned);
- ais_addbits(bits, 147, 1, (uint64_t)ais->type9.raim);
- ais_addbits(bits, 148, 19, (uint64_t)ais->type9.radio);
- len = 148 + 19;
- break;
- case 18: /* Standard Class B CS Position Report */
- ais_addbits(bits, 38, 8, (uint64_t)ais->type18.reserved);
- ais_addbits(bits, 46, 10, (uint64_t)ais->type18.speed);
- ais_addbits(bits, 56, 1, (uint64_t)ais->type18.accuracy);
- ais_addbits(bits, 57, 28, (uint64_t)ais->type18.lon);
- ais_addbits(bits, 85, 27, (uint64_t)ais->type18.lat);
- ais_addbits(bits, 112, 12, (uint64_t)ais->type18.course);
- ais_addbits(bits, 124, 9, (uint64_t)ais->type18.heading);
- ais_addbits(bits, 133, 6, (uint64_t)ais->type18.second);
- ais_addbits(bits, 139, 2, (uint64_t)ais->type18.regional);
- ais_addbits(bits, 141, 1, (uint64_t)ais->type18.cs);
- ais_addbits(bits, 142, 1, (uint64_t)ais->type18.display);
- ais_addbits(bits, 143, 1, (uint64_t)ais->type18.dsc);
- ais_addbits(bits, 144, 1, (uint64_t)ais->type18.band);
- ais_addbits(bits, 145, 1, (uint64_t)ais->type18.msg22);
- ais_addbits(bits, 146, 1, (uint64_t)ais->type18.assigned);
- ais_addbits(bits, 147, 1, (uint64_t)ais->type18.raim);
- ais_addbits(bits, 148, 20, (uint64_t)ais->type18.radio);
- len = 148 + 20;
- break;
- case 19: /* Extended Class B CS Position Report */
- ais_addbits(bits, 38, 8, (uint64_t)ais->type19.reserved);
- ais_addbits(bits, 46, 10, (uint64_t)ais->type19.speed);
- ais_addbits(bits, 56, 1, (uint64_t)ais->type19.accuracy);
- ais_addbits(bits, 57, 28, (uint64_t)ais->type19.lon);
- ais_addbits(bits, 85, 27, (uint64_t)ais->type19.lat);
- ais_addbits(bits, 112, 12, (uint64_t)ais->type19.course);
- ais_addbits(bits, 124, 9, (uint64_t)ais->type19.heading);
- ais_addbits(bits, 133, 6, (uint64_t)ais->type19.second);
- ais_addbits(bits, 139, 4, (uint64_t)ais->type19.regional);
- ais_addchar(bits, 143, 20, ais->type19.shipname);
- ais_addbits(bits, 263, 8, (uint64_t)ais->type19.shiptype);
- ais_addbits(bits, 271, 9, (uint64_t)ais->type19.to_bow);
- ais_addbits(bits, 280, 9, (uint64_t)ais->type19.to_stern);
- ais_addbits(bits, 289, 6, (uint64_t)ais->type19.to_port);
- ais_addbits(bits, 295, 6, (uint64_t)ais->type19.to_starboard);
- ais_addbits(bits, 299, 4, (uint64_t)ais->type19.epfd);
- ais_addbits(bits, 302, 1, (uint64_t)ais->type19.raim);
- ais_addbits(bits, 305, 1, (uint64_t)ais->type19.dte);
- ais_addbits(bits, 306, 1, (uint64_t)ais->type19.assigned);
- /* ais_addbits(bits, 307, 5, (uint64_t)ais->type19.spare); */
- len = 307 + 5;
- break;
- case 21: /* Aid-to-Navigation Report */
- ais_addbits(bits, 38, 5, (uint64_t)ais->type21.aid_type);
- ais_addchar(bits, 43, 20, ais->type21.name);
- ais_addbits(bits, 163, 1, (uint64_t)ais->type21.accuracy);
- ais_addbits(bits, 164, 28, (uint64_t)ais->type21.lon);
- ais_addbits(bits, 192, 27, (uint64_t)ais->type21.lat);
- ais_addbits(bits, 219, 9, (uint64_t)ais->type21.to_bow);
- ais_addbits(bits, 228, 9, (uint64_t)ais->type21.to_stern);
- ais_addbits(bits, 237, 6, (uint64_t)ais->type21.to_port);
- ais_addbits(bits, 243, 6, (uint64_t)ais->type21.to_starboard);
- ais_addbits(bits, 249, 4, (uint64_t)ais->type21.epfd);
- ais_addbits(bits, 253, 6, (uint64_t)ais->type21.second);
- ais_addbits(bits, 259, 1, (uint64_t)ais->type21.off_position);
- ais_addbits(bits, 260, 8, (uint64_t)ais->type21.regional);
- ais_addbits(bits, 268, 1, (uint64_t)ais->type21.raim);
- ais_addbits(bits, 269, 1, (uint64_t)ais->type21.virtual_aid);
- ais_addbits(bits, 270, 1, (uint64_t)ais->type21.assigned);
- /* ais_addbits(bits, 271, 1, (uint64_t)ais->type21.spare); */
- len = 271 + 1;
- if (strlen(ais->type21.name) > 20) {
- unsigned int extralen;
- extralen = (unsigned int)(strlen(ais->type21.name) - 20);
- ais_addchar(bits, 272, extralen, ais->type21.name + 20);
- len += extralen * 6;
- }
- break;
- case 24: /* Class B CS Static Data Report Part 1 */
- if (ais->type24.part == part_a) {
- ais_addbits(bits, 38, 2, (uint64_t)0);
- ais_addchar(bits, 40, 20, ais->type24.shipname);
- /* ais_addbits(bits, 160, 8, (uint64_t)ais->type24.a.spare); */
- len = 160;
- }
- break;
- case 24 | AIS_MSG_PART2_FLAG: /* Class B CS Static Data Report Part 2 */
- if ((ais->type24.part == part_b) || (ais->type24.part == both)) {
- ais_addbits(bits, 38, 2, (uint64_t)1);
- ais_addbits(bits, 40, 8, (uint64_t)ais->type24.shiptype);
- ais_addchar(bits, 48, 3, &ais->type24.vendorid[0]);
- ais_adddata(bits, 66, 3, &ais->type24.vendorid[3]);
- ais_addchar(bits, 90, 7, ais->type24.callsign);
- if (AIS_AUXILIARY_MMSI(ais->mmsi)) {
- ais_addbits(bits, 132, 30,
- (uint64_t)ais->type24.mothership_mmsi);
- } else {
- ais_addbits(bits, 132, 9, (uint64_t)ais->type24.dim.to_bow);
- ais_addbits(bits, 141, 9, (uint64_t)ais->type24.dim.to_stern);
- ais_addbits(bits, 150, 6, (uint64_t)ais->type24.dim.to_port);
- ais_addbits(bits, 156, 6,
- (uint64_t)ais->type24.dim.to_starboard);
- }
- /* ais_addbits(bits, 162, 6, ais->type24.b.spare); */
- len = 162 + 6;
- }
- break;
- case 27: /* Long Range AIS Broadcast message */
- ais_addbits(bits, 38, 1, (uint64_t)ais->type27.accuracy);
- ais_addbits(bits, 39, 1, (uint64_t)ais->type27.raim);
- ais_addbits(bits, 40, 4, (uint64_t)ais->type27.status);
- ais_addbits(bits, 44, 18, (uint64_t)ais->type27.lon);
- ais_addbits(bits, 62, 17, (uint64_t)ais->type27.lat);
- ais_addbits(bits, 79, 6, (uint64_t)ais->type27.speed);
- ais_addbits(bits, 85, 9, (uint64_t)ais->type27.course);
- ais_addbits(bits, 94, 1, (uint64_t)ais->type27.gnss);
- break;
- }
- ais_binary_to_ascii(bits, len);
- return len;
- }
- #endif /* AIVDM_ENABLE */
- // vim: set expandtab shiftwidth=4
|