Digitraffic
magnifying glass

Marine traffic

Open data from Finnish waterways

General info

Marine traffic information is gathered from Finnish Transport Infrastructure Agency’s data sources. Currently open data API provides following information:

  • Marine warnings

  • Harbor schedules (gathered from the Portnet-system)

  • Vessel location AIS (Automatic Identification System). Additional info.

  • Dirways from Baltice-system

  • Sea state estimation data from TLSC-system, that analyzes data send by smart AtoN buoy sites

  • Waterway traffic disturbances

  • Aton faults

  • Related metadata

Content

  • Do not remove this line (it will not be displayed)

REST/JSON -API

Swagger API descriptions

Full API descriptions can be found in Swagger-documentation page

Nautical warnings

https://meri.digitraffic.fi/api/nautical-warning/v1/warnings/active

Nautical warnings are fetched from POOKI.

At this time there is no metadata available.

Port calls

https://meri.digitraffic.fi/api/port-call/v1/port-calls

Port calls are fetched from Portnet.

Related metadata:

https://meri.digitraffic.fi/api/port-call/v1/ports

https://meri.digitraffic.fi/api/port-call/v1/vessel-details

https://meri.digitraffic.fi/api/port-call/v1/code-descriptions

Vessel locations

https://meri.digitraffic.fi/api/ais/v1/locations

Vessel locations and metadata are collected from AIS-messages broadcasted by vessels. Additional info.

Related metadata:

https://meri.digitraffic.fi/api/ais/v1/vessels

Dirways

https://meri.digitraffic.fi/api/winter-navigation/v1/dirways

Dirways are fetched from Baltice.

Related metadata:

https://meri.digitraffic.fi/api/winter-navigation/v1/ports

https://meri.digitraffic.fi/api/winter-navigation/v1/vessels

Sea state estimation (SSE)

Data + metadata:

https://meri.digitraffic.fi/api/sse/v1/measurements

Sea state estimation data is fetched from TLSC-server, that gathers and analyzes data send by AtoN sites.

Data is updated every 30 minutes.

Disturbances in waterway traffic

https://meri.digitraffic.fi/api/bridge-lock/v1/disruptions

Waterway traffic disturbances are fetched from POOKI.

Data is updated every 10 minutes.

Aton faults

https://meri.digitraffic.fi/api/aton/v1/faults

Aton faults are fetched from POOKI.

Data is updated every 10 minutes.

MQTT WebSocket APIs

Vessel locations can be tracked from following WebSocket APIs. Protocol is MQTT over WebSockets. This allows you to subscibe only those topics you are interested in.

Production address is wss://meri.digitraffic.fi:443/mqtt.

You must use SSL when connecting.

When using Paho JS-client the address is plain meri.digitraffic.fi and port 443, see example below.

Address for test is meri-test.digitraffic.fi.

Simple example client can be found at Support > MQTT examples page.

Topics

At the root of each offered data type is also the topic status. The message tells when the data is last updated in epoch seconds. E.g.:

status: {
  "updated" : 1676628995
}

Vessel topics

Topics are constructed like this:

  • vessels-v2/\<mmsi\>/metadata
  • vessels-v2/\<mmsi\>/locations
  • vessels-v2/status

Examples of tracking vessels data

vessels-v2/#                 # Tracking all data
vessels-v2/+/location        # Tracking all locations
vessels-v2/+/metadata        # Tracking all metadata
vessels-v2/<mmsi>/+          # Single vessel locations and metadata
vessels-v2/<mmsi>/location   # Single vessel locations
vessels-v2/<mmsi>/metadata   # Single vessel metadata

Vessel message formats

NOTE: the timestamp in the metadata message is in milliseconds while in the location message it is in seconds.

See also AIS data field descriptions in Swagger: https://meri.digitraffic.fi/swagger/#/AIS%20V1

Vessel metadata -message

{
    "timestamp":1668075026035,
    "destination":"UST LUGA",
    "name":"ARUNA CIHAN",
    "draught":68,
    "eta":733376,
    "posType":15,
    "refA":160,
    "refB":33,
    "refC":20,
    "refD":12,
    "callSign":"V7WW7",
    "imo":9543756,
    "type":70
}

Vessel location -message

{
    "time":1668075025,
    "sog":10.7,
    "cog":326.6,
    "navStat":0,
    "rot":0,
    "posAcc":true,
    "raim":false,
    "heading":325,
    "lon":20.345818,
    "lat":60.03802
}

