In a previous article, I introduced AIS Tools, as well as how they can be utilized to collect data from various sources. This article is about visualization on a interactive map. The term AIS-PLTR was derived from AIS chart plotter. The presentation of AIS information is commonly referred to as chart plotting. In order to be able to display geographic information on a interactive map, a backend is required which can provide the data via REST and updates in real time using a web socket. To solve this task, two projects where developed. AIS-PLTR for the front end and AIS-PLTR-SRV for the backend.
Visualize AIS Data with LeafletJS and MaterialUI Web
AIS-PLTR is intended to be the simplest possible AIS chart plotter with which ship positions can be displayed. The development was done with TypeScript and LeafletJS as Map API and MaterialUI Web as layout library. No other front end frameworks were used. Click here to open the AIS PLTR Application
Installation
The installation is done by clone the project repository and installing the dependencies.1
2
3git clone https://github.com/3epnm/ais-pltr
cd ais-pltr
npm install
AIS-PLTR uses webpack to bundle the source files. npm start
is called to run the development server or npm run build
to build a bundle of the application. The resulting dist folder within the project directory can then be served via a webserver, eg. nginx. At the end of this article, a example for a possible nginx configuration is given.
Features
The application only covers the area of the Port of Hamburg. Usually there are no more than 370 ships in the port, so that each of these ships can be renewed in real time without getting into performance problems.
The range of features is limited, but allows interesting things to be observed. In addition to a table of all ships, a detailed view of the ship parameters and a table of all ship positions of the last hour, the user can display and record the positions track for up to 8 ships.
The Map
The center of the application is a map on which the ship positions are rendered. The red dot indicates the mounting position of the AIS transceiver. Unfortunately, not all ships report the exact direction in which the bow is pointing. In this case, the ships are shown as a simple marker when they are not moving and this information cannot be derived from the course of the ship.
Arrival area of the port ferries at Hamburg Landungsbrücken
The Ship Table
The Ship table can be opened via the main menu drawer. The latter is shown if the user activates the menu icon in the top, left corner. If a ship in this table has updates, the corresponding row is animated. The table can be sorted if the user clicks on a column header. On the top right of the ship table a search field is located, where the table can be filtered by name, type or MMSI of a ship. A function, where the table can be filtered by port ferries can be found left from the search field. A click on a row centers the map to the current position of the selected vessel.
The ship table filtered by port ferries
Vessel Detail Views
If the User clicks on a ship marker, a popup with some details about the ship is shown as well as a ship image, if a free to use image is available. The popup offers a more detailed view to see all up-to-date AIS Details. When clicked on the Details button, a modal with two tabs is shown. The first tab, Ship Data
, shows static and voyage related data. The second tab, Position
, shows the current position report. The fields are updated, if changes occur.
The port ferry Altenwerder underway
Positions Table and Position Lock
The position table can be opened via the Positions
button of the ship popup. In the position table, the history of positions can be viewed where the most recent report is displayed on top. The table is updated if a new position report occurs. The user can use the Lock
function found in the top right corner of the position table to automatically re-center the map to the most recent position of the selected ship if it moves.
Position table for port ferry Oortkaten
Track Rendering
The user can create up to eight track recordings. The last button in the detail popup, labeled Track
, enables or disables a position recording for a ship. By default, the track of positions for the last hour is displayed. This can be enabled or disabled with the Load Track History
button from the main menu. The following screen recording illustrates this functionality. The position of the biggest ship of the three is locked. The other two ships are tugs which support the cargo ship. The track history is turned off.
Screen recording of cargo ships reach the port of Hamburg
Track Collection Popup
Additional functions
Some additional functions are located on the right side of the title bar.
Additional functions
Some additional functions are located on the right side of the title bar. With the
+
and -
button zoom the view in or out. The lock icon releases the position lock without having to open the position table of the ship in question. The bookmark icon before the help icon opens a list of regions, to which the map will zoom/pan if an entry is clicked. The last icon opens the help function, where the user can learn about the main features of this application.
Provide AIS Data with Rest and via Web Socket
For the AIS PLTR to be functional, a backend service is needed. AIS PLTR SRV is a simple backend for this purpose. The requirements are not particularly high. The only available resources are endpoints for reading shipdata and positions from the database as well as a web socket for streaming updates in real time.
Installation
The installation is done by clone the project repository and installing the dependencies.1
2
3git clone https://github.com/3epnm/ais-pltr
cd ais-pltr
npm install
Before the project can be started, the configuration must first be adjusted.
Configuration
The configuration is done with node-config-ts. A simple but effective configuration manager for typescript based projects. The easiest way to adapt the configuration is to adapt the file default.json from the config directory. In practice, it has proven useful to use a new configuration file depending on the NODE_ENV variable. How this works is explained in the documentation of node-config-ts. Refer to the npm page node-config-ts to learn all its features.
The configuration file has the following content, which is explained below.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23{
"database": {
"url": "mongodb://127.0.0.1:27017",
"options": {
"useNewUrlParser": true,
"useUnifiedTopology": true
},
"dbName": ""
},
"http": {
"port": 4000
},
"logger": {
"level": "warn",
"filter": 0,
"filename": ""
},
"ssh": {
"enabled": true,
"forward": "61126:127.0.0.1:61126",
"host": "***"
}
}
Database section
The configuration of the database is as follows:
Parameter | Description |
---|---|
url | The connection url to the MongoDB instance. |
options |
Options to setup the Database Connection. All options of the native MongoDB Driver are possible. |
dbName | The name of the database where to store report data. |
Http section
The only configuration which can be done is setting the port number on which the server is started.
Parameter | Description |
---|---|
port | The port number on which the server is listen for requests. |
Logger section
Logging is done with winston universal logging library.
Parameter | Description |
---|---|
level |
The logging levels are named after npm logging levels and allows to configure how verbose the messages are written to a logfile or to stdout. |
filter |
The filter is a MMSI Number - an identifier every AIS Report has and which is unique to the vessel. Used to log the processing of Reports for a specific vessel. |
filename |
The filename where the log file is written to. If empty, the messages are written to stdout. |
The logger uses the winston-daily-rotate-file to archive log files if used in a debug level for a longer period of time. In addition, the logger can also be controlled via the NODE_ENV environment variable. If set to “debug”, the log messages also written to stdout, regardless of whether the filename parameter is set or not.
SSH section
The following configuration enables an SSH tunnel to be created if required, which is started as a child process.
Parameter | Description |
---|---|
enabled | Whether the function is used or not |
forward | Which port from the source is forwarded to a port at the destination |
host | The host of the source |
Start the Service
Once the configuration is done, the service can be started with npm start
REST Endpoints
The REST services serve as a proxy to MongoDB. MongoDB offers an easy way to create queries with a JSON object. This fact makes it possible to develop a REST service that essentially works like a query on a MongoDB collection. Datetime parameters can be written as a ISO date string and are automatically transformed to JavaScript Date Objects for a valid request. Another parameter is limit in order to limit the result set according to the number of objects returned.
Ships Endpoint
The /api/ships
endpoint accepts requests against the ship data collection. Queries are defined using the cgi query parameter.
An additional limit parameter allows the number of documents to be limited.
Parameter | Description |
---|---|
filter |
A MongoDB Collection Filter, ISO date strings are automatically transformed to JavaScript Date Objects |
limit |
The number of documents to be loaded from the collection, if no filter is defined, the limit defaults to 500 |
All parameters are optional and the resulting collection is automatically sorted by ship name.
Example
HTTP GET /api/ships?filter={"MMSI":211207080}
1 | [ |
Position Endpoints
The /api/positions
endpoint accepts requests against the positions collection.
Parameter | Description |
---|---|
filter |
A MongoDB Collection Filter, ISO date strings are automatically transformed to JavaScript Date Objects |
limit |
The number of documents to be loaded from the collection, if no filter is defined, the limit defaults to 500 |
options | This parameter accepts a serialized JSON Object. |
The only option awailable is { "unique": true }
. If this option is set, the positions are unique by the vessels MMSI. All parameters are optional and the resulting collection is automatically sorted ascending by ais-timestamp.
The /api/position
endpoint is similar like the /api/positions endpoint. The difference is that only a single and most recent position within the result set is returned.
Parameter | Description |
---|---|
filter |
A MongoDB Collection Filter, ISO date strings are automatically transformed to JavaScript Date Objects |
Example
HTTP GET /api/position?filter={"MMSI":211207080}
1 | { |
Websocket
AIS PLTR SRV offers a websocket connection, where ship and position updates are broadcast to the clients. The websocket service is implemented with socket.io.
The server can be controlled with messages. As soon as a connection is established, subscribe
and unsubscribe
can be used to inform the service that the client is ready to receive data or that the connection is to be interrupted. Messages are sent to the server using the socket instance method emit
. If the subscription is successful, the server sends new ship data and positions, which results in a corresponding event.
Commands | Description |
---|---|
subscribe | Informs the server to start sending data. |
unsubscribe | Informs the server to stop sending data. |
A JSON object with a uuid is used by the server to identify the recipient. See the examples below.
Events | Description |
---|---|
positions | Newly received position data report. |
ships | Newly received static and voyage data report. |
Example
The following example illustrates how this service can be utilized.
1 | const socket = io() |
Proxy for Front- and Backend with Nginx
To bring the front end AIS PLTR and the backend AIS PLTR SRV together, it is good practice to use a proxy server, eg. NGINX, to combine multiple services and static data on a single host. A possible NGINX documentation is as follows.
Behind the /osm
route a redirection to openstreetmap is executed. Returned map tiles are cached to improve the performance and reduce the load to openstreetmap. Behind the /api
and /socket.io
route a redirection ais-pltr-srv. From root, the dist folder of the ais-pltr front end is served.
1 | http { |