pseudoais.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*
  2. * Encode AIS messages.
  3. *
  4. * See the file AIVDM.txt on the GPSD website for documentation and references.
  5. *
  6. * This file is build from driver_ais.c
  7. *
  8. * This file is Copyright 2013 by the GPSD project
  9. * SPDX-License-Identifier: BSD-2-clause
  10. */
  11. #include "gpsd_config.h" /* must be before all includes */
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #include "gpsd.h"
  16. #include "bits.h"
  17. #include <stdint.h>
  18. #ifdef AIVDM_ENABLE
  19. #define AIS_MSG_PART2_FLAG 0x100
  20. static unsigned char convtab[] = {"0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW`abcdefghijklmnopqrstuvw"};
  21. static unsigned char contab1[] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  22. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  23. 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
  24. 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
  25. 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
  26. 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
  27. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  28. 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
  29. static void ais_addbits(unsigned char *bits,
  30. unsigned int start,
  31. unsigned int len,
  32. uint64_t data)
  33. {
  34. unsigned int l;
  35. unsigned int pos;
  36. uint64_t mask;
  37. unsigned int mask1;
  38. mask = 0x1;
  39. pos = (start+len-1) / 6;
  40. mask1 = 0x20;
  41. mask1 = mask1 >> ((start+len-1) % 6);
  42. if (len == 0) {
  43. return;
  44. }
  45. for(l=0;l<len;l++) {
  46. if (data & mask) {
  47. bits[pos] |= mask1;
  48. }
  49. mask <<= 1;
  50. mask1 <<= 1;
  51. if (mask1 == 0x40) {
  52. pos -= 1;
  53. mask1 = 0x1;
  54. }
  55. }
  56. return;
  57. }
  58. static void ais_addchar(unsigned char *bits,
  59. unsigned int start,
  60. unsigned int len,
  61. char *data)
  62. {
  63. unsigned int l;
  64. unsigned int flag;
  65. for(l=0,flag=0;l<len;l++) {
  66. unsigned char a, b;
  67. a = (unsigned char) data[l];
  68. if (a == (unsigned char)'\0') {
  69. flag = 1;
  70. }
  71. if (flag == 0) {
  72. b = contab1[a & 0x7f];
  73. } else {
  74. b = (unsigned char) '\0';
  75. }
  76. ais_addbits(bits, start+6*l, 6, (uint64_t)b);
  77. }
  78. return;
  79. }
  80. static void ais_adddata(unsigned char *bits,
  81. unsigned int start,
  82. unsigned int len,
  83. char *data)
  84. {
  85. unsigned int l;
  86. for(l=0;l<len;l++) {
  87. ais_addbits(bits, start+6*l, 6, (uint64_t)data[l]);
  88. }
  89. return;
  90. }
  91. static void ais_binary_to_ascii(unsigned char *bits, unsigned int len)
  92. {
  93. unsigned int l;
  94. if (len == 0) {
  95. bits[0] = '\0';
  96. return;
  97. }
  98. for (l=0;l<len;l+=6) {
  99. bits[l/6] = convtab[bits[l/6] & 0x3f];
  100. }
  101. return;
  102. }
  103. unsigned int ais_binary_encode(struct ais_t *ais,
  104. unsigned char *bits,
  105. int flag)
  106. {
  107. unsigned int len;
  108. len = 0;
  109. if (flag != 0) {
  110. flag = AIS_MSG_PART2_FLAG;
  111. }
  112. ais_addbits(bits, 0, 6, (uint64_t)ais->type);
  113. ais_addbits(bits, 6, 2, (uint64_t)ais->repeat);
  114. ais_addbits(bits, 8, 30, (uint64_t)ais->mmsi);
  115. switch (flag | ais->type) {
  116. case 1: /* Position Report */
  117. case 2:
  118. case 3:
  119. ais_addbits(bits, 38, 4, (uint64_t)ais->type1.status);
  120. ais_addbits(bits, 42, 8, (uint64_t)ais->type1.turn);
  121. ais_addbits(bits, 50, 10, (uint64_t)ais->type1.speed);
  122. ais_addbits(bits, 60, 1, (uint64_t)ais->type1.accuracy);
  123. ais_addbits(bits, 61, 28, (uint64_t)ais->type1.lon);
  124. ais_addbits(bits, 89, 27, (uint64_t)ais->type1.lat);
  125. ais_addbits(bits, 116, 12, (uint64_t)ais->type1.course);
  126. ais_addbits(bits, 128, 9, (uint64_t)ais->type1.heading);
  127. ais_addbits(bits, 137, 6, (uint64_t)ais->type1.second);
  128. ais_addbits(bits, 143, 2, (uint64_t)ais->type1.maneuver);
  129. /* ais_addbits(bits, 145, 3, (uint64_t)ais->type1.spare); */
  130. ais_addbits(bits, 148, 1, (uint64_t)ais->type1.raim);
  131. ais_addbits(bits, 149, 19, (uint64_t)ais->type1.radio);
  132. len = 149 + 19;
  133. break;
  134. case 4: /* Base Station Report */
  135. case 11: /* UTC/Date Response */
  136. ais_addbits(bits, 38, 14, (uint64_t)ais->type4.year);
  137. ais_addbits(bits, 52, 4, (uint64_t)ais->type4.month);
  138. ais_addbits(bits, 56, 5, (uint64_t)ais->type4.day);
  139. ais_addbits(bits, 61, 5, (uint64_t)ais->type4.hour);
  140. ais_addbits(bits, 66, 6, (uint64_t)ais->type4.minute);
  141. ais_addbits(bits, 72, 6, (uint64_t)ais->type4.second);
  142. ais_addbits(bits, 78, 1, (uint64_t)ais->type4.accuracy);
  143. ais_addbits(bits, 79, 28, (uint64_t)ais->type4.lon);
  144. ais_addbits(bits, 107, 27, (uint64_t)ais->type4.lat);
  145. ais_addbits(bits, 134, 4, (uint64_t)ais->type4.epfd);
  146. /* ais_addbits(bits, 138, 10, (uint64_t)ais->type4.spare); */
  147. ais_addbits(bits, 148, 1, (uint64_t)ais->type4.raim);
  148. ais_addbits(bits, 149, 19, (uint64_t)ais->type4.radio);
  149. len = 149 + 19;
  150. break;
  151. case 5: /* Ship static and voyage related data */
  152. ais_addbits(bits, 38, 2, (uint64_t)ais->type5.ais_version);
  153. ais_addbits(bits, 40, 30, (uint64_t)ais->type5.imo);
  154. ais_addchar(bits, 70, 7, ais->type5.callsign);
  155. ais_addchar(bits, 112, 20, ais->type5.shipname);
  156. ais_addbits(bits, 232, 8, (uint64_t)ais->type5.shiptype);
  157. ais_addbits(bits, 240, 9, (uint64_t)ais->type5.to_bow);
  158. ais_addbits(bits, 249, 9, (uint64_t)ais->type5.to_stern);
  159. ais_addbits(bits, 258, 6, (uint64_t)ais->type5.to_port);
  160. ais_addbits(bits, 264, 6, (uint64_t)ais->type5.to_starboard);
  161. ais_addbits(bits, 270, 4, (uint64_t)ais->type5.epfd);
  162. ais_addbits(bits, 274, 4, (uint64_t)ais->type5.month);
  163. ais_addbits(bits, 278, 5, (uint64_t)ais->type5.day);
  164. ais_addbits(bits, 283, 5, (uint64_t)ais->type5.hour);
  165. ais_addbits(bits, 288, 6, (uint64_t)ais->type5.minute);
  166. ais_addbits(bits, 294, 8, (uint64_t)ais->type5.draught);
  167. ais_addchar(bits, 302, 20, ais->type5.destination);
  168. ais_addbits(bits, 422, 1, (uint64_t)ais->type5.dte);
  169. /* ais_addbits(bits, 423, 1, (uint64_t)ais->type5.spare); */
  170. len = 423 + 1;
  171. break;
  172. case 9: /* Standard SAR Aircraft Position Report */
  173. ais_addbits(bits, 38, 12, (uint64_t)ais->type9.alt);
  174. ais_addbits(bits, 50, 10, (uint64_t)ais->type9.speed);
  175. ais_addbits(bits, 60, 1, (uint64_t)ais->type9.accuracy);
  176. ais_addbits(bits, 61, 28, (uint64_t)ais->type9.lon);
  177. ais_addbits(bits, 89, 27, (uint64_t)ais->type9.lat);
  178. ais_addbits(bits, 116, 12, (uint64_t)ais->type9.course);
  179. ais_addbits(bits, 128, 6, (uint64_t)ais->type9.second);
  180. ais_addbits(bits, 134, 8, (uint64_t)ais->type9.regional);
  181. ais_addbits(bits, 142, 1, (uint64_t)ais->type9.dte);
  182. /* ais_addbits(bits, 143, 3, (uint64_t)ais->type9.spare); */
  183. ais_addbits(bits, 146, 1, (uint64_t)ais->type9.assigned);
  184. ais_addbits(bits, 147, 1, (uint64_t)ais->type9.raim);
  185. ais_addbits(bits, 148, 19, (uint64_t)ais->type9.radio);
  186. len = 148 + 19;
  187. break;
  188. case 18: /* Standard Class B CS Position Report */
  189. ais_addbits(bits, 38, 8, (uint64_t)ais->type18.reserved);
  190. ais_addbits(bits, 46, 10, (uint64_t)ais->type18.speed);
  191. ais_addbits(bits, 56, 1, (uint64_t)ais->type18.accuracy);
  192. ais_addbits(bits, 57, 28, (uint64_t)ais->type18.lon);
  193. ais_addbits(bits, 85, 27, (uint64_t)ais->type18.lat);
  194. ais_addbits(bits, 112, 12, (uint64_t)ais->type18.course);
  195. ais_addbits(bits, 124, 9, (uint64_t)ais->type18.heading);
  196. ais_addbits(bits, 133, 6, (uint64_t)ais->type18.second);
  197. ais_addbits(bits, 139, 2, (uint64_t)ais->type18.regional);
  198. ais_addbits(bits, 141, 1, (uint64_t)ais->type18.cs);
  199. ais_addbits(bits, 142, 1, (uint64_t)ais->type18.display);
  200. ais_addbits(bits, 143, 1, (uint64_t)ais->type18.dsc);
  201. ais_addbits(bits, 144, 1, (uint64_t)ais->type18.band);
  202. ais_addbits(bits, 145, 1, (uint64_t)ais->type18.msg22);
  203. ais_addbits(bits, 146, 1, (uint64_t)ais->type18.assigned);
  204. ais_addbits(bits, 147, 1, (uint64_t)ais->type18.raim);
  205. ais_addbits(bits, 148, 20, (uint64_t)ais->type18.radio);
  206. len = 148 + 20;
  207. break;
  208. case 19: /* Extended Class B CS Position Report */
  209. ais_addbits(bits, 38, 8, (uint64_t)ais->type19.reserved);
  210. ais_addbits(bits, 46, 10, (uint64_t)ais->type19.speed);
  211. ais_addbits(bits, 56, 1, (uint64_t)ais->type19.accuracy);
  212. ais_addbits(bits, 57, 28, (uint64_t)ais->type19.lon);
  213. ais_addbits(bits, 85, 27, (uint64_t)ais->type19.lat);
  214. ais_addbits(bits, 112, 12, (uint64_t)ais->type19.course);
  215. ais_addbits(bits, 124, 9, (uint64_t)ais->type19.heading);
  216. ais_addbits(bits, 133, 6, (uint64_t)ais->type19.second);
  217. ais_addbits(bits, 139, 4, (uint64_t)ais->type19.regional);
  218. ais_addchar(bits, 143, 20, ais->type19.shipname);
  219. ais_addbits(bits, 263, 8, (uint64_t)ais->type19.shiptype);
  220. ais_addbits(bits, 271, 9, (uint64_t)ais->type19.to_bow);
  221. ais_addbits(bits, 280, 9, (uint64_t)ais->type19.to_stern);
  222. ais_addbits(bits, 289, 6, (uint64_t)ais->type19.to_port);
  223. ais_addbits(bits, 295, 6, (uint64_t)ais->type19.to_starboard);
  224. ais_addbits(bits, 299, 4, (uint64_t)ais->type19.epfd);
  225. ais_addbits(bits, 302, 1, (uint64_t)ais->type19.raim);
  226. ais_addbits(bits, 305, 1, (uint64_t)ais->type19.dte);
  227. ais_addbits(bits, 306, 1, (uint64_t)ais->type19.assigned);
  228. /* ais_addbits(bits, 307, 5, (uint64_t)ais->type19.spare); */
  229. len = 307 + 5;
  230. break;
  231. case 21: /* Aid-to-Navigation Report */
  232. ais_addbits(bits, 38, 5, (uint64_t)ais->type21.aid_type);
  233. ais_addchar(bits, 43, 20, ais->type21.name);
  234. ais_addbits(bits, 163, 1, (uint64_t)ais->type21.accuracy);
  235. ais_addbits(bits, 164, 28, (uint64_t)ais->type21.lon);
  236. ais_addbits(bits, 192, 27, (uint64_t)ais->type21.lat);
  237. ais_addbits(bits, 219, 9, (uint64_t)ais->type21.to_bow);
  238. ais_addbits(bits, 228, 9, (uint64_t)ais->type21.to_stern);
  239. ais_addbits(bits, 237, 6, (uint64_t)ais->type21.to_port);
  240. ais_addbits(bits, 243, 6, (uint64_t)ais->type21.to_starboard);
  241. ais_addbits(bits, 249, 4, (uint64_t)ais->type21.epfd);
  242. ais_addbits(bits, 253, 6, (uint64_t)ais->type21.second);
  243. ais_addbits(bits, 259, 1, (uint64_t)ais->type21.off_position);
  244. ais_addbits(bits, 260, 8, (uint64_t)ais->type21.regional);
  245. ais_addbits(bits, 268, 1, (uint64_t)ais->type21.raim);
  246. ais_addbits(bits, 269, 1, (uint64_t)ais->type21.virtual_aid);
  247. ais_addbits(bits, 270, 1, (uint64_t)ais->type21.assigned);
  248. /* ais_addbits(bits, 271, 1, (uint64_t)ais->type21.spare); */
  249. len = 271 + 1;
  250. if (strlen(ais->type21.name) > 20) {
  251. unsigned int extralen;
  252. extralen = (unsigned int)(strlen(ais->type21.name) - 20);
  253. ais_addchar(bits, 272, extralen, ais->type21.name + 20);
  254. len += extralen * 6;
  255. }
  256. break;
  257. case 24: /* Class B CS Static Data Report Part 1 */
  258. if (ais->type24.part == part_a) {
  259. ais_addbits(bits, 38, 2, (uint64_t)0);
  260. ais_addchar(bits, 40, 20, ais->type24.shipname);
  261. /* ais_addbits(bits, 160, 8, (uint64_t)ais->type24.a.spare); */
  262. len = 160;
  263. }
  264. break;
  265. case 24 | AIS_MSG_PART2_FLAG: /* Class B CS Static Data Report Part 2 */
  266. if ((ais->type24.part == part_b) || (ais->type24.part == both)) {
  267. ais_addbits(bits, 38, 2, (uint64_t)1);
  268. ais_addbits(bits, 40, 8, (uint64_t)ais->type24.shiptype);
  269. ais_addchar(bits, 48, 3, &ais->type24.vendorid[0]);
  270. ais_adddata(bits, 66, 3, &ais->type24.vendorid[3]);
  271. ais_addchar(bits, 90, 7, ais->type24.callsign);
  272. if (AIS_AUXILIARY_MMSI(ais->mmsi)) {
  273. ais_addbits(bits, 132, 30,
  274. (uint64_t)ais->type24.mothership_mmsi);
  275. } else {
  276. ais_addbits(bits, 132, 9, (uint64_t)ais->type24.dim.to_bow);
  277. ais_addbits(bits, 141, 9, (uint64_t)ais->type24.dim.to_stern);
  278. ais_addbits(bits, 150, 6, (uint64_t)ais->type24.dim.to_port);
  279. ais_addbits(bits, 156, 6,
  280. (uint64_t)ais->type24.dim.to_starboard);
  281. }
  282. /* ais_addbits(bits, 162, 6, ais->type24.b.spare); */
  283. len = 162 + 6;
  284. }
  285. break;
  286. case 27: /* Long Range AIS Broadcast message */
  287. ais_addbits(bits, 38, 1, (uint64_t)ais->type27.accuracy);
  288. ais_addbits(bits, 39, 1, (uint64_t)ais->type27.raim);
  289. ais_addbits(bits, 40, 4, (uint64_t)ais->type27.status);
  290. ais_addbits(bits, 44, 18, (uint64_t)ais->type27.lon);
  291. ais_addbits(bits, 62, 17, (uint64_t)ais->type27.lat);
  292. ais_addbits(bits, 79, 6, (uint64_t)ais->type27.speed);
  293. ais_addbits(bits, 85, 9, (uint64_t)ais->type27.course);
  294. ais_addbits(bits, 94, 1, (uint64_t)ais->type27.gnss);
  295. break;
  296. }
  297. ais_binary_to_ascii(bits, len);
  298. return len;
  299. }
  300. #endif /* AIVDM_ENABLE */
  301. // vim: set expandtab shiftwidth=4