SSE topics

Topics are constructed like this:

  • sse-v2/status
  • sse-v2/site/<site-id>

Examples of tracking SSE-data

sse-v2/#                       # Tracking all data
sse-v2/status                  # Tracking status messages
sse-v2/site/+                  # Tracking all sites data
sse-v2/site/<site-id>          # Tracking single site data

SSE-data -message

{
    "timestamp":1668085252,
    "seaState":"CALM",
    "trend":"NO_CHANGE",
    "windWaveDir":175,
    "confidence":"GOOD",
    "heelAngle":3,
    "lightStatus":"OFF",
    "temperature":10
}

A simple JavaScript MQTT WebSocket client

The code below refers to the missing variable clientName. Initialize it with the name of your application.

Note! If your application is not constantly fetching data, close the connection by calling client.disconnect().)
The example code disconnects after 30 s.


<html>
<head>
    <title>Testiclient for vessel locations</title>
    <script type="text/javascript"
            src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <script type="text/javascript"
            src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.2/mqttws31.min.js"></script>

    <script>
        const lines = [];
        var messageCount = 0;
        let client;

        function connect() {
            console.log('trying to connect marine mqtt...');

            // enter a valid client name to fix the syntax error
            client = new Paho.MQTT.Client("meri-test.digitraffic.fi", 443, clientName);

            client.onConnectionLost = function (response) {
                console.info(Date.now() + ' Connection lost:' + response.errorMessage);
            };

            client.onMessageArrived = function (message) {
                messageCount++;

                addMessage(message);

                updateList();
            };

            const connectionProperties = {
                onSuccess: onConnect, onFailure: onConnectFailure, mqttVersion: 4, useSSL: true
            };

            client.connect(connectionProperties);

            window.setInterval(logMessageCount, 60 * 1000);
        }

        function disconnect() {
            client.disconnect();
        }

        function logMessageCount() {
            console.info(Date.now() + ' ' + messageCount + ' messages per minute');
            messageCount = 0;
        }

        function onConnect() {
            console.info(Date.now() + ' Connection open');
            client.subscribe("vessels-v2/#");
        }

        function onConnectFailure(response) {
            console.info(
                Date.now() + ' Connection failed .' + response.errorCode + ": " + response.errorMessage);
        }

        function addMessage(message) {
            const text = convert(message);

            if (lines.length > 100) {
                lines.shift();
            }

            lines.push(text);
        }

        function updateList() {
            $(".messages").html(lines.join('<br/>'));
        }

        function convert(message) {
            const content = message.payloadString;
            const topic = message.destinationName;
            const time = Date.now();
            const json = JSON.parse(content);
            let deltaMs;

            if (typeof json.properties === "undefined") {
                deltaMs = time - json.timestamp;
            } else {
                deltaMs = time - json.properties.timestampExternal;
            }

            return "{ now: " + time + ", &Delta;timeMs: " + deltaMs + ", topic: \"" + topic + "\", content: " + content + " }";
        }

        connect();

        // disconnect after 30 seconds
        setTimeout(disconnect, 30000);
    </script>
</head>
<body>
Messages:
<div class="messages"/>
</body>
</html>

A simple Python MQTT WebSocket client

Initialize APP_NAME variable with the name of your application.

Note! If your application is not constantly fetching data, close the connection by calling client.disconnect().
The example code disconnects after 30 s.

import uuid
import paho.mqtt.client as mqtt
import time

APP_NAME = 'Junamies/FoobarApp 1.0'


def on_message(client, userdata, message):
    print('message received', str(message.payload.decode('utf-8')))


def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print('Connected')
        client.subscribe("vessels-v2/#")
    else:
        print('Failed to connect, return code %d\n', rc)


client_name = '{}; {}'.format(APP_NAME, str(uuid.uuid4()))
client = mqtt.Client(client_name, transport="websockets")

client.on_connect = on_connect
client.on_message = on_message

client.tls_set()
client.connect('tie.digitraffic.fi', 443)

client.loop_start()
time.sleep(30)
client.loop_stop()

client.disconnect()

Restrictions

See Information and instructions for using APIs > General considerations

Supported and deprecated APIs

Listings of supported and deprecated APIs can be found here.

bug_reportDid you find an error? Help us improve this page.