31 Commits

Author SHA1 Message Date
xbgmsharp
1e177dd770 Update 2e2 frontend tests 2023-08-25 11:23:09 +02:00
xbgmsharp
96e91784c5 More github actions e2e testing 2023-08-25 11:14:10 +02:00
xbgmsharp
d5330ca482 Update github actions front-end e2e tests 2023-08-25 11:04:05 +02:00
xbgmsharp
4e304bfc53 Update README 2023-08-25 11:03:48 +02:00
xbgmsharp
b237d91990 Update github actions frontend tests 2023-08-23 13:00:36 +02:00
xbgmsharp
6ae7591f3d Update tests reduce check to postgres version to remove architecture from check 2023-08-23 12:48:49 +02:00
xbgmsharp
3a4aadc81a Update postgrest version parsing 2023-08-23 12:46:35 +02:00
xbgmsharp
c8c10dd51c Release 0.2.3 2023-08-23 12:30:55 +02:00
xbgmsharp
1bfea2ade5 Tests, add missing package.json 2023-08-23 12:29:11 +02:00
xbgmsharp
5105322eed Add unit tests mocha and sql 2023-08-23 12:23:51 +02:00
xbgmsharp
2d3c531960 Update api.logbook comment extra column 2023-08-22 17:00:43 +02:00
xbgmsharp
f37156f15c update github actions 2023-08-22 16:59:50 +02:00
xbgmsharp
11e0493964 Update README, openapi link 2023-08-22 16:59:40 +02:00
xbgmsharp
eee9ea6065 Update logbook extra json obj, add observations (seaState,cloudCoverage,Visibility) default values 2023-08-22 16:41:44 +02:00
xbgmsharp
b2f1e5e0e9 Update versions, add postgrest version 2023-08-22 16:41:01 +02:00
xbgmsharp
2a77216ef6 Update API schema comment for OpenAPI documentation. 2023-08-21 17:13:32 +02:00
xbgmsharp
eee862900d Update openapi documentation. 2023-08-21 15:24:43 +02:00
xbgmsharp
dc54d0c5e3 Update README 2023-08-21 15:11:07 +02:00
xbgmsharp
2684c83ce8 Update README 2023-08-21 15:09:20 +02:00
xbgmsharp
412a6e8a58 Add openapi documentation 2023-08-20 11:19:53 +02:00
xbgmsharp
f0198aeb3e Update github actions 2023-08-18 01:49:08 +02:00
xbgmsharp
2a8f74a62f Update github actions 2023-08-18 01:42:24 +02:00
xbgmsharp
0eda59d68a Update github actions 2023-08-18 01:36:53 +02:00
xbgmsharp
652b72c274 Update github actions 2023-08-18 01:26:53 +02:00
xbgmsharp
3b798c99c4 Update github actions e2e tests 2023-08-18 00:56:58 +02:00
xbgmsharp
4b6eeefdba Update web_dev and web_tests containers for e2e testings 2023-08-18 00:56:01 +02:00
xbgmsharp
306623a55a Add new API function, api.stats_logs_fn, export logs statistics 2023-08-18 00:54:58 +02:00
xbgmsharp
5230a83833 Update logbook table, add comment on column 2023-08-18 00:54:11 +02:00
xbgmsharp
96f80b9584 Update export logbook gpx function, move the function inside the logbook cron process workflow rather than directly on an API call. 2023-08-15 23:18:07 +02:00
xbgmsharp
c63bf63308 Update api.timelapse_fn, return only logbook with geojson data. 2023-08-15 10:16:23 +02:00
xbgmsharp
0f78d56b37 Ensure moorages view and function have a valid geographic point 2023-08-14 22:50:35 +02:00
39 changed files with 7130 additions and 125 deletions

View File

@@ -4,6 +4,7 @@ on:
pull_request: pull_request:
paths: paths:
- 'initdb/**' - 'initdb/**'
- 'tests/**'
branches: branches:
- 'main' - 'main'
push: push:
@@ -11,6 +12,9 @@ on:
- 'main' - 'main'
paths: paths:
- 'initdb/**' - 'initdb/**'
- 'tests/**'
tags:
- "*"
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -27,6 +31,9 @@ jobs:
- name: Pull Docker images - name: Pull Docker images
run: docker-compose pull db api run: docker-compose pull db api
- name: Build Docker images
run: docker-compose -f docker-compose.dev.yml -f docker-compose.yml build tests
- name: Install psql - name: Install psql
run: sudo apt install postgresql-client run: sudo apt install postgresql-client
@@ -54,7 +61,12 @@ jobs:
echo "Test PostgSail version" echo "Test PostgSail version"
psql -c "SELECT value FROM app_settings WHERE name = 'app.version';" psql -c "SELECT value FROM app_settings WHERE name = 'app.version';"
echo "Test PostgSail Unit Test" echo "Test PostgSail Unit Test"
docker-compose -f docker-compose.dev.yml -f docker-compose.yml up tests docker compose -f docker-compose.dev.yml -f docker-compose.yml up tests --abort-on-container-exit --exit-code-from tests
if [ $? != 0 ];
then
echo "Error running db-tests"
exit 1
fi
- name: Show the logs - name: Show the logs
if: always() if: always()
run: | run: |

View File

@@ -11,6 +11,8 @@ on:
- 'main' - 'main'
paths: paths:
- 'frontend/**' - 'frontend/**'
tags:
- "*"
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -19,14 +21,19 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
with:
submodules: 'true'
- name: Set env - name: Set env
run: cp .env.example .env run: cp .env.example .env
- name: Pull Docker images - name: Pull Docker images
run: docker-compose pull db api web run: docker compose -f docker-compose.dev.yml -f docker-compose.yml pull db api web_tests
- name: Run PostgSail Web test - name: Build Docker images
run: docker compose -f docker-compose.dev.yml -f docker-compose.yml build web_dev
- name: Run PostgSail Web tests
# Environment variables # Environment variables
env: env:
# The hostname used to communicate with the PostgreSQL service container # The hostname used to communicate with the PostgreSQL service container
@@ -43,9 +50,16 @@ jobs:
docker-compose up -d db && sleep 15 && docker-compose up -d api && sleep 5 docker-compose up -d db && sleep 15 && docker-compose up -d api && sleep 5
docker-compose ps -a docker-compose ps -a
echo "Test PostgSail Web Unit Test" echo "Test PostgSail Web Unit Test"
docker-compose up -d web && sleep 5 docker compose -f docker-compose.dev.yml -f docker-compose.yml up -d web_dev && sleep 100
docker-compose ps -a docker compose -f docker-compose.dev.yml -f docker-compose.yml logs web_dev
docker compose ps -a
curl http://localhost:8080/ curl http://localhost:8080/
docker compose -f docker-compose.dev.yml -f docker-compose.yml up web_tests --abort-on-container-exit --exit-code-from web_tests
if [ $? != 0 ];
then
echo "Error running frontend-tests"
exit 1
fi
- name: Show the logs - name: Show the logs
if: always() if: always()
run: | run: |

View File

@@ -11,6 +11,8 @@ on:
- 'main' - 'main'
paths: paths:
- 'grafana/**' - 'grafana/**'
tags:
- "*"
workflow_dispatch: workflow_dispatch:
jobs: jobs:

View File

@@ -2,6 +2,23 @@
Effortless cloud based solution for storing and sharing your SignalK data. Allow you to effortlessly log your sails and monitor your boat with historical data. Effortless cloud based solution for storing and sharing your SignalK data. Allow you to effortlessly log your sails and monitor your boat with historical data.
[![release](https://img.shields.io/github/release/xbgmsharp/postgsail?include_prereleases=&sort=semver&color=blue)](https://github.com/xbgmsharp/postgsail/releases/latest)
[![License](https://img.shields.io/badge/License-MIT-blue)](#license)
[![issues - postgsail](https://img.shields.io/github/issues/xbgmsharp/postgsail)](https://github.com/xbgmsharp/postgsail/issues)
[![Test services db, api](https://github.com/xbgmsharp/postgsail/actions/workflows/db-test.yml/badge.svg)](https://github.com/xbgmsharp/postgsail/actions/workflows/db-test.yml)
[![Test services db, api, web](https://github.com/xbgmsharp/postgsail/actions/workflows/frontend-test.yml/badge.svg)](https://github.com/xbgmsharp/postgsail/actions/workflows/frontend-test.yml)
[![Test services db, grafana](https://github.com/xbgmsharp/postgsail/actions/workflows/grafana-test.yml/badge.svg)](https://github.com/xbgmsharp/postgsail/actions/workflows/grafana-test.yml)
signalk-postgsail:
[![GitHub Release](https://img.shields.io/github/release/xbgmsharp/signalk-postgsail.svg)](https://github.com/xbgmsharp/signalk-postgsail/releases/latest)
postgsail-frontend:
[![GitHub Release](https://img.shields.io/github/release/xbgmsharp/vuestic-postgsail.svg)](https://github.com/xbgmsharp/vuestic-postgsail/releases/latest)
postgsail-telegram-bot:
[![GitHub Release](https://img.shields.io/github/release/xbgmsharp/postgsail-telegram-bot.svg)](https://github.com/xbgmsharp/postgsail-telegram-bot/releases/latest)
## Features ## Features
- Automatically log your voyages without manually starting or stopping a trip. - Automatically log your voyages without manually starting or stopping a trip.
@@ -17,6 +34,8 @@ Effortless cloud based solution for storing and sharing your SignalK data. Allow
- Notification via email or PushOver, Telegram - Notification via email or PushOver, Telegram
- Offline mode - Offline mode
- Low Bandwidth mode - Low Bandwidth mode
- Awesome statistics and graphs
- Anything missing? just ask!
## Context ## Context
@@ -44,18 +63,20 @@ Hosted and fullymanaged options for PostgSail, designed for all your deployme
## Using PostgSail ## Using PostgSail
### full-featured development environment A full-featured development environment.
The Visual Studio Code Remote - Containers extension lets you use a Docker container as a full-featured development environment.
#### With codesandbox #### With CodeSandbox
- https://codesandbox.io/p/github/xbgmsharp/postgsail/main
- Develop on [![CodeSandbox Ready-to-Code](https://img.shields.io/badge/CodeSandbox-Ready--to--Code-blue?logo=codesandbox)](https://codesandbox.io/p/github/xbgmsharp/postgsail/main)
- or via [direct link](https://codesandbox.io/p/github/xbgmsharp/postgsail/main)
#### With DevPod #### With DevPod
- https://devpod.sh/open#https://github.com/xbgmsharp/postgsail/&workspace=postgsail&provider=docker&ide=openvscode
- [![Open in DevPod!](https://devpod.sh/assets/open-in-devpod.svg)](https://devpod.sh/open#https://github.com/xbgmsharp/postgsail/&workspace=postgsail&provider=docker&ide=openvscode)
- or via [direct link](https://devpod.sh/open#https://github.com/xbgmsharp/postgsail&workspace=postgsail&provider=docker&ide=openvscode)
#### With Docker Dev Environments #### With Docker Dev Environments
- https://open.docker.com/dashboard/dev-envs?url=https://github.com/xbgmsharp/postgsail/ - [Open in Docker dev-envs!](https://open.docker.com/dashboard/dev-envs?url=https://github.com/xbgmsharp/postgsail/)
Open in Docker Dev Environments Open in Docker Dev Environments
### pre-deploy configuration ### pre-deploy configuration
@@ -136,6 +157,8 @@ $ docker-compose up tests
The OpenAPI description output depends on the permissions of the role that is contained in the JWT role claim. The OpenAPI description output depends on the permissions of the role that is contained in the JWT role claim.
Other applications can also use the [PostgSAIL API](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/xbgmsharp/postgsail/main/openapi.json).
API anonymous: API anonymous:
``` ```
@@ -156,7 +179,7 @@ $ curl http://localhost:3000/ -H 'Authorization: Bearer my_token_from_register_v
#### API main workflow #### API main workflow
Check the [unit test sample](https://github.com/xbgmsharp/postgsail/blob/main/tests/index.js). Check the [e2e unit test sample](https://github.com/xbgmsharp/postgsail/blob/main/tests/).
### Docker dependencies ### Docker dependencies

View File

@@ -90,6 +90,7 @@ services:
context: https://github.com/xbgmsharp/vuestic-postgsail.git#live context: https://github.com/xbgmsharp/vuestic-postgsail.git#live
dockerfile: Dockerfile_dev dockerfile: Dockerfile_dev
container_name: web_dev container_name: web_dev
hostname: web_dev
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- ./frontend:/app - ./frontend:/app
@@ -97,8 +98,9 @@ services:
- "api:postgrest" - "api:postgrest"
ports: ports:
- 8080:8080 - 8080:8080
env_file: .env
environment: environment:
- VITE_PGSAIL_URL=${PGSAIL_API_URL} - VITE_PGSAIL_URL=http://api:3000
- VITE_APP_INCLUDE_DEMOS=false - VITE_APP_INCLUDE_DEMOS=false
- VITE_APP_BUILD_VERSION=true - VITE_APP_BUILD_VERSION=true
- VITE_APP_TITLE=${VITE_APP_TITLE} - VITE_APP_TITLE=${VITE_APP_TITLE}
@@ -109,5 +111,25 @@ services:
options: options:
max-size: 10m max-size: 10m
web_tests:
image: cypress/included
container_name: web_tests
restart: unless-stopped
volumes:
- ./frontend/e2e:/e2e
links:
- "api:postgrest"
- "web_dev:frontend"
env_file: .env
environment:
- CYPRESS_BASE_URL=http://web_dev:8080
depends_on:
- db
- api
- web_dev
logging:
options:
max-size: 10m
volumes: volumes:
data: {} data: {}

View File

@@ -57,7 +57,10 @@ ALTER DATABASE signalk SET TIMEZONE='UTC';
-- Schema -- Schema
CREATE SCHEMA IF NOT EXISTS api; CREATE SCHEMA IF NOT EXISTS api;
COMMENT ON SCHEMA api IS 'api schema expose to postgrest'; COMMENT ON SCHEMA api IS
$$PostgSail API
A RESTful API that serves PostgSail data using postgrest.$$;
-- Revoke default privileges to all public functions -- Revoke default privileges to all public functions
ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC; ALTER DEFAULT PRIVILEGES REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC;

View File

@@ -120,14 +120,15 @@ CREATE TABLE IF NOT EXISTS api.logbook(
avg_speed DOUBLE PRECISION NULL, avg_speed DOUBLE PRECISION NULL,
max_speed DOUBLE PRECISION NULL, max_speed DOUBLE PRECISION NULL,
max_wind_speed DOUBLE PRECISION NULL, max_wind_speed DOUBLE PRECISION NULL,
notes TEXT NULL, notes TEXT NULL, -- remarks
extra JSONB NULL extra JSONB NULL -- computed signalk metrics of interest
); );
-- Description -- Description
COMMENT ON TABLE COMMENT ON TABLE
api.logbook api.logbook
IS 'Stores generated logbook'; IS 'Stores generated logbook';
COMMENT ON COLUMN api.logbook.distance IS 'in NM'; COMMENT ON COLUMN api.logbook.distance IS 'in NM';
COMMENT ON COLUMN api.logbook.extra IS 'computed signalk metrics of interest, runTime, currentLevel, etc';
-- Index todo! -- Index todo!
CREATE INDEX logbook_vessel_id_idx ON api.logbook (vessel_id); CREATE INDEX logbook_vessel_id_idx ON api.logbook (vessel_id);

View File

@@ -25,17 +25,20 @@ CREATE OR REPLACE FUNCTION api.timelapse_fn(
SELECT jsonb_agg(track_geojson->'features') INTO _geojson SELECT jsonb_agg(track_geojson->'features') INTO _geojson
FROM api.logbook FROM api.logbook
WHERE id >= start_log WHERE id >= start_log
AND id <= end_log; AND id <= end_log
AND track_geojson IS NOT NULL;
--raise WARNING 'by log _geojson %' , _geojson; --raise WARNING 'by log _geojson %' , _geojson;
ELSIF start_date IS NOT NULL AND public.isdate(start_date::text) AND public.isdate(end_date::text) THEN ELSIF start_date IS NOT NULL AND public.isdate(start_date::text) AND public.isdate(end_date::text) THEN
SELECT jsonb_agg(track_geojson->'features') INTO _geojson SELECT jsonb_agg(track_geojson->'features') INTO _geojson
FROM api.logbook FROM api.logbook
WHERE _from_time >= start_log::TIMESTAMP WITHOUT TIME ZONE WHERE _from_time >= start_log::TIMESTAMP WITHOUT TIME ZONE
AND _to_time <= end_date::TIMESTAMP WITHOUT TIME ZONE + interval '23 hours 59 minutes'; AND _to_time <= end_date::TIMESTAMP WITHOUT TIME ZONE + interval '23 hours 59 minutes'
AND track_geojson IS NOT NULL;
--raise WARNING 'by date _geojson %' , _geojson; --raise WARNING 'by date _geojson %' , _geojson;
ELSE ELSE
SELECT jsonb_agg(track_geojson->'features') INTO _geojson SELECT jsonb_agg(track_geojson->'features') INTO _geojson
FROM api.logbook; FROM api.logbook
WHERE track_geojson IS NOT NULL;
--raise WARNING 'all result _geojson %' , _geojson; --raise WARNING 'all result _geojson %' , _geojson;
END IF; END IF;
-- Return a GeoJSON filter on Point -- Return a GeoJSON filter on Point
@@ -83,61 +86,25 @@ COMMENT ON FUNCTION
-- https://opencpn.org/OpenCPN/info/gpxvalidation.html -- https://opencpn.org/OpenCPN/info/gpxvalidation.html
-- --
DROP FUNCTION IF EXISTS api.export_logbook_gpx_fn; DROP FUNCTION IF EXISTS api.export_logbook_gpx_fn;
CREATE OR REPLACE FUNCTION api.export_logbook_gpx_fn(IN _id INTEGER) RETURNS pg_catalog.xml CREATE OR REPLACE FUNCTION api.export_logbook_gpx_fn(IN _id INTEGER, OUT gpx XML) RETURNS pg_catalog.xml
AS $export_logbook_gpx$ AS $export_logbook_gpx$
DECLARE DECLARE
log_rec record; logbook_rec record;
BEGIN BEGIN
-- If _id is is not NULL and > 0 -- If _id is is not NULL and > 0
IF _id IS NULL OR _id < 1 THEN IF _id IS NULL OR _id < 1 THEN
RAISE WARNING '-> export_logbook_geojson_fn invalid input %', _id; RAISE WARNING '-> export_logbook_gpx_fn invalid input %', _id;
RETURN ''; RETURN;
END IF; END IF;
-- Gather log details _from_time and _to_time -- Gather log details
SELECT * INTO log_rec SELECT * INTO logbook_rec
FROM FROM api.logbook WHERE id = _id;
api.logbook l
WHERE l.id = _id;
-- Ensure the query is successful -- Ensure the query is successful
IF log_rec.vessel_id IS NULL THEN IF logbook_rec.vessel_id IS NULL THEN
RAISE WARNING '-> export_logbook_gpx_fn invalid logbook %', _id; RAISE WARNING '-> export_logbook_gpx_fn invalid logbook %', _id;
RETURN ''; RETURN;
END IF; END IF;
-- Generate XML gpx := logbook_rec.track_gpx;
RETURN xmlelement(name gpx,
xmlattributes( '1.1' as version,
'PostgSAIL' as creator,
'http://www.topografix.com/GPX/1/1' as xmlns,
'http://www.opencpn.org' as "xmlns:opencpn",
'https://iot.openplotter.cloud' as "xmlns:postgsail",
'http://www.w3.org/2001/XMLSchema-instance' as "xmlns:xsi",
'http://www.garmin.com/xmlschemas/GpxExtensions/v3' as "xmlns:gpxx",
'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd' as "xsi:schemaLocation"),
xmlelement(name trk,
xmlelement(name name, log_rec.name),
xmlelement(name desc, log_rec.notes),
xmlelement(name link, xmlattributes(concat('https://iot.openplotter.cloud/log/', log_rec.id) as href),
xmlelement(name text, log_rec.name)),
xmlelement(name extensions, xmlelement(name "postgsail:log_id", 1),
xmlelement(name "postgsail:link", concat('https://iot.openplotter.cloud/log/', log_rec.id)),
xmlelement(name "opencpn:guid", uuid_generate_v4()),
xmlelement(name "opencpn:viz", '1'),
xmlelement(name "opencpn:start", log_rec._from_time),
xmlelement(name "opencpn:end", log_rec._to_time)
),
xmlelement(name trkseg, xmlagg(
xmlelement(name trkpt,
xmlattributes(latitude as lat, longitude as lon),
xmlelement(name time, time)
)))))::pg_catalog.xml
FROM api.metrics m
WHERE m.latitude IS NOT NULL
AND m.longitude IS NOT NULL
AND m.time >= log_rec._from_time::TIMESTAMP WITHOUT TIME ZONE
AND m.time <= log_rec._to_time::TIMESTAMP WITHOUT TIME ZONE
AND vessel_id = log_rec.vessel_id;
-- ERROR: column "m.time" must appear in the GROUP BY clause or be used in an aggregate function at character 2304
--ORDER BY m.time ASC;
END; END;
$export_logbook_gpx$ LANGUAGE plpgsql; $export_logbook_gpx$ LANGUAGE plpgsql;
-- Description -- Description
@@ -327,6 +294,7 @@ CREATE FUNCTION api.export_moorages_geojson_fn(OUT geojson JSONB) RETURNS JSONB
EXTRACT(DAY FROM justify_hours ( stay_duration )) AS Total_Stay, EXTRACT(DAY FROM justify_hours ( stay_duration )) AS Total_Stay,
geog geog
FROM api.moorages FROM api.moorages
WHERE geog IS NOT NULL
) AS m ) AS m
) )
) INTO geojson; ) INTO geojson;
@@ -372,10 +340,66 @@ CREATE FUNCTION api.export_moorages_gpx_fn() RETURNS pg_catalog.xml AS $export_m
xmlelement(name "opencpn:scale_min_max", xmlattributes(true as UseScale, 30000 as ScaleMin, 0 as ScaleMax) xmlelement(name "opencpn:scale_min_max", xmlattributes(true as UseScale, 30000 as ScaleMin, 0 as ScaleMax)
)))) ))))
)::pg_catalog.xml )::pg_catalog.xml
FROM api.moorages m; FROM api.moorages m
WHERE geog IS NOT NULL;
END; END;
$export_moorages_gpx$ LANGUAGE plpgsql; $export_moorages_gpx$ LANGUAGE plpgsql;
-- Description -- Description
COMMENT ON FUNCTION COMMENT ON FUNCTION
api.export_moorages_gpx_fn api.export_moorages_gpx_fn
IS 'Export moorages as gpx'; IS 'Export moorages as gpx';
-- Statistics
DROP FUNCTION IF EXISTS api.stats_logs_fn;
CREATE OR REPLACE FUNCTION api.stats_logs_fn(
IN start_date TEXT DEFAULT NULL,
IN end_date TEXT DEFAULT NULL,
OUT stats JSON) RETURNS JSON AS $stats_logs$
DECLARE
_start_date TIMESTAMP WITHOUT TIME ZONE DEFAULT '1970-01-01';
_end_date TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW();
BEGIN
IF start_date IS NOT NULL AND public.isdate(start_date::text) AND public.isdate(end_date::text) THEN
RAISE WARNING '--> stats_fn, filter result stats by date [%]', start_date;
_start_date := start_date::TIMESTAMP WITHOUT TIME ZONE;
_end_date := end_date::TIMESTAMP WITHOUT TIME ZONE;
END IF;
RAISE WARNING '--> stats_fn, _start_date [%], _end_date [%]', _start_date, _end_date;
WITH
logs_view AS (
SELECT *
FROM api.logbook l
WHERE _from_time >= _start_date::TIMESTAMP WITHOUT TIME ZONE
AND _to_time <= _end_date::TIMESTAMP WITHOUT TIME ZONE + interval '23 hours 59 minutes'
),
max_speed_id AS (
SELECT id FROM logs_view WHERE max_speed = (SELECT max(max_speed) FROM logs_view) ),
max_wind_speed_id AS (
SELECT id FROM logs_view WHERE max_wind_speed = (SELECT max(max_wind_speed) FROM logs_view)),
max_distance_id AS (
SELECT id FROM logs_view WHERE distance = (SELECT max(distance) FROM logs_view)),
max_duration_id AS (
SELECT id FROM logs_view WHERE duration = (SELECT max(duration) FROM logs_view)),
logs_stats AS (
SELECT
count(*) AS count,
max(max_speed) AS max_speed,
max(max_wind_speed) AS max_wind_speed,
max(distance) AS max_distance,
max(duration) AS max_duration,
sum(duration) AS sum_duration
FROM logs_view l )
--select * from logbook;
-- Return a JSON
SELECT jsonb_build_object(
'max_speed_id', max_speed_id.id,
'max_wind_speed_id', max_wind_speed_id.id,
'max_distance_id', max_distance_id.id)::jsonb || to_jsonb(logs_stats.*)::jsonb INTO stats
FROM max_speed_id, max_wind_speed_id, max_distance_id, logs_stats, max_duration_id;
-- TODO Add moorages
END;
$stats_logs$ LANGUAGE plpgsql;
-- Description
COMMENT ON FUNCTION
api.stats_logs_fn
IS 'Logs stats by date';

View File

@@ -194,6 +194,7 @@ CREATE OR REPLACE VIEW api.moorages_view WITH (security_invoker=true,security_ba
FROM api.moorages m, api.stays_at sa FROM api.moorages m, api.stays_at sa
WHERE m.name is not null WHERE m.name is not null
AND m.stay_code = sa.stay_code AND m.stay_code = sa.stay_code
AND geog IS NOT NULL
GROUP BY m.id,m.name,sa.description,m.stay_duration,m.reference_count,m.geog,sa.stay_code GROUP BY m.id,m.name,sa.description,m.stay_duration,m.reference_count,m.geog,sa.stay_code
-- ORDER BY 4 DESC; -- ORDER BY 4 DESC;
ORDER BY m.reference_count DESC; ORDER BY m.reference_count DESC;
@@ -213,7 +214,8 @@ CREATE OR REPLACE VIEW api.moorage_view WITH (security_invoker=true,security_bar
m.notes m.notes
-- m.geog -- m.geog
FROM api.moorages m FROM api.moorages m
WHERE m.name IS NOT NULL; WHERE m.name IS NOT NULL
AND geog IS NOT NULL;
-- Description -- Description
COMMENT ON VIEW COMMENT ON VIEW
api.moorage_view api.moorage_view

View File

@@ -170,67 +170,191 @@ COMMENT ON FUNCTION
public.logbook_update_geojson_fn public.logbook_update_geojson_fn
IS 'Update log details with geojson'; IS 'Update log details with geojson';
create FUNCTION logbook_update_extra_json_fn(IN _id integer, IN _start text, IN _end text, -- Generate GPX XML file output
OUT _extra_json JSON -- https://opencpn.org/OpenCPN/info/gpxvalidation.html
) AS $logbook_extra_json$ --
declare CREATE OR REPLACE FUNCTION public.logbook_update_gpx_fn(IN _id INTEGER, IN _start text, IN _end text,
log_json jsonb default '{}'::jsonb; OUT _track_gpx XML) RETURNS pg_catalog.xml
runtime_json jsonb default '{}'::jsonb; AS $logbook_update_gpx$
metric_rec record; DECLARE
begin log_rec record;
-- Calculate 'navigation.log' app_settings jsonb;
with BEGIN
start_trip as ( -- If _id is is not NULL and > 0
-- Fetch 'navigation.log' start IF _id IS NULL OR _id < 1 THEN
SELECT key, value RAISE WARNING '-> logbook_update_gpx_fn invalid input %', _id;
FROM api.metrics m, RETURN;
jsonb_each_text(m.metrics) END IF;
WHERE key ILIKE 'navigation.log' AND time = _start::timestamp without time zone AND vessel_id = '76ea3a2d0ae0' -- Gather log details _from_time and _to_time
), SELECT * INTO log_rec
end_trip as ( FROM
-- Fetch 'navigation.log' end api.logbook l
SELECT key, value WHERE l.id = _id;
FROM api.metrics m, -- Ensure the query is successful
jsonb_each_text(m.metrics) IF log_rec.vessel_id IS NULL THEN
WHERE key ILIKE 'navigation.log' AND time = _end::timestamp without time zone AND vessel_id = '76ea3a2d0ae0' RAISE WARNING '-> logbook_update_gpx_fn invalid logbook %', _id;
), RETURN;
nm as ( END IF;
-- calculate distance and convert to nautical miles -- Gathe url from app settings
select ((end_trip.value::NUMERIC - start_trip.value::numeric) / 1.852) as trip from start_trip,end_trip app_settings := get_app_settings_fn();
) --RAISE DEBUG '-> logbook_update_gpx_fn app_settings %', app_settings;
-- Generate JSON -- Generate XML
select jsonb_build_object('navigation.log', trip) into log_json from nm; SELECT xmlelement(name gpx,
raise notice '-> logbook_update_extra_json_fn navigation.log: %', log_json; xmlattributes( '1.1' as version,
'PostgSAIL' as creator,
'http://www.topografix.com/GPX/1/1' as xmlns,
'http://www.opencpn.org' as "xmlns:opencpn",
app_settings->>'app.url' as "xmlns:postgsail",
'http://www.w3.org/2001/XMLSchema-instance' as "xmlns:xsi",
'http://www.garmin.com/xmlschemas/GpxExtensions/v3' as "xmlns:gpxx",
'http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd' as "xsi:schemaLocation"),
xmlelement(name trk,
xmlelement(name name, log_rec.name),
xmlelement(name desc, log_rec.notes),
xmlelement(name link, xmlattributes(concat(app_settings->>'app.url', '/log/', log_rec.id) as href),
xmlelement(name text, log_rec.name)),
xmlelement(name extensions, xmlelement(name "postgsail:log_id", 1),
xmlelement(name "postgsail:link", concat(app_settings->>'app.url','/log/', log_rec.id)),
xmlelement(name "opencpn:guid", uuid_generate_v4()),
xmlelement(name "opencpn:viz", '1'),
xmlelement(name "opencpn:start", log_rec._from_time),
xmlelement(name "opencpn:end", log_rec._to_time)
),
xmlelement(name trkseg, xmlagg(
xmlelement(name trkpt,
xmlattributes(latitude as lat, longitude as lon),
xmlelement(name time, time)
)))))::pg_catalog.xml INTO _track_gpx
FROM api.metrics m
WHERE m.latitude IS NOT NULL
AND m.longitude IS NOT NULL
AND m.time >= log_rec._from_time::TIMESTAMP WITHOUT TIME ZONE
AND m.time <= log_rec._to_time::TIMESTAMP WITHOUT TIME ZONE
AND vessel_id = log_rec.vessel_id;
-- ERROR: column "m.time" must appear in the GROUP BY clause or be used in an aggregate function at character 2304
--ORDER BY m.time ASC;
END;
$logbook_update_gpx$ LANGUAGE plpgsql;
-- Description
COMMENT ON FUNCTION
public.logbook_update_gpx_fn
IS 'Update log details with gpx xml';
-- Calculate engine hours from propulsion.%.runTime CREATE FUNCTION logbook_get_extra_json_fn(IN search TEXT, OUT output_json JSON)
for metric_rec in AS $logbook_get_extra_json$
declare
metric_json jsonb default '{}'::jsonb;
metric_rec record;
BEGIN
-- TODO
-- Calculate 'search' first entry
FOR metric_rec IN
SELECT key, value SELECT key, value
FROM api.metrics m, FROM api.metrics m,
jsonb_each_text(m.metrics) jsonb_each_text(m.metrics)
WHERE key ILIKE 'propulsion.%.runTime' AND time = _start::timestamp without time zone AND vessel_id = '76ea3a2d0ae0' WHERE key ILIKE search
loop AND time = _start::timestamp without time zone
AND vessel_id = current_setting('vessel.id', false)
LOOP
-- Engine Hours in seconds -- Engine Hours in seconds
raise notice '-> logbook_update_extra_json_fn propulsion.*.runTime: %', metric_rec; raise notice '-> logbook_get_extra_json_fn metric: %', metric_rec;
with with
end_runtime as ( end_metric AS (
-- Fetch 'propulsion.*.runTime' end -- Fetch 'tanks.%.currentVolume' last entry
SELECT key, value SELECT key, value
FROM api.metrics m, FROM api.metrics m,
jsonb_each_text(m.metrics) jsonb_each_text(m.metrics)
WHERE key ILIKE metric_rec.key AND time = _end::timestamp without time zone AND vessel_id = '76ea3a2d0ae0' WHERE key ILIKE metric_rec.key
AND time = _end::timestamp without time zone
AND vessel_id = current_setting('vessel.id', false)
), ),
runtime as ( metric AS (
-- calculate runTime Engine Hours in seconds -- Subtract
select (end_runtime.value::numeric - metric_rec.value::numeric) as value from end_runtime SELECT (end_metric.value::numeric - metric_rec.value::numeric) AS value FROM end_metric
) )
-- Generate JSON -- Generate JSON
select jsonb_build_object(metric_rec.key, runtime.value) into runtime_json from runtime; SELECT jsonb_build_object(metric_rec.key, metric.value) INTO metric_json FROM metrics;
raise notice '-> logbook_update_extra_json_fn key: %, value: %', metric_rec.key, runtime_json; raise notice '-> logbook_get_extra_json_fn key: %, value: %', metric_rec.key, metric_json;
end loop; END LOOP;
END;
$logbook_get_extra_json$ LANGUAGE plpgsql;
-- Description
COMMENT ON FUNCTION
public.logbook_get_extra_json_fn
IS 'TODO';
-- Update logbook with extra value and return json CREATE FUNCTION logbook_update_extra_json_fn(IN _id integer, IN _start text, IN _end text,
select COALESCE(log_json::JSONB, '{}'::jsonb) || COALESCE(runtime_json::JSONB, '{}'::jsonb) into _extra_json; OUT _extra_json JSON
raise notice '-> logbook_update_extra_json_fn %', _extra_json; ) AS $logbook_extra_json$
declare
obs_json jsonb default '{ "seaState": -1, "cloudCoverage": -1, "visibility": -1}'::jsonb;
log_json jsonb default '{}'::jsonb;
runtime_json jsonb default '{}'::jsonb;
metrics_json jsonb default '{}'::jsonb;
metric_rec record;
BEGIN
-- Calculate 'navigation.log' metrics
WITH
start_trip as (
-- Fetch 'navigation.log' start, first entry
SELECT key, value
FROM api.metrics m,
jsonb_each_text(m.metrics)
WHERE key ILIKE 'navigation.log'
AND time = _start::timestamp without time zone
AND vessel_id = current_setting('vessel.id', false)
),
end_trip as (
-- Fetch 'navigation.log' end, last entry
SELECT key, value
FROM api.metrics m,
jsonb_each_text(m.metrics)
WHERE key ILIKE 'navigation.log'
AND time = _end::timestamp without time zone
AND vessel_id = current_setting('vessel.id', false)
),
nm as (
-- calculate distance and convert to nautical miles
SELECT ((end_trip.value::NUMERIC - start_trip.value::numeric) / 1.852) as trip from start_trip,end_trip
)
-- Generate JSON
SELECT jsonb_build_object('navigation.log', trip) INTO log_json FROM nm;
raise notice '-> logbook_update_extra_json_fn navigation.log: %', log_json;
-- Calculate engine hours from propulsion.%.runTime first entry
FOR metric_rec IN
SELECT key, value
FROM api.metrics m,
jsonb_each_text(m.metrics)
WHERE key ILIKE 'propulsion.%.runTime'
AND time = _start::timestamp without time zone
AND vessel_id = current_setting('vessel.id', false)
LOOP
-- Engine Hours in seconds
raise notice '-> logbook_update_extra_json_fn propulsion.*.runTime: %', metric_rec;
with
end_runtime AS (
-- Fetch 'propulsion.*.runTime' last entry
SELECT key, value
FROM api.metrics m,
jsonb_each_text(m.metrics)
WHERE key ILIKE metric_rec.key
AND time = _end::timestamp without time zone
AND vessel_id = current_setting('vessel.id', false)
),
runtime AS (
-- calculate runTime Engine Hours in seconds
SELECT (end_runtime.value::numeric - metric_rec.value::numeric) AS value FROM end_runtime
)
-- Generate JSON
SELECT jsonb_build_object(metric_rec.key, runtime.value) INTO runtime_json FROM runtime;
raise notice '-> logbook_update_extra_json_fn key: %, value: %', metric_rec.key, runtime_json;
END LOOP;
-- Update logbook with extra value and return json
SELECT COALESCE(log_json::JSONB, '{}'::jsonb) || COALESCE(runtime_json::JSONB, '{}'::jsonb) INTO metrics_json;
SELECT jsonb_build_object('metrics', metrics_json, 'observations', obs_json) INTO _extra_json;
raise notice '-> logbook_update_extra_json_fn log_json: %, runtime_json: %, _extra_json: %', log_json, runtime_json, _extra_json;
END; END;
$logbook_extra_json$ LANGUAGE plpgsql; $logbook_extra_json$ LANGUAGE plpgsql;
-- Description -- Description
@@ -251,6 +375,7 @@ CREATE OR REPLACE FUNCTION process_logbook_queue_fn(IN _id integer) RETURNS void
log_settings jsonb; log_settings jsonb;
user_settings jsonb; user_settings jsonb;
geojson jsonb; geojson jsonb;
gpx xml;
_invalid_time boolean; _invalid_time boolean;
_invalid_interval boolean; _invalid_interval boolean;
_invalid_distance boolean; _invalid_distance boolean;
@@ -343,7 +468,7 @@ CREATE OR REPLACE FUNCTION process_logbook_queue_fn(IN _id integer) RETURNS void
RAISE WARNING '-> process_logbook_queue_fn delete invalid logbook [%]', logbook_rec.id; RAISE WARNING '-> process_logbook_queue_fn delete invalid logbook [%]', logbook_rec.id;
DELETE FROM api.stays WHERE id = current_stays_id; DELETE FROM api.stays WHERE id = current_stays_id;
RAISE WARNING '-> process_logbook_queue_fn delete invalid stays [%]', current_stays_id; RAISE WARNING '-> process_logbook_queue_fn delete invalid stays [%]', current_stays_id;
-- TODO should we substract (-1) moorages ref count or reprocess it?!? -- TODO should we subtract (-1) moorages ref count or reprocess it?!?
RETURN; RETURN;
END IF; END IF;
@@ -354,7 +479,7 @@ CREATE OR REPLACE FUNCTION process_logbook_queue_fn(IN _id integer) RETURNS void
to_name := reverse_geocode_py_fn('nominatim', logbook_rec._to_lng::NUMERIC, logbook_rec._to_lat::NUMERIC); to_name := reverse_geocode_py_fn('nominatim', logbook_rec._to_lng::NUMERIC, logbook_rec._to_lat::NUMERIC);
SELECT CONCAT(from_name, ' to ' , to_name) INTO log_name; SELECT CONCAT(from_name, ' to ' , to_name) INTO log_name;
-- Generate `propulsion.*.runTime` and `navigation.log` -- Process `propulsion.*.runTime` and `navigation.log`
-- Calculate extra json -- Calculate extra json
extra_json := logbook_update_extra_json_fn(logbook_rec.id, logbook_rec._from_time::TEXT, logbook_rec._to_time::TEXT); extra_json := logbook_update_extra_json_fn(logbook_rec.id, logbook_rec._from_time::TEXT, logbook_rec._to_time::TEXT);
@@ -380,6 +505,13 @@ CREATE OR REPLACE FUNCTION process_logbook_queue_fn(IN _id integer) RETURNS void
track_geojson = geojson track_geojson = geojson
WHERE id = logbook_rec.id; WHERE id = logbook_rec.id;
-- GPX field
gpx := logbook_update_gpx_fn(logbook_rec.id, logbook_rec._from_time::TEXT, logbook_rec._to_time::TEXT);
UPDATE api.logbook
SET
track_gpx = gpx
WHERE id = logbook_rec.id;
-- Prepare notification, gather user settings -- Prepare notification, gather user settings
SELECT json_build_object('logbook_name', log_name, 'logbook_link', logbook_rec.id) into log_settings; SELECT json_build_object('logbook_name', log_name, 'logbook_link', logbook_rec.id) into log_settings;
user_settings := get_user_settings_from_vesselid_fn(logbook_rec.vessel_id::TEXT); user_settings := get_user_settings_from_vesselid_fn(logbook_rec.vessel_id::TEXT);
@@ -389,7 +521,7 @@ CREATE OR REPLACE FUNCTION process_logbook_queue_fn(IN _id integer) RETURNS void
-- Send notification -- Send notification
PERFORM send_notification_fn('logbook'::TEXT, user_settings::JSONB); PERFORM send_notification_fn('logbook'::TEXT, user_settings::JSONB);
-- Process badges -- Process badges
RAISE NOTICE '--> user_settings [%]', user_settings->>'email'::TEXT; RAISE DEBUG '-> debug process_logbook_queue_fn user_settings [%]', user_settings->>'email'::TEXT;
PERFORM set_config('user.email', user_settings->>'email'::TEXT, false); PERFORM set_config('user.email', user_settings->>'email'::TEXT, false);
PERFORM badges_logbook_fn(logbook_rec.id); PERFORM badges_logbook_fn(logbook_rec.id);
PERFORM badges_geom_fn(logbook_rec.id); PERFORM badges_geom_fn(logbook_rec.id);

View File

@@ -156,7 +156,6 @@ AS $version$
_appv TEXT; _appv TEXT;
_sysv TEXT; _sysv TEXT;
BEGIN BEGIN
-- Add postgrest version https://postgrest.org/en/v11.2/references/admin.html#server-version
SELECT SELECT
value, rtrim(substring(version(), 0, 17)) AS sys_version into _appv,_sysv value, rtrim(substring(version(), 0, 17)) AS sys_version into _appv,_sysv
FROM app_settings FROM app_settings
@@ -164,7 +163,8 @@ AS $version$
RETURN json_build_object('api_version', _appv, RETURN json_build_object('api_version', _appv,
'sys_version', _sysv, 'sys_version', _sysv,
'timescaledb', (SELECT extversion as timescaledb FROM pg_extension WHERE extname='timescaledb'), 'timescaledb', (SELECT extversion as timescaledb FROM pg_extension WHERE extname='timescaledb'),
'postgis', (SELECT extversion as postgis FROM pg_extension WHERE extname='postgis')); 'postgis', (SELECT extversion as postgis FROM pg_extension WHERE extname='postgis'),
'postgrest', (SELECT rtrim(substring(application_name from 'PostgREST [0-9.]+')) as postgrest FROM pg_stat_activity WHERE application_name ilike '%postgrest%' LIMIT 1));
END; END;
$version$ language plpgsql security definer; $version$ language plpgsql security definer;
-- Description -- Description
@@ -174,13 +174,13 @@ COMMENT ON FUNCTION
DROP VIEW IF EXISTS api.versions_view; DROP VIEW IF EXISTS api.versions_view;
CREATE OR REPLACE VIEW api.versions_view AS CREATE OR REPLACE VIEW api.versions_view AS
-- Add postgrest version https://postgrest.org/en/v11.2/references/admin.html#server-version
SELECT SELECT
value AS api_version, value AS api_version,
--version() as sys_version --version() as sys_version
rtrim(substring(version(), 0, 17)) AS sys_version, rtrim(substring(version(), 0, 17)) AS sys_version,
(SELECT extversion as timescaledb FROM pg_extension WHERE extname='timescaledb'), (SELECT extversion as timescaledb FROM pg_extension WHERE extname='timescaledb'),
(SELECT extversion as postgis FROM pg_extension WHERE extname='postgis') (SELECT extversion as postgis FROM pg_extension WHERE extname='postgis'),
(SELECT rtrim(substring(application_name from 'PostgREST [0-9.]+')) as postgrest FROM pg_stat_activity WHERE application_name ilike '%postgrest%' limit 1)
FROM app_settings FROM app_settings
WHERE name = 'app.version'; WHERE name = 'app.version';
-- Description -- Description

View File

@@ -1 +1 @@
0.2.2 0.2.3

1
openapi.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -5,4 +5,3 @@ ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get -q update && apt-get -qy upgrade && apt-get -qy install postgresql-client RUN apt-get -q update && apt-get -qy upgrade && apt-get -qy install postgresql-client
# Clean up APT when done. # Clean up APT when done.
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

822
tests/index.js Normal file
View File

@@ -0,0 +1,822 @@
'use strict';
/*
* Unit test #1
* Create 2 users and 2 associate vessel with metrics
*
* process.env.PGSAIL_API_URI = from inside the docker
*
* npm install supertest should mocha mochawesome moment
* alias mocha="./node_modules/mocha/bin/_mocha"
* mocha index.js --reporter mochawesome --reporter-options reportDir=/mnt/postgsail/,reportFilename=report_api.html
*
*/
const sleep = ms => new Promise(r => setTimeout(r, ms));
const supertest = require("supertest");
// Deprecated
const should = require("should");
//const chai = require("chai");
//const should = chai.should();
let request = null;
let user_jwt = null;
let vessel_jwt = null;
var moment = require('moment');
const metrics_kapla = require('./metrics_sample_kapla.json');
const metrics_aava = require('./metrics_sample_aava.json');
const fs = require('fs');
// CNAMEs Array
[
{ cname: process.env.PGSAIL_API_URI, name: "PostgSail unit test kapla",
signin: { email: 'demo+kapla@openplotter.cloud', pass: 'test', firstname:'First_kapla', lastname:'Last_kapla'},
login: { email: 'demo+kapla@openplotter.cloud', pass: 'test'},
vessel: { vessel_email: "demo+kapla@openplotter.cloud", vessel_mmsi: "test", vessel_name: "kapla"},
preferences: { key: '{email_notifications}', value: false }, /* Disable email_notifications */
vessel_metadata: {
name: "kapla",
mmsi: "123456789",
client_id: "vessels.urn:mrn:signalk:uuid:5b4f7543-7153-4840-b139-761310b242fd",
length: "12",
beam: "10",
height: "24",
ship_type: "36",
plugin_version: "0.0.1",
signalk_version: "signalk_version",
time: moment.utc().subtract(69, 'minutes').format()
/* To trigger monitor_offline quickly */
},
vessel_metrics: metrics_kapla,
user_tables: [
{ url: '/stays', res_body_length: 3},
// not processed yet, { url: '/moorages', res_body_length: 2},
{ url: '/logbook', res_body_length: 2},
{ url: '/metadata', res_body_length: 1}
],
user_views: [
// not processed yet, { url: '/stays_view', res_body_length: 1},
// not processed yet, { url: '/moorages_view', res_body_length: 1},
{ url: '/logs_view', res_body_length: 2},
{ url: '/log_view', res_body_length: 2},
//{ url: '/stats_view', res_body_length: 1},
{ url: '/vessels_view', res_body_length: 1},
],
user_patchs: [
{ url: '/logbook?id=eq.1',
patch: {
name: "patch log name",
notes: "new log note"
},
},
{ url: '/stays?id=eq.1',
patch: {
name: "patch stay name",
stay_code: 2,
notes: "new stay note"
},
},
/* not processed yet, { url: '/moorages?id=eq.1',
patch: {
name: "patch moorage name",
home_flag: true,
stay_code: 2,
notes: "new moorage note"
},
}
*/
],
user_fn: [
{ url: '/rpc/timelapse_fn',
payload: {
start_log: 1
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_geojson_fn',
payload: {
_id: 1
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_gpx_fn',
payload: {
_id: 1
},
res: {
obj_name: null
}
},
{ url: '/rpc/vessel_fn',
payload: null,
res: {
obj_name: 'vessel'
}
},
{ url: '/rpc/settings_fn',
payload: null,
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/versions_fn',
payload: null,
res: {
obj_name: 'versions'
}
}
],
otp_fn: [
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+kapla@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/email_fn',
payload: { token: null },
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+kapla@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/pushover_fn',
payload: { token: null, pushover_user_key: '1234567890azerty!'},
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+kapla@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/telegram_fn',
payload: { token: null, telegram_obj: {"chat": {"id": 1234567890, "type": "private", "title": null, "all_members_are_administrators": null}, "date": "NOW", "from": {"id": 1234567890, "is_bot": false, "first_name": "Kapla", "language_code": "en"}} },
res: {
obj_name: 'settings'
}
}
]
},
{ cname: process.env.PGSAIL_API_URI, name: "PostgSail unit test, aava",
signin: { email: 'demo+aava@openplotter.cloud', pass: 'test', firstname:'first_aava', lastname:'last_aava'},
login: { email: 'demo+aava@openplotter.cloud', pass: 'test'},
vessel: { vessel_email: "demo+aava@openplotter.cloud", vessel_mmsi: "787654321", vessel_name: "aava"},
preferences: { key: '{email_notifications}', value: false }, /* Disable email_notifications */
vessel_metadata: {
name: "aava",
mmsi: "787654321",
client_id: "vessels.urn:mrn:imo:mmsi:787654321",
length: "12",
beam: "10",
height: "24",
ship_type: "37",
plugin_version: "1.0.2",
signalk_version: "1.20.0",
time: moment().subtract(69, 'minutes').format()
},
vessel_metrics: metrics_aava,
user_tables: [
{ url: '/stays', res_body_length: 2},
// not processed yet, { url: '/moorages', res_body_length: 2},
{ url: '/logbook', res_body_length: 1},
{ url: '/metadata', res_body_length: 1}
],
user_views: [
// not processed yet, { url: '/stays_view', res_body_length: 1},
// not processed yet, { url: '/moorages_view', res_body_length: 1},
{ url: '/logs_view', res_body_length: 1},
{ url: '/log_view', res_body_length: 1},
//{ url: '/stats_view', res_body_length: 1},
{ url: '/vessels_view', res_body_length: 1},
],
user_patchs: [
{ url: '/logbook?id=eq.3',
patch: {
name: "patch log name",
notes: "new log note"
},
},
{ url: '/stays?id=eq.4',
patch: {
name: "patch stay name",
stay_code: 2,
notes: "new stay note"
},
},
/* not processed yet, { url: '/moorages?id=eq.1',
patch: {
name: "patch moorage name",
home_flag: true,
stay_code: 2,
notes: "new moorage note"
},
}
*/
],
user_fn: [
{ url: '/rpc/timelapse_fn',
payload: {
start_log: 3
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_geojson_fn',
payload: {
_id: 3
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_gpx_fn',
payload: {
_id: 3
},
res: {
obj_name: null
}
},
{ url: '/rpc/vessel_fn',
payload: null,
res: {
obj_name: 'vessel'
}
},
{ url: '/rpc/settings_fn',
payload: null,
res: {
obj_name: 'settings'
}
}
],
otp_fn: [
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+aava@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/email_fn',
payload: { token: null },
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+aava@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/pushover_fn',
payload: { token: null, pushover_user_key: '0987654321qwerty!'},
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+aava@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/telegram_fn',
payload: { token: null, telegram_obj: {"chat": {"id": 9876543210, "type": "private", "title": null, "all_members_are_administrators": null}, "date": "NOW", "from": {"id": 9876543210, "is_bot": false, "first_name": "Aava", "language_code": "en"}} },
res: {
obj_name: 'settings'
}
},
]
}
].forEach( function(test){
//console.log(`${test.cname}`);
describe(`${test.name}`, function(){
request = supertest.agent(test.cname);
request.set('User-Agent', 'PostgSail unit tests');
describe("OpenAPI description", function(){
it('/', function(done) {
request = supertest.agent(test.cname);
request
.get('/')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.paths['/rpc/signup']);
should.exist(res.body.paths['/rpc/login']);
should.exist(res.body.paths['/rpc/reset']);
should.exist(res.body.paths['/rpc/recover']);
//should.exist(res.body.paths['/rpc/generate_otp_fn']);
should.exist(res.body.paths['/rpc/pushover_fn']);
should.exist(res.body.paths['/rpc/telegram_fn']);
should.exist(res.body.paths['/rpc/telegram']);
done(err);
});
});
}); // OpenAPI description
describe("Get JWT user_role", function(){
it('/rpc/signup return user_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/signup')
.send(test.signin)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
user_jwt = res.body.token;
should.exist(user_jwt);
done(err);
});
});
it('/rpc/login return user_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/login')
.send(test.login)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
//res.body.token.should.match(user_jwt);
console.log(user_jwt);
should.exist(user_jwt);
done(err);
});
});
}); // JWT user_role
describe("OpenAPI with JWT user_role", function(){
it('/', function(done) {
request = supertest.agent(test.cname);
request
.get('/')
.set('Authorization', `Bearer ${user_jwt}`)
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
// Functions
should.exist(res.body.paths['/rpc/register_vessel']);
should.exist(res.body.paths['/rpc/update_user_preferences_fn']);
should.exist(res.body.paths['/rpc/settings_fn']);
should.exist(res.body.paths['/rpc/versions_fn']);
// Tables
should.exist(res.body.paths['/metadata']);
should.exist(res.body.paths['/metrics']);
should.exist(res.body.paths['/logbook']);
should.exist(res.body.paths['/stays']);
should.exist(res.body.paths['/moorages']);
// Views
should.exist(res.body.paths['/logs_view']);
should.exist(res.body.paths['/moorages_view']);
should.exist(res.body.paths['/stays_view']);
should.exist(res.body.paths['/vessels_view']);
//should.exist(res.body.paths['/stats_view']);
should.exist(res.body.paths['/monitoring_view']);
done(err);
});
});
}); // OpenAPI JWT user_role
describe("Set preferences email_notifications, JWT user_role", function(){
it('/rpc/update_user_preferences_fn return true', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/update_user_preferences_fn')
.send(test.preferences)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.text);
should.exist(res.text);
res.text.should.match('true');
done(err);
});
});
}); // JWT user_role
describe("Get versions, JWT user_role", function(){
it('/rpc/versions_fn return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get('/rpc/versions_fn')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.text);
should.exist(res.body.api_version);
should.exist(res.body.sys_version);
done(err);
});
});
}); // JWT user_role
describe("Get JWT vessel_role from user_role", function(){
it('/rpc/register_vessel return vessel_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/register_vessel')
.send(test.vessel)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
vessel_jwt = res.body.token;
console.log(vessel_jwt);
should.exist(vessel_jwt);
// Save vessel JWT token for later use.
fs.writeFile(`vessel_jwt_${test.vessel.vessel_name}.txt`, vessel_jwt, (err) => {
// In case of a error throw err.
if (err) throw err;
})
done(err);
});
});
}); // JWT user_role
describe("OpenAPI with JWT vessel_role", function(){
it('/', function(done) {
request = supertest.agent(test.cname);
request
.get('/')
.set('Authorization', `Bearer ${vessel_jwt}`)
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.paths['/metadata']);
should.exist(res.body.paths['/metrics']);
should.exist(res.body.paths['/logbook']);
should.exist(res.body.paths['/stays']);
should.exist(res.body.paths['/moorages']);
done(err);
});
});
}); // OpenAPI JWT vessel_role
describe("Get vessel details view, JWT user_role", function(){
it('/vessels_view return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get('/vessels_view')
.set('Authorization', `Bearer ${user_jwt}`)
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
console.log(res.body);
//res.body.length.should.match(0);
res.body.length.should.match(1);
//res.body[0].last_contact.should.match('Never');
should.equal(res.body[0].last_contact, null);
done(err);
});
});
}); // JWT user_role
describe("Get vessel details function, JWT user_role", function(){
// no metadata from vessel so error - unrecognized configuration parameter "vessel.client_id"
it('/rpc/vessel_fn return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get('/rpc/vessel_fn')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.end(function(err,res){
console.log(res.body)
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
//body = res.body;
//console.log(res.text);
done(err);
});
});
}); // JWT user_role
describe("Vessel POST metadata, JWT vessel_role", function(){
it('/metadata?on_conflict=vessel_id', function(done) {
request = supertest.agent(test.cname);
request
.post('/metadata?on_conflict=vessel_id')
.send(test.vessel_metadata)
.set('Authorization', `Bearer ${vessel_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.set('Prefer', 'return=headers-only,resolution=merge-duplicates')
.end(function(err,res){
res.status.should.equal(201);
//console.log(res.header);
should.exist(res.header['server']);
res.header['server'].should.match(new RegExp('postgrest','g'));
done(err);
});
});
}); // Vessel metadata JWT vessel_role
describe("Vessel POST metrics, JWT vessel_role", function(){
let data = [];
//console.log(vessel_metrics['metrics'][0]);
let i;
for (i = 0; i < test.vessel_metrics['metrics'].length; i++) {
data[i] = test.vessel_metrics['metrics'][i];
// Override time, -2h to allow to new data later without delay.
data[i]['time'] = moment.utc().subtract(2, 'hours').add(i, 'minutes').format();
// Override client_id
data[i]['client_id'] = test.vessel_metadata.client_id;
}
// Force last entry to be back in time from previous, it should be ignore silently
data.at(-1).time = moment.utc(data.at(-2).time).subtract(1, 'minutes').format();
//console.log(data[0]);
it('/metrics?select=time', function(done) {
request = supertest.agent(test.cname);
request
.post('/metrics?select=time')
.send(data)
.set('Authorization', `Bearer ${vessel_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.set('Prefer', 'return=representation')
.end(function(err,res){
//console.log(res.body);
res.status.should.equal(201);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
res.body.length.should.match(test.vessel_metrics['metrics'].length-1);
done(err);
});
});
}); // Vessel POST metrics JWT vessel_role
/*
describe("run_cron_jobs() JWT vessel_role", function(){
it('/rpc/run_cron_jobs', function(done) {
request = supertest.agent(test.cname);
request
.get('/rpc/run_cron_jobs')
.set('Authorization', `Bearer ${vessel_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
done();
});
});
}); // run_cron_jobs() JWT vessel_role
*/
describe("Table endpoint, JWT user_role", function(){
test.user_tables.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get(`${subtest.url}`)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
res.body.length.should.match(subtest.res_body_length);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Table endpoint
describe("Views endpoint, JWT user_role", function(){
test.user_views.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get(`${subtest.url}`)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
res.body.length.should.match(subtest.res_body_length);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Views endpoint
describe("Patch endpoint, JWT user_role", function(){
test.user_patchs.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.patch(subtest.url)
.send(subtest.patch)
.set('Content-Type', 'application/json')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(204);
should.exist(res.header['server']);
res.header['server'].should.match(new RegExp('postgrest','g'));
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Patch endpoint
describe("Function endpoint, JWT user_role", function(){
test.user_fn.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//should.exist(res.body);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Function endpoint
/*
describe("Function OTP endpoint, JWT user_role", function(){
let otp = null;
test.otp_fn.forEach(function (subtest) {
otp = null;
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res}`);
if (otp) {
subtest.payload.token = otp;
}
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
console.log(res.body);
should.exist(res.body);
if (subtest.url == '/rpc/generate_otp_fn') {
otp = res.body;
} else {
res.text.should.match('true');
otp = null;
}
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Function OTP endpoint
*/
}); // OpenAPI description
}); // CNAMEs Array

645
tests/index2.js Normal file
View File

@@ -0,0 +1,645 @@
'use strict';
/*
* Unit test #2, additional aava sample vessel metrics
*
* process.env.PGSAIL_API_URI = from inside the docker
*
* npm install supertest should mocha mochawesome moment
* alias mocha="./node_modules/mocha/bin/_mocha"
* mocha index.js --reporter mochawesome --reporter-options reportDir=/mnt/postgsail/,reportFilename=report_api.html
*
*/
const supertest = require("supertest");
const should = require("should");
let request = null;
let user_jwt = null;
let vessel_jwt = null;
var moment = require('moment');
const metrics_simulator = require('./metrics_sample_simulator.json');
// CNAMEs Array
[
{ cname: process.env.PGSAIL_API_URI, name: "PostgSail unit test 2, aava",
signin: { email: 'demo+aava@openplotter.cloud', pass: 'test', firstname:'first_aava', lastname:'last_aava'},
login: { email: 'demo+aava@openplotter.cloud', pass: 'test'},
vessel: { vessel_email: "demo+aava@openplotter.cloud", vessel_mmsi: "787654321", vessel_name: "aava"},
preferences: { key: '{email_notifications}', value: false }, /* Disable email_notifications */
vessel_metadata: {
name: "aava",
mmsi: "787654321",
client_id: "vessels.urn:mrn:imo:mmsi:787654321",
length: "12",
beam: "10",
height: "24",
ship_type: "37",
plugin_version: "1.0.2",
signalk_version: "1.20.0",
time: moment().subtract(69, 'minutes').format()
},
vessel_metrics: metrics_simulator,
user_tables: [
{ url: '/stays', res_body_length: 3},
// not processed yet, { url: '/moorages', res_body_length: 2},
{ url: '/logbook', res_body_length: 2},
{ url: '/metadata', res_body_length: 1}
],
user_views: [
// not processed yet, { url: '/stays_view', res_body_length: 1},
// not processed yet, { url: '/moorages_view', res_body_length: 1},
{ url: '/logs_view', res_body_length: 2},
{ url: '/log_view', res_body_length: 2},
//{ url: '/stats_view', res_body_length: 1},
{ url: '/vessels_view', res_body_length: 1},
],
user_patchs: [
{ url: '/logbook?id=eq.4',
patch: {
name: "patch log name 2",
notes: "new log note 2"
},
},
{ url: '/stays?id=eq.5',
patch: {
name: "patch stay name 2",
stay_code: 2,
notes: "new stay note 2"
},
},
/* not processed yet, { url: '/moorages?id=eq.1',
patch: {
name: "patch moorage name",
home_flag: true,
stay_code: 2,
notes: "new moorage note"
},
}
*/
],
user_fn: [
{ url: '/rpc/timelapse_fn',
payload: {
start_log: 4
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_geojson_fn',
payload: {
_id: 4
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_gpx_fn',
payload: {
_id: 4
},
res: {
obj_name: null
}
},
{ url: '/rpc/vessel_fn',
payload: null,
res: {
obj_name: 'vessel'
}
},
{ url: '/rpc/settings_fn',
payload: null,
res: {
obj_name: 'settings'
}
}
],
others_fn: [
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+aava@openplotter.cloud' },
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/pushover_fn',
// invalid key to avoid trigger notification
payload: { token: 'zxy', pushover_test_key: '987azerty#'},
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/update_user_preferences_fn',
//payload: { key: '{xyz}', value: '987azerty#'},
// invalid key to avoid trigger notification
payload: { key: '{telegram_test}', value: '{"id": 987654321, "is_bot": false, "first_name": "aaVa", "language_code": "en"}' },
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/bot',
payload: { email: 'demo+aava@openplotter.cloud', chat_id: 987654321},
res: {
obj_name: 'settings'
}
}
]
}
].forEach( function(test){
//console.log(`${test.cname}`);
describe(`${test.name}`, function(){
request = supertest.agent(test.cname);
request.set('User-Agent', 'PostgSail unit tests');
describe("OpenAPI description", function(){
it('/', function(done) {
request = supertest.agent(test.cname);
request
.get('/')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.paths['/rpc/signup']);
should.exist(res.body.paths['/rpc/login']);
//should.exist(res.body.paths['/rpc/generate_otp_fn']);
should.exist(res.body.paths['/rpc/pushover_fn']);
should.exist(res.body.paths['/rpc/telegram_fn']);
//should.exist(res.body.paths['/rpc/bot']);
done(err);
});
});
}); // OpenAPI description
describe("Get JWT user_role", function(){
it('/rpc/signup return user_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/signup')
.send(test.signin)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
user_jwt = res.body.token;
should.exist(user_jwt);
done(err);
});
});
it('/rpc/login return user_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/login')
.send(test.login)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
res.body.token.should.match(user_jwt);
console.log(user_jwt);
should.exist(user_jwt);
done(err);
});
});
}); // JWT user_role
describe("OpenAPI with JWT user_role", function(){
it('/', function(done) {
request = supertest.agent(test.cname);
request
.get('/')
.set('Authorization', `Bearer ${user_jwt}`)
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
// Function
should.exist(res.body.paths['/rpc/register_vessel']);
should.exist(res.body.paths['/rpc/update_user_preferences_fn']);
should.exist(res.body.paths['/rpc/settings_fn']);
should.exist(res.body.paths['/rpc/versions_fn']);
// Tables
should.exist(res.body.paths['/metadata']);
should.exist(res.body.paths['/metrics']);
should.exist(res.body.paths['/logbook']);
should.exist(res.body.paths['/stays']);
should.exist(res.body.paths['/moorages']);
// Views
should.exist(res.body.paths['/logs_view']);
should.exist(res.body.paths['/moorages_view']);
should.exist(res.body.paths['/stays_view']);
should.exist(res.body.paths['/vessels_view']);
// should.exist(res.body.paths['/stats_view']);
should.exist(res.body.paths['/monitoring_view']);
done(err);
});
});
}); // OpenAPI JWT user_role
describe("Set preferences email_notifications, JWT user_role", function(){
it('/rpc/update_user_preferences_fn return true', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/update_user_preferences_fn')
.send(test.preferences)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.text);
should.exist(res.text);
res.text.should.match('true');
done(err);
});
});
}); // JWT user_role
describe("Get versions, JWT user_role", function(){
it('/rpc/versions_fn return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get('/rpc/versions_fn')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.text);
should.exist(res.body.api_version);
should.exist(res.body.sys_version);
done(err);
});
});
}); // JWT user_role
describe("Get JWT vessel_role from user_role", function(){
it('/rpc/register_vessel return vessel_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/register_vessel')
.send(test.vessel)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
vessel_jwt = res.body.token;
console.log(vessel_jwt);
should.exist(vessel_jwt);
done(err);
});
});
}); // JWT user_role
describe("OpenAPI with JWT vessel_role", function(){
it('/', function(done) {
request = supertest.agent(test.cname);
request
.get('/')
.set('Authorization', `Bearer ${vessel_jwt}`)
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.paths['/metadata']);
should.exist(res.body.paths['/metrics']);
should.exist(res.body.paths['/logbook']);
should.exist(res.body.paths['/stays']);
should.exist(res.body.paths['/moorages']);
done(err);
});
});
}); // OpenAPI JWT vessel_role
describe("Get vessel details view, JWT user_role", function(){
it('/vessels_view return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get('/vessels_view')
.set('Authorization', `Bearer ${user_jwt}`)
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
console.log(res.body);
//res.body.length.should.match(0);
res.body.length.should.match(1);
//res.body[0].last_contact.should.match('Never');
should.exist(res.body[0].last_contact);
done(err);
});
});
}); // JWT user_role
describe("Get vessel details function, JWT user_role", function(){
it('/rpc/vessel_fn return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/vessel_fn')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//should.exist(res.body);
//body = res.body;
console.log(res.text);
done(err);
});
});
}); // JWT user_role
describe("Vessel POST metadata, JWT vessel_role", function(){
it('/metadata', function(done) {
request = supertest.agent(test.cname);
request
.post('/metadata')
.send(test.vessel_metadata)
.set('Authorization', `Bearer ${vessel_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.set('Prefer', 'return=headers-only')
.end(function(err,res){
res.status.should.equal(201);
//console.log(res.header);
should.exist(res.header['server']);
res.header['server'].should.match(new RegExp('postgrest','g'));
done(err);
});
});
}); // Vessel metadata JWT vessel_role
describe("Vessel POST metrics, JWT vessel_role", function(){
let data = [];
//console.log(vessel_metrics['metrics'][0]);
let i;
for (i = 0; i < test.vessel_metrics['metrics'].length; i++) {
data[i] = test.vessel_metrics['metrics'][i];
// Override time, +1h because previous sample include 47 entry.
data[i]['time'] = moment().add(1, 'hour').add(i, 'minutes').format();
// Override client_id
data[i]['client_id'] = test.vessel_metadata.client_id;
}
console.log(data[0]);
it('/metrics?select=time', function(done) {
request = supertest.agent(test.cname);
request
.post('/metrics?select=time')
.send(data)
.set('Authorization', `Bearer ${vessel_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.set('Prefer', 'return=representation')
.end(function(err,res){
//console.log(res.body);
res.status.should.equal(201);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
res.body.length.should.match(test.vessel_metrics['metrics'].length);
done(err);
});
});
}); // Vessel POST metrics JWT vessel_role
/*
describe("run_cron_jobs() JWT vessel_role", function(){
it('/rpc/run_cron_jobs', function(done) {
request = supertest.agent(test.cname);
request
.get('/rpc/run_cron_jobs')
.set('Authorization', `Bearer ${vessel_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
done();
});
});
}); // run_cron_jobs() JWT vessel_role
*/
describe("Table endpoint, JWT user_role", function(){
test.user_tables.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get(`${subtest.url}`)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
res.body.length.should.match(subtest.res_body_length);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Table endpoint
describe("Views endpoint, JWT user_role", function(){
test.user_views.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get(`${subtest.url}`)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
res.body.length.should.match(subtest.res_body_length);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Views endpoint
describe("Patch endpoint, JWT user_role", function(){
test.user_patchs.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.patch(subtest.url)
.send(subtest.patch)
.set('Content-Type', 'application/json')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(204);
should.exist(res.header['server']);
res.header['server'].should.match(new RegExp('postgrest','g'));
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Patch endpoint
describe("Function user_fn endpoint, JWT user_role", function(){
test.user_fn.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//should.exist(res.body);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Function endpoint
/*
describe("Function others endpoint, JWT user_role", function(){
let otp = null;
test.others_fn.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.body);
should.exist(res.body);
if (subtest.url == '/rpc/generate_otp_fn') {
otp = res.body.text();
}
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Function endpoint
*/
}); // OpenAPI description
}); // CNAMEs Array

802
tests/index3.js Normal file
View File

@@ -0,0 +1,802 @@
'use strict';
/*
* Unit test #3, check post cron results, moorages, stays and stats
*
* process.env.PGSAIL_API_URI = from inside the docker
*
* npm install supertest should mocha mochawesome moment
* alias mocha="./node_modules/mocha/bin/_mocha"
* mocha index.js --reporter mochawesome --reporter-options reportDir=/mnt/postgsail/,reportFilename=report_api.html
*
*/
const supertest = require("supertest");
// Deprecated
const should = require("should");
//const chai = require("chai");
//const should = chai.should();
let request = null;
let user_jwt = null;
let vessel_jwt = null;
var moment = require('moment');
// CNAMEs Array
[
{ cname: process.env.PGSAIL_API_URI, name: "PostgSail unit test kapla",
signin: { email: 'demo+kapla@openplotter.cloud', pass: 'test', firstname:'First_kapla', lastname:'Last_kapla'},
login: { email: 'demo+kapla@openplotter.cloud', pass: 'test'},
vessel: { vessel_email: "demo+kapla@openplotter.cloud", vessel_mmsi: null, vessel_name: "kapla"},
preferences: { key: '{email_notifications}', value: false }, /* Disable email_notifications */
vessel_metadata: {
name: "kapla",
mmsi: "123456789",
client_id: "vessels.urn:mrn:imo:mmsi:123456789",
length: "12",
beam: "10",
height: "24",
ship_type: "36",
plugin_version: "0.0.1",
signalk_version: "1.12.0",
time: moment().subtract(69, 'minutes').format()
/* To trigger monitor_offline quickly */
},
user_tables: [
{ url: '/stays', res_body_length: 3},
{ url: '/moorages', res_body_length: 2},
{ url: '/logbook', res_body_length: 2},
{ url: '/metadata', res_body_length: 1}
],
user_views: [
{ url: '/stays_view', res_body_length: 2},
{ url: '/moorages_view', res_body_length: 2},
{ url: '/logs_view', res_body_length: 2},
{ url: '/log_view', res_body_length: 2},
//{ url: '/stats_view', res_body_length: 1},
{ url: '/vessels_view', res_body_length: 1},
],
user_patchs: [
{ url: '/logbook?id=eq.1',
patch: {
name: "patch log name 3",
notes: "new log note 3"
},
},
{ url: '/stays?id=eq.1',
patch: {
name: "patch stay name 3",
stay_code: 2,
notes: "new stay note 3"
},
},
{ url: '/moorages?id=eq.1',
patch: {
name: "patch moorage name 3",
home_flag: true,
stay_code: 2,
notes: "new moorage note 3"
},
}
],
user_fn: [
{ url: '/rpc/timelapse_fn',
payload: {
start_log: 2
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_geojson_fn',
payload: {
_id: 2
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_gpx_fn',
payload: {
_id: 2
},
res: {
obj_name: null
}
},
{ url: '/rpc/export_moorages_geojson_fn',
payload: {},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_moorages_gpx_fn',
payload: {},
res: {
obj_name: null
}
},
{ url: '/rpc/find_log_from_moorage_fn',
payload: {
_id: 2
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/find_log_to_moorage_fn',
payload: {
_id: 2
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/vessel_fn',
payload: null,
res: {
obj_name: 'vessel'
}
},
{ url: '/rpc/settings_fn',
payload: null,
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/versions_fn',
payload: null,
res: {
obj_name: 'versions'
}
},
{ url: '/rpc/stats_logs_fn',
payload: {},
res: {
obj_name: 'stats'
}
},
{ url: '/rpc/stats_logs_fn',
payload: {
start_date: '2022-01-01',
end_date: '2022-06-12'
},
res: {
obj_name: null
}
},
],
email_otp_fn: [
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+kapla@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/email_fn',
//payload: { token: 'abc', pushover_user_key: '123qwerty!'},
// invalid key to avoid trigger notification
payload: { token: '123456' },
res: {
obj_name: 'settings'
}
}
],
pushover_fn: [
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+kapla@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/pushover_fn',
//payload: { token: 'abc', pushover_user_key: '123qwerty!'},
// invalid key to avoid trigger notification
payload: { token: null, pushover_test_key: '123qwerty!'},
res: {
obj_name: 'settings'
}
}
],
telegram_fn: [
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+kapla@openplotter.cloud' },
res: {
otp: 0
}
},
{ url: '/rpc/telegram_fn',
//payload: { key: '{abc}', value: {"a": "1", "b": 2, "c": true}},
// invalid key to avoid trigger notification
payload: { token: null, telegram_test: '{"id": 123456789, "is_bot": false, "first_name": "kaplA", "language_code": "en"}' },
res: {
obj_name: 'settings'
}
}
]
},
{ cname: process.env.PGSAIL_API_URI, name: "PostgSail unit test, aava",
signin: {email: 'demo+aava@openplotter.cloud', pass: 'test', firstname:'first_aava', lastname:'last_aava'},
login: {email: 'demo+aava@openplotter.cloud', pass: 'test'},
vessel: {vessel_email: "demo+aava@openplotter.cloud", vessel_mmsi: null, vessel_name: "aava"},
preferences: { key: '{email_notifications}', value: false }, /* Disable email_notifications */
vessel_metadata: {
name: "aava",
mmsi: "787654321",
client_id: "vessels.urn:mrn:imo:mmsi:787654321",
length: "12",
beam: "10",
height: "24",
ship_type: "37",
plugin_version: "1.0.2",
signalk_version: "1.20.0",
time: moment().subtract(69, 'minutes').format()
},
user_tables: [
{ url: '/stays', res_body_length: 3},
{ url: '/moorages', res_body_length: 2},
{ url: '/logbook', res_body_length: 2},
{ url: '/metadata', res_body_length: 1}
],
user_views: [
{ url: '/stays_view', res_body_length: 2},
{ url: '/moorages_view', res_body_length: 2},
{ url: '/logs_view', res_body_length: 2},
{ url: '/log_view', res_body_length: 2},
//{ url: '/stats_view', res_body_length: 1},
{ url: '/vessels_view', res_body_length: 1},
],
user_patchs: [
{ url: '/logbook?id=eq.4',
patch: {
name: "patch log name 4",
notes: "new log note 4"
},
},
{ url: '/stays?id=eq.4',
patch: {
name: "patch stay name 4",
stay_code: 2,
notes: "new stay note 4"
},
},
{ url: '/moorages?id=eq.4',
patch: {
name: "patch moorage name",
home_flag: true,
stay_code: 2,
notes: "new moorage note"
},
}
],
user_fn: [
{ url: '/rpc/timelapse_fn',
payload: {
start_log: 4
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_geojson_fn',
payload: {
_id: 4
},
res: {
obj_name: 'geojson'
}
},
{ url: '/rpc/export_logbook_gpx_fn',
payload: {
_id: 4
},
res: {
obj_name: null
}
},
{ url: '/rpc/export_moorages_geojson_fn',
payload: {},
res: {
geojson: { type: 'FeatureCollection', features: [ [Object], [Object] ] }
}
},
{ url: '/rpc/export_moorages_gpx_fn',
payload: {},
res: {
obj_name: null
}
},
{ url: '/rpc/find_log_from_moorage_fn',
payload: {
_id: 4
},
res: { geojson: { type: 'FeatureCollection', features: [ [Object] ] } }
},
{ url: '/rpc/find_log_to_moorage_fn',
payload: {
_id: 4
},
res: { geojson: { type: 'FeatureCollection', features: [ [Object] ] } }
},
{ url: '/rpc/vessel_fn',
payload: null,
res: {
vessel: {
beam: 10,
mmsi: 787654321,
name: 'aava',
height: 24,
length: 37,
alpha_2: null,
country: null,
geojson: { type: 'Feature', geometry: [Object], properties: [Object] },
ship_type: 'Pleasure Craft',
created_at: '2023-08-17T16:32:13',
last_contact: '2023-08-17T15:23:14'
}
}
},
{ url: '/rpc/settings_fn',
payload: null,
res: {
settings: {
email: 'demo+aava@openplotter.cloud',
first: 'first_aava',
last: 'last_aava',
preferences: { badges: [Object], email_notifications: false },
created_at: '2023-08-17T16:32:12.701788',
username: 'F Last_Aava',
has_vessel: true
}
}
},
{ url: '/rpc/stats_logs_fn',
payload: {},
res: { // Compare keys only
stats: {
count: 2,
max_speed: 7.1,
max_distance: 8.2365,
max_duration: '01:11:00',
max_speed_id: 3,
sum_duration: '01:54:00',
max_wind_speed: 44.2,
max_distance_id: 3,
max_wind_speed_id: 4
}
}
},
{ url: '/rpc/stats_logs_fn',
payload: {
start_date: '2022-01-01',
end_date: '2022-06-12'
},
res: { stats: null }
},
],
others_fn: [
{ url: '/rpc/generate_otp_fn',
payload: { email: 'demo+aava@openplotter.cloud' },
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/pushover_fn',
// invalid key to avoid trigger notification
payload: { token: 'zxy', pushover_test_key: '987azerty#'},
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/update_user_preferences_fn',
//payload: { key: '{xyz}', value: '987azerty#'},
// invalid key to avoid trigger notification
payload: { key: '{telegram_test}', value: '{"id": 987654321, "is_bot": false, "first_name": "aaVa", "language_code": "en"}' },
res: {
obj_name: 'settings'
}
},
{ url: '/rpc/bot',
payload: { email: 'demo+aava@openplotter.cloud', chat_id: 987654321},
res: {
obj_name: 'settings'
}
}
]
}
].forEach( function(test){
//console.log(`${test.cname}`);
describe(`${test.name}`, function(){
request = supertest.agent(test.cname);
request.set('User-Agent', 'PostgSail unit tests');
describe("OpenAPI description", function(){
it('/', function(done) {
request = supertest.agent(test.cname);
request
.get('/')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.paths['/rpc/signup']);
should.exist(res.body.paths['/rpc/login']);
//should.exist(res.body.paths['/rpc/generate_otp_fn']);
should.exist(res.body.paths['/rpc/pushover_fn']);
should.exist(res.body.paths['/rpc/telegram_fn']);
//should.exist(res.body.paths['/rpc/bot']);
done(err);
});
});
}); // OpenAPI description
describe("Get JWT user_role", function(){
it('/rpc/signup return user_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/signup')
.send(test.signin)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
user_jwt = res.body.token;
should.exist(user_jwt);
done(err);
});
});
it('/rpc/login return user_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/login')
.send(test.login)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
//res.body.token.should.match(user_jwt);
//console.log(user_jwt);
should.exist(user_jwt);
done(err);
});
});
}); // JWT user_role
describe("OpenAPI with JWT user_role", function(){
it('/', function(done) {
request = supertest.agent(test.cname);
request
.get('/')
.set('Authorization', `Bearer ${user_jwt}`)
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
// Function
should.exist(res.body.paths['/rpc/register_vessel']);
should.exist(res.body.paths['/rpc/update_user_preferences_fn']);
should.exist(res.body.paths['/rpc/settings_fn']);
should.exist(res.body.paths['/rpc/versions_fn']);
// Tables
should.exist(res.body.paths['/metadata']);
should.exist(res.body.paths['/metrics']);
should.exist(res.body.paths['/logbook']);
should.exist(res.body.paths['/stays']);
should.exist(res.body.paths['/moorages']);
// Views
should.exist(res.body.paths['/logs_view']);
should.exist(res.body.paths['/moorages_view']);
should.exist(res.body.paths['/stays_view']);
should.exist(res.body.paths['/vessels_view']);
//should.exist(res.body.paths['/stats_view']);
should.exist(res.body.paths['/monitoring_view']);
done(err);
});
});
}); // OpenAPI JWT user_role
describe("Set preferences email_notifications, JWT user_role", function(){
it('/rpc/update_user_preferences_fn return true', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/update_user_preferences_fn')
.send(test.preferences)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.text);
should.exist(res.text);
res.text.should.match('true');
done(err);
});
});
}); // JWT user_role
describe("Get versions, JWT user_role", function(){
it('/rpc/versions_fn return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get('/rpc/versions_fn')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.text);
should.exist(res.body.api_version);
should.exist(res.body.sys_version);
done(err);
});
});
}); // JWT user_role
describe("Get JWT vessel_role from user_role", function(){
it('/rpc/register_vessel return vessel_role jwt token', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/register_vessel')
.send(test.vessel)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body.token);
vessel_jwt = res.body.token;
console.log(vessel_jwt);
should.exist(vessel_jwt);
done(err);
});
});
}); // JWT user_role
describe("Get vessel details view, JWT user_role", function(){
it('/vessels_view return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get('/vessels_view')
.set('Authorization', `Bearer ${user_jwt}`)
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
console.log(res.body);
//res.body.length.should.match(0);
res.body.length.should.match(1);
//res.body[0].last_contact.should.match('Never');
should.exist(res.body[0].last_contact);
done(err);
});
});
}); // JWT user_role
describe("Get vessel details function, JWT user_role", function(){
it('/rpc/vessel_fn return json', function(done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post('/rpc/vessel_fn')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.set('Content-Type', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//should.exist(res.body);
//body = res.body;
console.log(res.text);
done(err);
});
});
}); // JWT user_role
describe("Table endpoint, JWT user_role", function(){
test.user_tables.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get(`${subtest.url}`)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
//console.log(res.body);
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
res.body.length.should.match(subtest.res_body_length);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Table endpoint
describe("Views endpoint, JWT user_role", function(){
test.user_views.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get(`${subtest.url}`)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
//console.log(res.body);
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
should.exist(res.body);
res.body.length.should.match(subtest.res_body_length);
console.log(res.body);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Views endpoint
describe("Patch endpoint, JWT user_role", function(){
test.user_patchs.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.patch(subtest.url)
.send(subtest.patch)
.set('Content-Type', 'application/json')
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(204);
should.exist(res.header['server']);
res.header['server'].should.match(new RegExp('postgrest','g'));
console.log(res.body);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Patch endpoint
describe("Function user_fn endpoint, JWT user_role", function(){
test.user_fn.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//should.exist(res.body);
console.log(res.body);
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Function endpoint
/*
describe("Function others endpoint, JWT user_role", function(){
let otp = null;
test.others_fn.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.body);
should.exist(res.body);
if (subtest.url == '/rpc/generate_otp_fn') {
otp = res.body.text();
}
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Function endpoint
*/
}); // OpenAPI description
}); // CNAMEs Array

671
tests/index4.js Normal file
View File

@@ -0,0 +1,671 @@
"use strict";
/*
* Unit test #4
* OTP for email, Pushover, Telegram
*
* process.env.PGSAIL_API_URI = from inside the docker
*
* npm install supertest should mocha mochawesome moment
* alias mocha="./node_modules/mocha/bin/_mocha"
* mocha index4.js --reporter mochawesome --reporter-options reportDir=/mnt/postgsail/,reportFilename=report_api.html
*
*/
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const supertest = require("supertest");
// Deprecated
const should = require("should");
//const chai = require("chai");
//const should = chai.should();
let request = null;
let user_jwt = null;
var moment = require("moment");
// Users Array
[
{
cname: process.env.PGSAIL_API_URI,
name: "PostgSail unit test kapla",
signin: {
email: "demo+kapla@openplotter.cloud",
pass: "test",
firstname: "First_kapla",
lastname: "Last_kapla",
},
login: { email: "demo+kapla@openplotter.cloud", pass: "test" },
preferences: { key: "{email_valid}", value: false },
email_otp: [
{
url: "/rpc/generate_otp_fn",
payload: { email: "demo+kapla@openplotter.cloud" },
res: {
otp: 0,
},
},
{
url: "/rpc/email_fn",
payload: { token: null },
res: {
obj_name: "settings",
},
},
],
pushover_otp: [
{
//url: '/rpc/generate_otp_fn',
url: "/rpc/pushover_subscribe_link_fn",
//payload: { email: 'demo+kapla@openplotter.cloud' },
res: {
obj_name: "pushover_link",
},
},
{
url: "/rpc/pushover_fn",
payload: { token: null, pushover_user_key: "1234567890azerty!" },
res: {
obj_name: "settings",
},
},
],
telegram_otp: [
{
url: "/rpc/update_user_preferences_fn",
payload: { key: "{email_notifications}", value: false },
},
{
url: "/rpc/update_user_preferences_fn",
payload: { key: "{phone_notifications}", value: false },
},
{
//url: '/rpc/generate_otp_fn',
url: "/rpc/telegram_otp_fn",
payload: { email: "demo+kapla@openplotter.cloud" },
res: {
otp: 0,
},
},
{
url: "/rpc/telegram_fn",
payload: {
token: null,
telegram_obj: {
chat: {
id: 1234567890,
type: "private",
title: null,
all_members_are_administrators: null,
},
date: "NOW",
from: {
id: 1234567890,
is_bot: false,
first_name: "Kapla",
language_code: "en",
},
},
},
res: {},
},
],
telegram: { payload: { user_id: 1234567890 } },
telegram_fn: [{ url: "/rpc/vessel_fn" }, { url: "/monitoring_view" }],
badges: {
url: "/rpc/settings_fn",
payload: null,
res: {
obj_name: "settings",
},
},
monitoring: [
{
url: "/monitoring_view",
payload: null,
res: {},
},
{
url: "/monitoring_view2",
payload: null,
res: {},
},
{
url: "/monitoring_view3",
payload: null,
res: {},
},
{
url: "/monitoring_voltage",
payload: null,
res: {},
},
{
url: "/monitoring_temperatures",
payload: null,
res: {},
},
{
url: "/monitoring_humidity",
payload: null,
res: {},
},
],
eventlogs: {
url: "/eventlogs_view",
payload: null,
res: {},
},
},
{
cname: process.env.PGSAIL_API_URI,
name: "PostgSail unit test, aava",
signin: {
email: "demo+aava@openplotter.cloud",
pass: "test",
firstname: "first_aava",
lastname: "last_aava",
},
login: { email: "demo+aava@openplotter.cloud", pass: "test" },
preferences: { key: "{email_valid}", value: false },
email_otp: [
{
url: "/rpc/generate_otp_fn",
payload: { email: "demo+aava@openplotter.cloud" },
res: {
otp: 0,
},
},
{
url: "/rpc/email_fn",
payload: { token: null },
res: {
obj_name: "settings",
},
},
],
pushover_otp: [
{
//url: '/rpc/generate_otp_fn',
url: "/rpc/pushover_subscribe_link_fn",
//payload: { email: 'demo+aava@openplotter.cloud' },
res: {
obj_name: "pushover_link",
},
},
{
url: "/rpc/pushover_fn",
payload: { token: null, pushover_user_key: "0987654321qwerty!" },
res: {
obj_name: "settings",
},
},
],
telegram_otp: [
{
url: "/rpc/update_user_preferences_fn",
payload: { key: "{email_notifications}", value: false },
},
{
url: "/rpc/update_user_preferences_fn",
payload: { key: "{phone_notifications}", value: false },
},
{
//url: '/rpc/generate_otp_fn',
url: "/rpc/telegram_otp_fn",
payload: { email: "demo+aava@openplotter.cloud" },
res: {
otp: 0,
},
},
{
url: "/rpc/telegram_fn",
payload: {
token: null,
telegram_obj: {
chat: {
id: 9876543210,
type: "private",
title: null,
all_members_are_administrators: null,
},
date: "NOW",
from: {
id: 9876543210,
is_bot: false,
first_name: "Aava",
language_code: "en",
},
},
},
res: {},
},
],
telegram: { payload: { user_id: 9876543210 } },
telegram_fn: [{ url: "/rpc/vessel_fn" }, { url: "/monitoring_view" }],
badges: {
url: "/rpc/settings_fn",
payload: null,
res: {
obj_name: "settings",
},
},
monitoring: [
{
url: "/monitoring_view",
payload: null,
res: {},
},
{
url: "/monitoring_view2",
payload: null,
res: {},
},
{
url: "/monitoring_view3",
payload: null,
res: {},
},
{
url: "/monitoring_voltage",
payload: null,
res: {},
},
{
url: "/monitoring_temperatures",
payload: null,
res: {},
},
{
url: "/monitoring_humidity",
payload: null,
res: {},
},
],
eventlogs: {
url: "/eventlogs_view",
payload: null,
res: {},
},
},
].forEach(function (test) {
//console.log(`${test.cname}`);
describe(`${test.name}`, function () {
request = supertest.agent(test.cname);
request.set("User-Agent", "PostgSail unit tests");
describe("Get JWT user_role", function () {
it("/rpc/signup return user_role jwt token", function (done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post("/rpc/signup")
.send(test.signin)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(new RegExp("json", "g"));
res.header["server"].should.match(new RegExp("postgrest", "g"));
should.exist(res.body.token);
user_jwt = res.body.token;
should.exist(user_jwt);
done(err);
});
});
it("/rpc/login return user_role jwt token", function (done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post("/rpc/login")
.send(test.login)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(new RegExp("json", "g"));
res.header["server"].should.match(new RegExp("postgrest", "g"));
should.exist(res.body.token);
res.body.token.should.match(user_jwt);
console.log(user_jwt);
should.exist(user_jwt);
done(err);
});
});
}); // JWT user_role
describe("Set preferences email_notifications, JWT user_role", function () {
it("/rpc/update_user_preferences_fn return true", function (done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post("/rpc/update_user_preferences_fn")
.send(test.preferences)
.set("Authorization", `Bearer ${user_jwt}`)
.set("Accept", "application/json")
.set("Content-Type", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(new RegExp("json", "g"));
res.header["server"].should.match(new RegExp("postgrest", "g"));
//console.log(res.text);
should.exist(res.text);
res.text.should.match("true");
done(err);
});
});
}); // JWT user_role
describe("Function email OTP endpoint, JWT user_role", function () {
let otp = null;
test.email_otp.forEach(function (subtest) {
it(`${subtest.url}`, function (done) {
try {
//console.log(`${subtest.url} ${subtest.payload}`);
if (otp) {
subtest.payload.token = otp;
}
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set("Authorization", `Bearer ${user_jwt}`)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(
new RegExp("json", "g")
);
res.header["server"].should.match(new RegExp("postgrest", "g"));
console.log(res.body);
should.exist(res.body);
if (subtest.url == "/rpc/generate_otp_fn") {
otp = res.body;
} else {
res.text.should.match("true");
}
done(err);
});
} catch (error) {
done();
}
});
});
}); // email OTP endpoint
describe("Function Pushover OTP endpoint, JWT user_role", function () {
let otp = null;
test.pushover_otp.forEach(function (subtest) {
it(`${subtest.url}`, function (done) {
try {
//console.log(`${subtest.url} ${subtest.payload}`);
if (otp) {
subtest.payload.token = otp;
}
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set("Authorization", `Bearer ${user_jwt}`)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(
new RegExp("json", "g")
);
res.header["server"].should.match(new RegExp("postgrest", "g"));
//console.log(res.body);
should.exist(res.body);
if (subtest.url == "/rpc/pushover_subscribe_link_fn") {
should.exist(res.body.pushover_link.link);
let rx = /3D(\d+)\&/g;
//console.log(rx.exec(res.body.pushover_link.link)[1]);
let arr = rx.exec(res.body.pushover_link.link);
//console.log(arr);
console.log(arr[1]);
otp = arr[1];
} else {
res.text.should.match("true");
}
done(err);
});
} catch (error) {
done();
}
});
});
}); // pushover OTP endpoint
describe("Function Telegram OTP endpoint, JWT user_role", function () {
let otp = null;
test.telegram_otp.forEach(function (subtest) {
it(`${subtest.url}`, function (done) {
try {
console.log(`${subtest.url} ${subtest.payload.email} ${otp}`);
if (otp) {
subtest.payload.token = otp;
console.log(subtest.payload.telegram_obj.date);
subtest.payload.telegram_obj.date = moment.utc().format();
}
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set("Authorization", `Bearer ${user_jwt}`)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(
new RegExp("json", "g")
);
res.header["server"].should.match(new RegExp("postgrest", "g"));
console.log(res.body);
should.exist(res.body);
if (subtest.url == "/rpc/telegram_otp_fn") {
console.log(res.body.otp_code);
otp = res.body.otp_code;
} else {
console.log(res.text);
res.text.should.match("true");
otp = null;
}
done(err);
});
} catch (error) {
done();
}
});
});
}); // telegram OTP endpoint
describe("telegram session, anonymous", function () {
it("/rpc/telegram return jwt token", function (done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post("/rpc/telegram")
.send(test.telegram.payload)
.set("Accept", "application/json")
.set("Content-Type", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(new RegExp("json", "g"));
res.header["server"].should.match(new RegExp("postgrest", "g"));
should.exist(res.body.token);
user_jwt = res.body.token;
console.log(res.body.token);
done(err);
});
});
}); // anonymous JWT
describe("Telegram endpoint, JWT user_role", function () {
let otp = null;
test.telegram_fn.forEach(function (subtest) {
it(`${subtest.url}`, function (done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get(subtest.url)
.set("Authorization", `Bearer ${user_jwt}`)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(
new RegExp("json", "g")
);
res.header["server"].should.match(new RegExp("postgrest", "g"));
console.log(res.body);
should.exist(res.body);
done(err);
});
} catch (error) {
done();
}
});
});
}); // Function endpoint
/*
describe("Function others endpoint, JWT user_role", function(){
let otp = null;
test.others_fn.forEach(function (subtest) {
it(`${subtest.url}`, function(done) {
try {
//console.log(`${subtest.url} ${subtest.res_body_length}`);
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post(subtest.url)
.send(subtest.payload)
.set('Authorization', `Bearer ${user_jwt}`)
.set('Accept', 'application/json')
.end(function(err,res){
res.status.should.equal(200);
should.exist(res.header['content-type']);
should.exist(res.header['server']);
res.header['content-type'].should.match(new RegExp('json','g'));
res.header['server'].should.match(new RegExp('postgrest','g'));
//console.log(res.body);
should.exist(res.body);
if (subtest.url == '/rpc/generate_otp_fn') {
otp = res.body.text();
}
done(err);
});
}
catch (error) {
done();
}
});
});
}); // Function endpoint
*/
describe("Badges, user jwt", function () {
it("/rpc/settings_fn return user settings", function (done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.post("/rpc/settings_fn")
.set("Authorization", `Bearer ${user_jwt}`)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(new RegExp("json", "g"));
res.header["server"].should.match(new RegExp("postgrest", "g"));
console.log(res.body);
should.exist(res.body.settings);
should.exist(res.body.settings.preferences.badges)
let badges = res.body.settings.preferences.badges;
//console.log(Object.keys(badges));
Object.keys(badges).length.should.be.aboveOrEqual(3);
(badges).should.have.properties('Helmsman', 'Wake Maker', 'Stormtrooper');
done(err);
});
});
}); // user JWT
describe("Function monitoring endpoint, JWT user_role", function () {
let otp = null;
test.monitoring.forEach(function (subtest) {
it(`${subtest.url}`, function (done) {
try {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get(subtest.url)
.set("Authorization", `Bearer ${user_jwt}`)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(
new RegExp("json", "g")
);
res.header["server"].should.match(new RegExp("postgrest", "g"));
//console.log(res.body);
should.exist(res.body);
//let monitoring = res.body;
//console.log(monitoring);
// minimum set for static monitoring page
// no value for humidity monitoring
//monitoring.length.should.be.aboveOrEqual(21);
done(err);
});
} catch (error) {
done();
}
});
});
}); // Monitoring endpoint
describe("Event Logs, user jwt", function () {
it("/eventlogs_view endpoint, list process_queue, JWT user_role", function (done) {
// Reset agent so we do not save cookies
request = supertest.agent(test.cname);
request
.get("/eventlogs_view")
.set("Authorization", `Bearer ${user_jwt}`)
.set("Accept", "application/json")
.end(function (err, res) {
res.status.should.equal(200);
should.exist(res.header["content-type"]);
should.exist(res.header["server"]);
res.header["content-type"].should.match(new RegExp("json", "g"));
res.header["server"].should.match(new RegExp("postgrest", "g"));
//console.log(res.body);
should.exist(res.body);
let event = res.body;
//console.log(event);
// minimum events log for kapla & aava 13 + 4 email_otp = 17
event.length.should.be.aboveOrEqual(13);
done(err);
});
});
}); // user JWT
}); // OpenAPI description
}); // Users Array

View File

@@ -0,0 +1,567 @@
{
"metrics": [
{
"time" : "2022-07-31T11:28:13.331Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7231605,
"longitude" : 24.7358807,
"speedoverground" : 7.1,
"courseovergroundtrue" : 188.9,
"windspeedapparent" : 13.9,
"anglespeedapparent" : 56.0,
"status" : "moored",
"metrics" : {"navigation.log": 17441210, "navigation.trip.log": 80099, "navigation.headingTrue": 3.3179, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 36.219, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.48, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 19.6, "electrical.batteries.1.voltage": 13.38, "navigation.gnss.antennaAltitude": 2.21, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 36.22, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 89, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 9, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:29:13.340Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7213961,
"longitude" : 24.7349507,
"speedoverground" : 6.5,
"courseovergroundtrue" : 197.4,
"windspeedapparent" : 15.4,
"anglespeedapparent" : 43.0,
"status" : "moored",
"metrics" : {"navigation.log": 17441395, "navigation.trip.log": 80284, "navigation.headingTrue": 3.4924, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 32.289, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 231, "electrical.batteries.1.voltage": 14.45, "navigation.gnss.antennaAltitude": -0.04, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 32.29, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 57, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 4, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 11, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:30:28.338Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7190763,
"longitude" : 24.733775,
"speedoverground" : 7.1,
"courseovergroundtrue" : 194.4,
"windspeedapparent" : 16.3,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441580, "navigation.trip.log": 80544, "navigation.headingTrue": 3.4226, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 23.808999999999997, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.61, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 231.5, "electrical.batteries.1.voltage": 13.02, "navigation.gnss.antennaAltitude": 2.06, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 23.81, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 73, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:31:28.348Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7173052,
"longitude" : 24.7325741,
"speedoverground" : 6.5,
"courseovergroundtrue" : 198.8,
"windspeedapparent" : 15.8,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441766, "navigation.trip.log": 80747, "navigation.headingTrue": 3.5972, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 20.948999999999998, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 192.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 0.21, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 20.95, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 64, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:32:28.364Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7156422,
"longitude" : 24.731211599999998,
"speedoverground" : 6.4,
"courseovergroundtrue" : 203.3,
"windspeedapparent" : 13.7,
"anglespeedapparent" : 58.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442136, "navigation.trip.log": 80951, "navigation.headingTrue": 3.5361, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 17.529, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 2.93, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 105.2, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 2.49, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 17.53, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 43, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 4, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 11, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:33:28.377Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7139966,
"longitude" : 24.7299656,
"speedoverground" : 6.5,
"courseovergroundtrue" : 200.4,
"windspeedapparent" : 15.6,
"anglespeedapparent" : 44.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442321, "navigation.trip.log": 81136, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.999, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 70.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.69, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 34, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:34:28.396Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7124464,
"longitude" : 24.728924,
"speedoverground" : 5.8,
"courseovergroundtrue" : 197.8,
"windspeedapparent" : 12.2,
"anglespeedapparent" : 31.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442506, "navigation.trip.log": 81321, "navigation.headingTrue": 3.5535, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.999, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.07, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 43.9, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.11, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 66, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:35:28.413Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7106379,
"longitude" : 24.728088,
"speedoverground" : 6.7,
"courseovergroundtrue" : 187.8,
"windspeedapparent" : 13.7,
"anglespeedapparent" : 42.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442692, "navigation.trip.log": 81507, "navigation.headingTrue": 3.4313, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 14.029, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 36.1, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.78, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14.03, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 69, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:36:28.424Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7087125,
"longitude" : 24.7276837,
"speedoverground" : 7.1,
"courseovergroundtrue" : 185.4,
"windspeedapparent" : 13.5,
"anglespeedapparent" : 51.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442877, "navigation.trip.log": 81692, "navigation.headingTrue": 3.3004, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 22.689, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 25.2, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 3.24, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 22.69, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 45, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:37:28.444Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7245499,
"longitude" : 24.736394999999998,
"speedoverground" : 6.7,
"courseovergroundtrue" : 196.5,
"windspeedapparent" : 14.1,
"anglespeedapparent" : 42.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441025, "navigation.trip.log": 79951, "navigation.headingTrue": 3.475, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 71.039, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 16.4, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.32, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 71.04, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 64, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:38:28.483Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7227198,
"longitude" : 24.735699,
"speedoverground" : 6.4,
"courseovergroundtrue" : 186.4,
"windspeedapparent" : 13.9,
"anglespeedapparent" : 44.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441210, "navigation.trip.log": 80136, "navigation.headingTrue": 3.4401, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 33.169000000000004, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 172, "electrical.batteries.1.voltage": 13.35, "navigation.gnss.antennaAltitude": 2.11, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 33.17, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 32, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 5, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 6, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 13, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:39:28.509Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7209298,
"longitude" : 24.73472,
"speedoverground" : 6.8,
"courseovergroundtrue" : 190.7,
"windspeedapparent" : 15.4,
"anglespeedapparent" : 38.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441395, "navigation.trip.log": 80340, "navigation.headingTrue": 3.4663, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 30.738999999999997, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 211.6, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 0.76, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 30.74, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 52, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 9, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:40:28.539Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7190763,
"longitude" : 24.733774999999998,
"speedoverground" : 7.1,
"courseovergroundtrue" : 194.4,
"windspeedapparent" : 16.3,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441580, "navigation.trip.log": 80544, "navigation.headingTrue": 3.4226, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 23.808999999999997, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.61, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 231.5, "electrical.batteries.1.voltage": 13.02, "navigation.gnss.antennaAltitude": 2.06, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 23.81, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 73, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:41:28.561Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7173052,
"longitude" : 24.7325741,
"speedoverground" : 6.5,
"courseovergroundtrue" : 198.8,
"windspeedapparent" : 15.8,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441766, "navigation.trip.log": 80747, "navigation.headingTrue": 3.5972, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 20.948999999999998, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 192.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 0.39, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 20.95, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 64, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:42:28.569Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7156422,
"longitude" : 24.7312116,
"speedoverground" : 6.4,
"courseovergroundtrue" : 203.3,
"windspeedapparent" : 13.7,
"anglespeedapparent" : 58.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442136, "navigation.trip.log": 80951, "navigation.headingTrue": 3.5361, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 17.529, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 2.93, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 107.6, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 2.49, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 17.53, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 43, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 4, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 11, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:43:28.603Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7139966,
"longitude" : 24.7299656,
"speedoverground" : 6.4,
"courseovergroundtrue" : 200.4,
"windspeedapparent" : 15.6,
"anglespeedapparent" : 44.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442321, "navigation.trip.log": 81136, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.999, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 70.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.69, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 34, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:44:28.629Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7124464,
"longitude" : 24.728924,
"speedoverground" : 5.7,
"courseovergroundtrue" : 197.6,
"windspeedapparent" : 12.2,
"anglespeedapparent" : 31.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442506, "navigation.trip.log": 81321, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.999, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.07, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 43.9, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.05, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 66, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:45:28.645Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7106379,
"longitude" : 24.728088,
"speedoverground" : 6.7,
"courseovergroundtrue" : 187.8,
"windspeedapparent" : 13.7,
"anglespeedapparent" : 42.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442692, "navigation.trip.log": 81507, "navigation.headingTrue": 3.4313, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 14.029, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 36.1, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.78, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14.03, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 69, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:46:28.664Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7087125,
"longitude" : 24.7276837,
"speedoverground" : 7.0,
"courseovergroundtrue" : 185.4,
"windspeedapparent" : 13.5,
"anglespeedapparent" : 51.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442877, "navigation.trip.log": 81692, "navigation.headingTrue": 3.3004, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 22.689, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 25.2, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 3.24, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 22.69, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 45, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:47:28.696Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7245499,
"longitude" : 24.736394999999998,
"speedoverground" : 6.7,
"courseovergroundtrue" : 196.5,
"windspeedapparent" : 14.1,
"anglespeedapparent" : 42.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441025, "navigation.trip.log": 79951, "navigation.headingTrue": 3.475, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 71.039, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 16.4, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.32, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 71.04, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 64, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:48:28.712Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7226901,
"longitude" : 24.735683899999998,
"speedoverground" : 6.4,
"courseovergroundtrue" : 187.7,
"windspeedapparent" : 14.9,
"anglespeedapparent" : 44.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441210, "navigation.trip.log": 80136, "navigation.headingTrue": 3.4313, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 33.169000000000004, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 172, "electrical.batteries.1.voltage": 13.35, "navigation.gnss.antennaAltitude": 2.13, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 33.17, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 32, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 5, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 6, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 13, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:49:28.726Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7209298,
"longitude" : 24.73472,
"speedoverground" : 6.8,
"courseovergroundtrue" : 190.7,
"windspeedapparent" : 15.4,
"anglespeedapparent" : 38.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441395, "navigation.trip.log": 80340, "navigation.headingTrue": 3.4663, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 30.738999999999997, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 211.6, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 0.76, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 30.74, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 52, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 9, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:50:28.743Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7190454,
"longitude" : 24.7337548,
"speedoverground" : 7.0,
"courseovergroundtrue" : 194.4,
"windspeedapparent" : 16.3,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441580, "navigation.trip.log": 80544, "navigation.headingTrue": 3.4226, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 23.808999999999997, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.61, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 231.5, "electrical.batteries.1.voltage": 13.02, "navigation.gnss.antennaAltitude": 2.06, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 23.81, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 73, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:51:28.762Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7172775,
"longitude" : 24.7325491,
"speedoverground" : 6.5,
"courseovergroundtrue" : 198.3,
"windspeedapparent" : 13.9,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441766, "navigation.trip.log": 80747, "navigation.headingTrue": 3.5797, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 20.948999999999998, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 192.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 0.39, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 20.95, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 64, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:52:28.783Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7156422,
"longitude" : 24.7312116,
"speedoverground" : 6.4,
"courseovergroundtrue" : 203.3,
"windspeedapparent" : 15.6,
"anglespeedapparent" : 58.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442136, "navigation.trip.log": 80951, "navigation.headingTrue": 3.5361, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 17.529, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 2.93, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 107.6, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 2.49, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 17.53, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 43, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 4, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 11, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:53:28.800Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7139716,
"longitude" : 24.7299463,
"speedoverground" : 6.4,
"courseovergroundtrue" : 200.4,
"windspeedapparent" : 14.1,
"anglespeedapparent" : 44.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442321, "navigation.trip.log": 81136, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.999, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 70.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.69, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 34, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:54:28.819Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7124464,
"longitude" : 24.728924,
"speedoverground" : 5.7,
"courseovergroundtrue" : 197.6,
"windspeedapparent" : 15.9,
"anglespeedapparent" : 31.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442506, "navigation.trip.log": 81321, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.999, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.07, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 43.9, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.05, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 66, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:55:28.837Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7106379,
"longitude" : 24.728088,
"speedoverground" : 6.7,
"courseovergroundtrue" : 187.8,
"windspeedapparent" : 16.9,
"anglespeedapparent" : 42.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442692, "navigation.trip.log": 81507, "navigation.headingTrue": 3.4313, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 14.029, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 36.1, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.74, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14.03, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 69, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:56:28.855Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7086808,
"longitude" : 24.7276789,
"speedoverground" : 7.0,
"courseovergroundtrue" : 185.4,
"windspeedapparent" : 13.5,
"anglespeedapparent" : 51.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442877, "navigation.trip.log": 81692, "navigation.headingTrue": 3.3004, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 22.689, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 25.2, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 3.24, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 22.69, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 45, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:57:28.876Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7245198,
"longitude" : 24.7363702,
"speedoverground" : 6.7,
"courseovergroundtrue" : 196.5,
"windspeedapparent" : 14.1,
"anglespeedapparent" : 42.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441025, "navigation.trip.log": 79951, "navigation.headingTrue": 3.475, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 71.039, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 16.4, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.32, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 71.04, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 64, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:58:28.899Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7226901,
"longitude" : 24.735683899999998,
"speedoverground" : 6.4,
"courseovergroundtrue" : 187.7,
"windspeedapparent" : 14.9,
"anglespeedapparent" : 44.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441210, "navigation.trip.log": 80136, "navigation.headingTrue": 3.4313, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 33.169000000000004, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 172, "electrical.batteries.1.voltage": 13.35, "navigation.gnss.antennaAltitude": 2.13, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 33.17, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 32, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 5, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 6, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 13, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T11:59:28.928Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7208986,
"longitude" : 24.734705599999998,
"speedoverground" : 6.8,
"courseovergroundtrue" : 190.7,
"windspeedapparent" : 15.4,
"anglespeedapparent" : 38.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441395, "navigation.trip.log": 80358, "navigation.headingTrue": 3.5099, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 30.738999999999997, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 211.6, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 0.78, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 30.74, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 52, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 9, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:00:28.941Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7190454,
"longitude" : 24.7337548,
"speedoverground" : 7.0,
"courseovergroundtrue" : 194.4,
"windspeedapparent" : 17.0,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441580, "navigation.trip.log": 80544, "navigation.headingTrue": 3.4226, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 23.808999999999997, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.61, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 231.5, "electrical.batteries.1.voltage": 13.02, "navigation.gnss.antennaAltitude": 2.06, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 23.81, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 73, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:01:28.966Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7172775,
"longitude" : 24.7325491,
"speedoverground" : 6.5,
"courseovergroundtrue" : 198.3,
"windspeedapparent" : 15.1,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441766, "navigation.trip.log": 80747, "navigation.headingTrue": 3.5797, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 20.948999999999998, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 192.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 0.39, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 20.95, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 64, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:02:28.982Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7156162,
"longitude" : 24.731190599999998,
"speedoverground" : 6.4,
"courseovergroundtrue" : 203.1,
"windspeedapparent" : 15.6,
"anglespeedapparent" : 58.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442136, "navigation.trip.log": 80951, "navigation.headingTrue": 3.5273, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 17.529, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 2.93, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 107.6, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 2.6, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 17.53, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 43, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 4, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 11, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:03:28.988Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7139716,
"longitude" : 24.7299463,
"speedoverground" : 6.4,
"courseovergroundtrue" : 200.4,
"windspeedapparent" : 14.1,
"anglespeedapparent" : 44.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442321, "navigation.trip.log": 81136, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.999, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.07, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 70.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.69, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 34, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:04:29.008Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7124174,
"longitude" : 24.7289112,
"speedoverground" : 5.7,
"courseovergroundtrue" : 197.6,
"windspeedapparent" : 15.9,
"anglespeedapparent" : 31.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442506, "navigation.trip.log": 81321, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.749, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.07, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 43.9, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.05, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 13.75, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 66, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:05:29.025Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7106066,
"longitude" : 24.7280837,
"speedoverground" : 6.7,
"courseovergroundtrue" : 191.2,
"windspeedapparent" : 16.9,
"anglespeedapparent" : 42.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442692, "navigation.trip.log": 81507, "navigation.headingTrue": 3.4313, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 13.539, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 36.1, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.74, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 13.54, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 69, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:06:29.043Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7086808,
"longitude" : 24.7276789,
"speedoverground" : 7.0,
"courseovergroundtrue" : 185.4,
"windspeedapparent" : 14.4,
"anglespeedapparent" : 51.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442877, "navigation.trip.log": 81710, "navigation.headingTrue": 3.3004, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 22.689, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 25.2, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 3.24, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 22.69, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 45, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:07:29.071Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7245198,
"longitude" : 24.7363702,
"speedoverground" : 6.7,
"courseovergroundtrue" : 196.5,
"windspeedapparent" : 14.1,
"anglespeedapparent" : 42.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441025, "navigation.trip.log": 79951, "navigation.headingTrue": 3.475, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 71.039, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.19, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 16.4, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.51, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 71.04, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 64, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:08:29.081Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7226901,
"longitude" : 24.7356839,
"speedoverground" : 6.4,
"courseovergroundtrue" : 187.7,
"windspeedapparent" : 14.9,
"anglespeedapparent" : 44.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441210, "navigation.trip.log": 80155, "navigation.headingTrue": 3.4313, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 33.719, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.09, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 172, "electrical.batteries.1.voltage": 13.35, "navigation.gnss.antennaAltitude": 2.13, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 33.72, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 72, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 6, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 13, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:09:29.094Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7208986,
"longitude" : 24.734705599999998,
"speedoverground" : 6.8,
"courseovergroundtrue" : 191.3,
"windspeedapparent" : 15.4,
"anglespeedapparent" : 38.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441395, "navigation.trip.log": 80358, "navigation.headingTrue": 3.5099, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 31.529, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 211.6, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 0.78, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 31.53, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 49, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 9, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:10:29.108Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7190454,
"longitude" : 24.7337548,
"speedoverground" : 7.0,
"courseovergroundtrue" : 194.4,
"windspeedapparent" : 17.0,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441580, "navigation.trip.log": 80544, "navigation.headingTrue": 3.4226, "navigation.gnss.satellites": 11, "environment.depth.belowKeel": 25.398999999999997, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.47, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 231.5, "electrical.batteries.1.voltage": 13.02, "navigation.gnss.antennaAltitude": 1.8, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 25.4, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 57, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 1, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 1, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:11:29.120Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7172775,
"longitude" : 24.7325491,
"speedoverground" : 6.5,
"courseovergroundtrue" : 198.3,
"windspeedapparent" : 15.1,
"anglespeedapparent" : 41.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17441766, "navigation.trip.log": 80747, "navigation.headingTrue": 3.5797, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 20.948999999999998, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.34, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 192.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 0.39, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 20.95, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 81, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 4, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:12:29.137Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7156162,
"longitude" : 24.731190599999998,
"speedoverground" : 6.4,
"courseovergroundtrue" : 203.1,
"windspeedapparent" : 15.6,
"anglespeedapparent" : 58.0,
"status" : "sailing",
"metrics" : {"navigation.log": 17442136, "navigation.trip.log": 80951, "navigation.headingTrue": 3.5273, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 17.529, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.21, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 107.6, "electrical.batteries.1.voltage": 14.55, "navigation.gnss.antennaAltitude": 2.6, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 17.53, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 2, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 55, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 3, "network.n2k.ngt-1.130356.ch1.bandwidth": 2, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 11, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:13:29.150Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7139716,
"longitude" : 24.729946299999998,
"speedoverground" : 6.4,
"courseovergroundtrue" : 200.7,
"windspeedapparent" : 14.1,
"anglespeedapparent" : 44.0,
"status" : "anchored",
"metrics" : {"navigation.log": 17442321, "navigation.trip.log": 81136, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 14.209000000000001, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.07, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 70.4, "electrical.batteries.1.voltage": 14.56, "navigation.gnss.antennaAltitude": 2.38, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 14.21, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 70, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 4, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 4, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
},
{
"time" : "2022-07-31T12:14:29.168Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:987654321",
"latitude" : 59.7124174,
"longitude" : 24.7289112,
"speedoverground" : 5.7,
"courseovergroundtrue" : 197.6,
"windspeedapparent" : 15.9,
"anglespeedapparent" : 31.0,
"status" : "anchored",
"metrics" : {"navigation.log": 17442506, "navigation.trip.log": 81321, "navigation.headingTrue": 3.571, "navigation.gnss.satellites": 10, "environment.depth.belowKeel": 13.749, "navigation.magneticVariation": 0.1414, "navigation.speedThroughWater": 3.07, "environment.water.temperature": 313.15, "electrical.batteries.1.current": 43.9, "electrical.batteries.1.voltage": 14.54, "navigation.gnss.antennaAltitude": 2.05, "network.n2k.ngt-1.130356.errorID": 0, "network.n2k.ngt-1.130356.modelID": 14, "environment.depth.belowTransducer": 13.75, "electrical.batteries.1.temperature": 299.82, "environment.depth.transducerToKeel": -0.001, "navigation.gnss.horizontalDilution": 0.8, "network.n2k.ngt-1.130356.ch1.rxLoad": 4, "network.n2k.ngt-1.130356.ch1.txLoad": 0, "network.n2k.ngt-1.130356.ch2.rxLoad": 0, "network.n2k.ngt-1.130356.ch2.txLoad": 40, "network.n2k.ngt-1.130356.ch1.deleted": 0, "network.n2k.ngt-1.130356.ch2.deleted": 0, "network.n2k.ngt-1.130356.ch2Bandwidth": 4, "network.n2k.ngt-1.130356.ch1.bandwidth": 3, "network.n2k.ngt-1.130356.ch1.rxDropped": 0, "network.n2k.ngt-1.130356.ch2.rxDropped": 0, "network.n2k.ngt-1.130356.ch1.rxFiltered": 0, "network.n2k.ngt-1.130356.ch2.rxFiltered": 0, "network.n2k.ngt-1.130356.ch1.rxBandwidth": 5, "network.n2k.ngt-1.130356.ch1.txBandwidth": 0, "network.n2k.ngt-1.130356.ch2.rxBandwidth": 0, "network.n2k.ngt-1.130356.ch2.txBandwidth": 10, "network.n2k.ngt-1.130356.uniChannelCount": 2, "network.n2k.ngt-1.130356.indiChannelCount": 2, "network.n2k.ngt-1.130356.ch1.BufferLoading": 0, "network.n2k.ngt-1.130356.ch2.bufferLoading": 0, "network.n2k.ngt-1.130356.ch1.PointerLoading": 0, "network.n2k.ngt-1.130356.ch2.pointerLoading": 0}
}
]}

View File

@@ -0,0 +1,615 @@
{
"metrics": [
{
"time" : "2022-07-30T14:52:28.000Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.077666666666666,
"longitude" : 23.530866666666668,
"speedoverground" : 0.0,
"courseovergroundtrue" : 207.5,
"windspeedapparent" : 14.8,
"anglespeedapparent" : -12.0,
"status" : "moored",
"metrics" : {"environment.wind.speedTrue": 4.44, "navigation.speedThroughWater": 3.0918118943701245, "performance.velocityMadeGood": 2.9323340761912995, "environment.wind.angleTrueWater": -0.3665191430024964, "environment.depth.belowTransducer": 13.1, "navigation.courseOverGroundMagnetic": 3.620685534088946, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T14:53:28.000Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.077666666666666,
"longitude" : 23.530866666666668,
"speedoverground" : 5.7,
"courseovergroundtrue" : 207.5,
"windspeedapparent" : 14.8,
"anglespeedapparent" : -12.0,
"status" : "moored",
"metrics" : {"environment.wind.speedTrue": 4.44, "navigation.speedThroughWater": 3.0918118943701245, "performance.velocityMadeGood": 2.9323340761912995, "environment.wind.angleTrueWater": -0.3665191430024964, "environment.depth.belowTransducer": 13.1, "navigation.courseOverGroundMagnetic": 3.620685534088946, "navigation.courseRhumbline.crossTrackError": 0, "propulsion.main.runTime":1776241 }
},
{
"time" : "2022-07-30T14:54:28.016Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.07065,
"longitude" : 23.52355,
"speedoverground" : 5.6,
"courseovergroundtrue" : 211.5,
"windspeedapparent" : 14.8,
"anglespeedapparent" : -7.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 4.52, "navigation.speedThroughWater": 3.0815230028747167, "performance.velocityMadeGood": 2.9683451964252274, "environment.wind.angleTrueWater": -0.20943951028714078, "environment.depth.belowTransducer": 13.58, "navigation.courseOverGroundMagnetic": 3.6910223029603775, "navigation.courseRhumbline.crossTrackError": 0, "propulsion.main.runTime":1776241 }
},
{
"time" : "2022-07-30T14:55:28.021Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.0637,
"longitude" : 23.515866666666668,
"speedoverground" : 5.6,
"courseovergroundtrue" : 211.3,
"windspeedapparent" : 15.7,
"anglespeedapparent" : 0.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 4.99, "navigation.speedThroughWater": 3.0558007741361966, "performance.velocityMadeGood": 3.00950076240686, "environment.wind.angleTrueWater": 0, "environment.depth.belowTransducer": 16.75, "navigation.courseOverGroundMagnetic": 3.6878807103060707, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T14:56:28.033Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.05671666666667,
"longitude" : 23.507866666666665,
"speedoverground" : 5.9,
"courseovergroundtrue" : 211.1,
"windspeedapparent" : 19.8,
"anglespeedapparent" : -2.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 4.22, "navigation.speedThroughWater": 3.1895563635765014, "performance.velocityMadeGood": 3.1586896890902767, "environment.wind.angleTrueWater": -0.0174532925239284, "environment.depth.belowTransducer": 18.96, "navigation.courseOverGroundMagnetic": 3.683866453025567, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T14:57:28.049Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.04915,
"longitude" : 23.500533333333333,
"speedoverground" : 6.1,
"courseovergroundtrue" : 212.0,
"windspeedapparent" : 14.2,
"anglespeedapparent" : -5.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.9, "navigation.speedThroughWater": 3.2204230380627252, "performance.velocityMadeGood": 3.168978580585685, "environment.wind.angleTrueWater": -0.19198621776321237, "environment.depth.belowTransducer": 21.41, "navigation.courseOverGroundMagnetic": 3.6997489492223417, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T14:58:28.064Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.04163333333333,
"longitude" : 23.493,
"speedoverground" : 6.0,
"courseovergroundtrue" : 204.9,
"windspeedapparent" : 12.0,
"anglespeedapparent" : -26.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 1.93, "navigation.speedThroughWater": 3.2615786040443577, "performance.velocityMadeGood": 0.8025335366418294, "environment.wind.angleTrueWater": -1.30899693929463, "environment.depth.belowTransducer": 21.01, "navigation.courseOverGroundMagnetic": 3.5753069735267324, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T14:59:28.095Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.03398333333333,
"longitude" : 23.485466666666667,
"speedoverground" : 6.1,
"courseovergroundtrue" : 206.0,
"windspeedapparent" : 9.5,
"anglespeedapparent" : -23.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.29, "navigation.speedThroughWater": 3.2461452668012454, "performance.velocityMadeGood": 1.6668004222561073, "environment.wind.angleTrueWater": -0.9948376738639186, "environment.depth.belowTransducer": 27.74, "navigation.courseOverGroundMagnetic": 3.595203727004011, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:00:28.106Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.02621666666667,
"longitude" : 23.479033333333334,
"speedoverground" : 6.0,
"courseovergroundtrue" : 201.6,
"windspeedapparent" : 10.5,
"anglespeedapparent" : -8.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.21, "navigation.speedThroughWater": 3.2410008210535413, "performance.velocityMadeGood": 3.0660896656316043, "environment.wind.angleTrueWater": -0.38397243552642474, "environment.depth.belowTransducer": 31.18, "navigation.courseOverGroundMagnetic": 3.518409239898726, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:01:28.107Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.01835,
"longitude" : 23.47295,
"speedoverground" : 6.0,
"courseovergroundtrue" : 197.4,
"windspeedapparent" : 10.9,
"anglespeedapparent" : -13.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.07, "navigation.speedThroughWater": 3.2461452668012454, "performance.velocityMadeGood": 2.896322955957371, "environment.wind.angleTrueWater": -0.40142572805035315, "environment.depth.belowTransducer": 34.89, "navigation.courseOverGroundMagnetic": 3.445454477148705, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:02:28.118Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.01045,
"longitude" : 23.46745,
"speedoverground" : 6.0,
"courseovergroundtrue" : 201.6,
"windspeedapparent" : 12.8,
"anglespeedapparent" : -26.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 3.98, "navigation.speedThroughWater": 3.2101341465673174, "performance.velocityMadeGood": 2.263556128989775, "environment.wind.angleTrueWater": -0.8203047486246348, "environment.depth.belowTransducer": 23.33, "navigation.courseOverGroundMagnetic": 3.518060174048247, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:03:28.140Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 60.00351666666667,
"longitude" : 23.461033333333333,
"speedoverground" : 5.1,
"courseovergroundtrue" : 210.5,
"windspeedapparent" : 12.0,
"anglespeedapparent" : -8.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.34, "navigation.speedThroughWater": 2.69054512604921, "performance.velocityMadeGood": 2.5207784163749767, "environment.wind.angleTrueWater": -0.3665191430024964, "environment.depth.belowTransducer": 18.21, "navigation.courseOverGroundMagnetic": 3.673219944585971, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:04:28.159Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.99755,
"longitude" : 23.45415,
"speedoverground" : 4.8,
"courseovergroundtrue" : 215.7,
"windspeedapparent" : 14.4,
"anglespeedapparent" : 6.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 4.86, "navigation.speedThroughWater": 2.5670784281043133, "performance.velocityMadeGood": 2.546500645113497, "environment.wind.angleTrueWater": 0.20943951028714078, "environment.depth.belowTransducer": 8.97, "navigation.courseOverGroundMagnetic": 3.765198796187073, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:05:28.169Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.99235,
"longitude" : 23.445683333333335,
"speedoverground" : 4.7,
"courseovergroundtrue" : 225.9,
"windspeedapparent" : 16.1,
"anglespeedapparent" : -5.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 6.075590428038464, "navigation.speedThroughWater": 2.5053450791318648, "performance.velocityMadeGood": 2.4641895131502323, "environment.wind.angleTrueWater": -0.12217304766749879, "environment.depth.belowTransducer": 7.03, "navigation.courseOverGroundMagnetic": 3.9426987811554253, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:06:28.196Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.989266666666666,
"longitude" : 23.438766666666666,
"speedoverground" : 1.9,
"courseovergroundtrue" : 223.2,
"windspeedapparent" : 16.7,
"anglespeedapparent" : 3.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 7.61, "navigation.speedThroughWater": 1.0134558122976947, "performance.velocityMadeGood": 0.9825891378114705, "environment.wind.angleTrueWater": 0.052359877571785195, "environment.depth.belowTransducer": 5.78, "navigation.courseOverGroundMagnetic": 3.89522582549034, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:07:28.205Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.98786666666667,
"longitude" : 23.435116666666666,
"speedoverground" : 1.9,
"courseovergroundtrue" : 229.6,
"windspeedapparent" : 18.1,
"anglespeedapparent" : -5.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 8.02, "navigation.speedThroughWater": 1.0186002580453988, "performance.velocityMadeGood": 0.9620113548206545, "environment.wind.angleTrueWater": -0.19198621776321237, "environment.depth.belowTransducer": 5.33, "navigation.courseOverGroundMagnetic": 4.007799562269678, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:08:28.218Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.986333333333334,
"longitude" : 23.43165,
"speedoverground" : 1.4,
"courseovergroundtrue" : 204.7,
"windspeedapparent" : 14.8,
"anglespeedapparent" : 4.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 6.3, "navigation.speedThroughWater": 0.745944633417085, "performance.velocityMadeGood": 0.7408001876693809, "environment.wind.angleTrueWater": 0, "environment.depth.belowTransducer": 5.49, "navigation.courseOverGroundMagnetic": 3.5732125784238606, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:09:28.241Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.984833333333334,
"longitude" : 23.4292,
"speedoverground" : 1.3,
"courseovergroundtrue" : 225.8,
"windspeedapparent" : 13.4,
"anglespeedapparent" : -20.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 4.48, "navigation.speedThroughWater": 0.745944633417085, "performance.velocityMadeGood": 0.7613779706601971, "environment.wind.angleTrueWater": -0.40142572805035315, "environment.depth.belowTransducer": 7.8, "navigation.courseOverGroundMagnetic": 3.9414770506787504, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:10:28.257Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.9862,
"longitude" : 23.432566666666666,
"speedoverground" : 3.3,
"courseovergroundtrue" : 41.1,
"windspeedapparent" : 16.1,
"anglespeedapparent" : 175.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 9.93, "navigation.speedThroughWater": 1.6205004105267706, "performance.velocityMadeGood": -1.6153559647790667, "environment.wind.angleTrueWater": 3.071779484211398, "environment.depth.belowTransducer": 5.41, "navigation.courseOverGroundMagnetic": 0.7171557898082179, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:11:43.288Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.98726666666666,
"longitude" : 23.43375,
"speedoverground" : 1.7,
"courseovergroundtrue" : 228.8,
"windspeedapparent" : 15.7,
"anglespeedapparent" : 8.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 6.37, "navigation.speedThroughWater": 0.9825891378114705, "performance.velocityMadeGood": 0.8694113313619818, "environment.wind.angleTrueWater": 0.15707963271535558, "environment.depth.belowTransducer": 5.31, "navigation.courseOverGroundMagnetic": 3.9934878624000567, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:12:58.309Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.98615,
"longitude" : 23.431566666666665,
"speedoverground" : 1.0,
"courseovergroundtrue" : 223.5,
"windspeedapparent" : 22.1,
"anglespeedapparent" : -6.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 7.63, "navigation.speedThroughWater": 0.6687779472015245, "performance.velocityMadeGood": 0.61218904397678, "environment.wind.angleTrueWater": -0.12217304766749879, "environment.depth.belowTransducer": 5.71, "navigation.courseOverGroundMagnetic": 3.9011599449484757, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:13:58.309Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.98615,
"longitude" : 23.431566666666665,
"speedoverground" : 1.0,
"courseovergroundtrue" : 223.5,
"windspeedapparent" : 22.1,
"anglespeedapparent" : -6.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 7.63, "navigation.speedThroughWater": 0.6687779472015245, "performance.velocityMadeGood": 0.61218904397678, "environment.wind.angleTrueWater": -0.12217304766749879, "environment.depth.belowTransducer": 5.71, "navigation.courseOverGroundMagnetic": 3.9011599449484757, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:14:28.343Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.98565,
"longitude" : 23.4307,
"speedoverground" : 1.2,
"courseovergroundtrue" : 224.5,
"windspeedapparent" : 19.4,
"anglespeedapparent" : 2.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 5.83, "navigation.speedThroughWater": 0.7613779706601971, "performance.velocityMadeGood": 0.7150779589308607, "environment.wind.angleTrueWater": -0.29670597290678274, "environment.depth.belowTransducer": 6.44, "navigation.courseOverGroundMagnetic": 3.9177405728462076, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:15:28.366Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.98468333333334,
"longitude" : 23.429383333333334,
"speedoverground" : 6.1,
"courseovergroundtrue" : 219.9,
"windspeedapparent" : 13.2,
"anglespeedapparent" : 3.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 3.35, "navigation.speedThroughWater": 3.4622119882048152, "performance.velocityMadeGood": 3.32845639876451, "environment.wind.angleTrueWater": 0, "environment.depth.belowTransducer": 8.07, "navigation.courseOverGroundMagnetic": 3.837455427236137, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:16:28.373Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.978233333333336,
"longitude" : 23.42106666666667,
"speedoverground" : 5.3,
"courseovergroundtrue" : 216.7,
"windspeedapparent" : 15.3,
"anglespeedapparent" : -8.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 4.93, "navigation.speedThroughWater": 2.9632007506775238, "performance.velocityMadeGood": 2.772856258012474, "environment.wind.angleTrueWater": -0.20943951028714078, "environment.depth.belowTransducer": 5.16, "navigation.courseOverGroundMagnetic": 3.7824775557857624, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:17:28.386Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.977716666666666,
"longitude" : 23.431,
"speedoverground" : 2.1,
"courseovergroundtrue" : 151.9,
"windspeedapparent" : 12.8,
"anglespeedapparent" : 32.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.74, "navigation.speedThroughWater": 1.1214891729994796, "performance.velocityMadeGood": 0.2520778416374977, "environment.wind.angleTrueWater": 1.5533430346296275, "environment.depth.belowTransducer": 3.49, "navigation.courseOverGroundMagnetic": 2.6518532660856806, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:18:28.434Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.97688333333333,
"longitude" : 23.432133333333333,
"speedoverground" : 0.0,
"courseovergroundtrue" : 179.3,
"windspeedapparent" : 11.1,
"anglespeedapparent" : 88.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 3.1895563635765014, "navigation.speedThroughWater": 0, "performance.velocityMadeGood": 0, "environment.wind.angleTrueWater": 1.8151424224885533, "environment.depth.belowTransducer": 1.67, "navigation.courseOverGroundMagnetic": 3.1290262836898832, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:19:28.467Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.97688333333333,
"longitude" : 23.4321,
"speedoverground" : 0.0,
"courseovergroundtrue" : 241.0,
"windspeedapparent" : 4.3,
"anglespeedapparent" : 74.0,
"status" : "moored",
"metrics" : {"environment.wind.speedTrue": 0, "navigation.speedThroughWater": 0, "performance.velocityMadeGood": 0, "environment.wind.angleTrueWater": 0.7853981635767779, "environment.depth.belowTransducer": 1.65, "navigation.courseOverGroundMagnetic": 4.206068965341505, "navigation.courseRhumbline.crossTrackError": 0, "propulsion.main.runTime":1776251}
},
{
"time" : "2022-07-30T15:20:28.467Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.97688333333333,
"longitude" : 23.4321,
"speedoverground" : 0.0,
"courseovergroundtrue" : 241.0,
"windspeedapparent" : 4.3,
"anglespeedapparent" : 74.0,
"status" : "moored",
"metrics" : {"environment.wind.speedTrue": 0, "navigation.speedThroughWater": 0, "performance.velocityMadeGood": 0, "environment.wind.angleTrueWater": 0.7853981635767779, "environment.depth.belowTransducer": 1.65, "navigation.courseOverGroundMagnetic": 4.206068965341505, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:21:28.467Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.97688333333333,
"longitude" : 23.4321,
"speedoverground" : 0.0,
"courseovergroundtrue" : 241.0,
"windspeedapparent" : 4.3,
"anglespeedapparent" : 74.0,
"status" : "moored",
"metrics" : {"environment.wind.speedTrue": 0, "navigation.speedThroughWater": 0, "performance.velocityMadeGood": 0, "environment.wind.angleTrueWater": 0.7853981635767779, "environment.depth.belowTransducer": 1.65, "navigation.courseOverGroundMagnetic": 4.206068965341505, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:22:28.479Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.9781,
"longitude" : 23.425533333333334,
"speedoverground" : 5.0,
"courseovergroundtrue" : 258.3,
"windspeedapparent" : 9.1,
"anglespeedapparent" : 11.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.24, "navigation.speedThroughWater": 2.577367319599721, "performance.velocityMadeGood": 2.3561561524484476, "environment.wind.angleTrueWater": 0.41887902057428156, "environment.depth.belowTransducer": 5.05, "navigation.courseOverGroundMagnetic": 4.507661860154987, "navigation.courseRhumbline.crossTrackError": 0, "propulsion.main.runTime": 1776251}
},
{
"time" : "2022-07-30T15:23:28.492Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.9738,
"longitude" : 23.41165,
"speedoverground" : 6.2,
"courseovergroundtrue" : 228.0,
"windspeedapparent" : 11.8,
"anglespeedapparent" : 12.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.92, "navigation.speedThroughWater": 3.194700809324205, "performance.velocityMadeGood": 2.5207784163749767, "environment.wind.angleTrueWater": 0.8028514561007063, "environment.depth.belowTransducer": 5.44, "navigation.courseOverGroundMagnetic": 3.9854593478390496, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:24:28.498Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.967,
"longitude" : 23.40138333333333,
"speedoverground" : 6.1,
"courseovergroundtrue" : 197.7,
"windspeedapparent" : 10.9,
"anglespeedapparent" : 16.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.99, "navigation.speedThroughWater": 3.215278592315021, "performance.velocityMadeGood": 1.2964003284214165, "environment.wind.angleTrueWater": 1.274090354246773, "environment.depth.belowTransducer": 5.74, "navigation.courseOverGroundMagnetic": 3.4508649978311228, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:25:28.540Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.958866666666665,
"longitude" : 23.395816666666665,
"speedoverground" : 6.2,
"courseovergroundtrue" : 203.9,
"windspeedapparent" : 10.5,
"anglespeedapparent" : 38.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 3.44, "navigation.speedThroughWater": 3.215278592315021, "performance.velocityMadeGood": 1.512467049824986, "environment.wind.angleTrueWater": 1.2566370617228446, "environment.depth.belowTransducer": 7.13, "navigation.courseOverGroundMagnetic": 3.5587263456290006, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:26:28.572Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.9508,
"longitude" : 23.390166666666666,
"speedoverground" : 6.2,
"courseovergroundtrue" : 200.6,
"windspeedapparent" : 12.0,
"anglespeedapparent" : 63.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 4.12, "navigation.speedThroughWater": 3.2461452668012454, "performance.velocityMadeGood": -1.3787114603846813, "environment.wind.angleTrueWater": 1.884955592584267, "environment.depth.belowTransducer": 8.6, "navigation.courseOverGroundMagnetic": 3.5004323485990794, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:27:28.599Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.94275,
"longitude" : 23.38365,
"speedoverground" : 6.3,
"courseovergroundtrue" : 206.9,
"windspeedapparent" : 7.8,
"anglespeedapparent" : 22.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 2.13, "navigation.speedThroughWater": 3.2255674838104293, "performance.velocityMadeGood": -1.1317780644948876, "environment.wind.angleTrueWater": 1.9373154701560522, "environment.depth.belowTransducer": 12.98, "navigation.courseOverGroundMagnetic": 3.6112607561260246, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:28:28.606Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.93578333333333,
"longitude" : 23.37245,
"speedoverground" : 6.5,
"courseovergroundtrue" : 227.5,
"windspeedapparent" : 7.6,
"anglespeedapparent" : -10.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 1.12, "navigation.speedThroughWater": 3.2307119295581335, "performance.velocityMadeGood": -2.896322955957371, "environment.wind.angleTrueWater": -2.7750735113046154, "environment.depth.belowTransducer": 11.7, "navigation.courseOverGroundMagnetic": 3.9704495162684714, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:29:28.619Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.93076666666666,
"longitude" : 23.3572,
"speedoverground" : 6.3,
"courseovergroundtrue" : 232.5,
"windspeedapparent" : 6.8,
"anglespeedapparent" : 19.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.92, "navigation.speedThroughWater": 3.2307119295581335, "performance.velocityMadeGood": -1.960033829875237, "environment.wind.angleTrueWater": 2.2165681505389068, "environment.depth.belowTransducer": 14.23, "navigation.courseOverGroundMagnetic": 4.05858864351431, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:30:28.637Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.925133333333335,
"longitude" : 23.3448,
"speedoverground" : 5.9,
"courseovergroundtrue" : 228.4,
"windspeedapparent" : 7.2,
"anglespeedapparent" : 13.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.82, "navigation.speedThroughWater": 3.2358563753058376, "performance.velocityMadeGood": -2.1246560938017662, "environment.wind.angleTrueWater": 2.373647783254262, "environment.depth.belowTransducer": 14.29, "navigation.courseOverGroundMagnetic": 3.986855611240964, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:31:28.668Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.918933333333335,
"longitude" : 23.33415,
"speedoverground" : 6.0,
"courseovergroundtrue" : 211.6,
"windspeedapparent" : 6.4,
"anglespeedapparent" : -15.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.86, "navigation.speedThroughWater": 3.2255674838104293, "performance.velocityMadeGood": -0.38068898533009854, "environment.wind.angleTrueWater": -1.7278759598689115, "environment.depth.belowTransducer": 18.1, "navigation.courseOverGroundMagnetic": 3.6927676322127705, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:32:28.735Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.9114,
"longitude" : 23.32743333333333,
"speedoverground" : 6.2,
"courseovergroundtrue" : 175.6,
"windspeedapparent" : 6.4,
"anglespeedapparent" : -8.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.36, "navigation.speedThroughWater": 3.199845255071909, "performance.velocityMadeGood": -0.3189556363576501, "environment.wind.angleTrueWater": -1.6057029122014126, "environment.depth.belowTransducer": 10.95, "navigation.courseOverGroundMagnetic": 3.064972700127066, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:33:28.757Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.90315,
"longitude" : 23.329966666666667,
"speedoverground" : 6.1,
"courseovergroundtrue" : 144.0,
"windspeedapparent" : 5.8,
"anglespeedapparent" : -3.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.24, "navigation.speedThroughWater": 3.2049897008196133, "performance.velocityMadeGood": -2.4847672961410483, "environment.wind.angleTrueWater": -2.3911010757781903, "environment.depth.belowTransducer": 13.92, "navigation.courseOverGroundMagnetic": 2.512575991744732, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:34:28.787Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.89735,
"longitude" : 23.3428,
"speedoverground" : 6.3,
"courseovergroundtrue" : 129.8,
"windspeedapparent" : 5.2,
"anglespeedapparent" : -2.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 1, "navigation.speedThroughWater": 3.2307119295581335, "performance.velocityMadeGood": -3.1895563635765014, "environment.wind.angleTrueWater": -2.932153144019971, "environment.depth.belowTransducer": 11.32, "navigation.courseOverGroundMagnetic": 2.265960968381624, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:35:28.798Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.88953333333333,
"longitude" : 23.3492,
"speedoverground" : 6.5,
"courseovergroundtrue" : 162.5,
"windspeedapparent" : 7.2,
"anglespeedapparent" : -7.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.95, "navigation.speedThroughWater": 3.199845255071909, "performance.velocityMadeGood": -3.050656328388492, "environment.wind.angleTrueWater": -2.844886681400329, "environment.depth.belowTransducer": 10.04, "navigation.courseOverGroundMagnetic": 2.8354619034374076, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:36:28.812Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.88126666666667,
"longitude" : 23.345833333333335,
"speedoverground" : 6.1,
"courseovergroundtrue" : 196.5,
"windspeedapparent" : 8.7,
"anglespeedapparent" : -15.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.87, "navigation.speedThroughWater": 3.199845255071909, "performance.velocityMadeGood": -1.1832225219719277, "environment.wind.angleTrueWater": -1.972222055203909, "environment.depth.belowTransducer": 22.3, "navigation.courseOverGroundMagnetic": 3.429921046802409, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:37:28.835Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.87278333333333,
"longitude" : 23.344066666666667,
"speedoverground" : 6.2,
"courseovergroundtrue" : 160.5,
"windspeedapparent" : 7.8,
"anglespeedapparent" : -5.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.57, "navigation.speedThroughWater": 3.174123026333389, "performance.velocityMadeGood": 2.870600727218851, "environment.wind.angleTrueWater": -0.261799387858926, "environment.depth.belowTransducer": 24.73, "navigation.courseOverGroundMagnetic": 2.8016025159409867, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:38:28.838Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.866616666666665,
"longitude" : 23.355716666666666,
"speedoverground" : 6.1,
"courseovergroundtrue" : 131.4,
"windspeedapparent" : 35.8,
"anglespeedapparent" : 9.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.51, "navigation.speedThroughWater": 3.2255674838104293, "performance.velocityMadeGood": -1.347844785898457, "environment.wind.angleTrueWater": 1.7453292523928399, "environment.depth.belowTransducer": 9.85, "navigation.courseOverGroundMagnetic": 2.292489973017995, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:39:28.867Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.86,
"longitude" : 23.365766666666666,
"speedoverground" : 5.8,
"courseovergroundtrue" : 122.0,
"windspeedapparent" : 37.2,
"anglespeedapparent" : 10.0,
"status" : "sailing",
"metrics" : {"environment.wind.speedTrue": 0.63, "navigation.speedThroughWater": 3.2255674838104293, "performance.velocityMadeGood": -2.242978345998959, "environment.wind.angleTrueWater": 2.3038346131585485, "environment.depth.belowTransducer": 17.73, "navigation.courseOverGroundMagnetic": 2.129127154994025, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:40:28.867Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.86,
"longitude" : 23.365766666666666,
"speedoverground" : 4.5,
"courseovergroundtrue" : 122.0,
"windspeedapparent" : 7.2,
"anglespeedapparent" : 10.0,
"status" : "anchored",
"metrics" : {"environment.wind.speedTrue": 0.63, "navigation.speedThroughWater": 3.2255674838104293, "performance.velocityMadeGood": -2.242978345998959, "environment.wind.angleTrueWater": 2.3038346131585485, "environment.depth.belowTransducer": 17.73, "navigation.courseOverGroundMagnetic": 2.129127154994025, "navigation.courseRhumbline.crossTrackError": 0, "propulsion.main.runTime":1776262}
},
{
"time" : "2022-07-30T15:41:28.867Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.86,
"longitude" : 23.365766666666666,
"speedoverground" : 0.0,
"courseovergroundtrue" : 122.0,
"windspeedapparent" : 7.2,
"anglespeedapparent" : 10.0,
"status" : "anchored",
"metrics" : {"environment.wind.speedTrue": 0.63, "navigation.speedThroughWater": 3.2255674838104293, "performance.velocityMadeGood": -2.242978345998959, "environment.wind.angleTrueWater": 2.3038346131585485, "environment.depth.belowTransducer": 17.73, "navigation.courseOverGroundMagnetic": 2.129127154994025, "navigation.courseRhumbline.crossTrackError": 0}
},
{
"time" : "2022-07-30T15:41:28.867Z",
"client_id" : "vessels.urn:mrn:imo:mmsi:123456789",
"latitude" : 59.86,
"longitude" : 23.365766666666666,
"speedoverground" : 0.0,
"courseovergroundtrue" : 122.0,
"windspeedapparent" : 7.2,
"anglespeedapparent" : 10.0,
"status" : "anchored",
"metrics" : {"environment.wind.speedTrue": 0.63, "navigation.speedThroughWater": 3.2255674838104293, "performance.velocityMadeGood": -2.242978345998959, "environment.wind.angleTrueWater": 2.3038346131585485, "environment.depth.belowTransducer": 17.73, "navigation.courseOverGroundMagnetic": 2.129127154994025, "navigation.courseRhumbline.crossTrackError": 0}
}
]}

View File

@@ -0,0 +1,879 @@
{
"metrics": [
{
"time" : "2022-12-13 20:39:04.562",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.3786471,
"longitude" : 2.277667383333333,
"speedoverground" : 4.1,
"courseovergroundtrue" : 17.4,
"windspeedapparent" : 8.1,
"anglespeedapparent" : -32.3,
"status" : "moored",
"metrics" : {"navigation.headingTrue": 0.3036872899163541, "environment.wind.speedTrue": 1.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.3036872899163541, "environment.depth.belowKeel": 9.3, "navigation.speedThroughWater": 2.109222756558654, "environment.water.temperature": 280.75, "environment.depth.belowSurface": 9.3, "environment.wind.directionTrue": 5.223770452411769, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 0, "propulsion.engine_2.revolutions": 0, "environment.depth.belowTransducer": 9.3, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 5.223770452411769, "navigation.gnss.horizontalDilution": 1.8, "navigation.courseOverGroundMagnetic": 0.3036872899163541, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670963929}
},
{
"time" : "2022-12-13 20:40:04.568",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.37983186666666,
"longitude" : 2.2781615333333334,
"speedoverground" : 4.1,
"courseovergroundtrue" : 16.5,
"windspeedapparent" : 6.0,
"anglespeedapparent" : -25.2,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.28797932664481857, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.28797932664481857, "environment.depth.belowKeel": 11.8, "navigation.speedThroughWater": 2.109222756558654, "environment.water.temperature": 280.95, "environment.depth.belowSurface": 11.8, "environment.wind.directionTrue": 5.483824511018303, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 0, "propulsion.engine_2.revolutions": 0, "environment.depth.belowTransducer": 11.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 5.483824511018303, "navigation.gnss.horizontalDilution": 1.7, "navigation.courseOverGroundMagnetic": 0.28797932664481857, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670963985}
},
{
"time" : "2022-12-13 20:41:04.592",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.380872266666664,
"longitude" : 2.2785093333333335,
"speedoverground" : 4.1,
"courseovergroundtrue" : 13.6,
"windspeedapparent" : 7.2,
"anglespeedapparent" : -34.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.2373647783254262, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.2373647783254262, "environment.depth.belowKeel": 10.7, "navigation.speedThroughWater": 2.109222756558654, "environment.water.temperature": 281.15, "environment.depth.belowSurface": 10.7, "environment.wind.directionTrue": 4.974188369319593, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 0, "propulsion.engine_2.revolutions": 0, "environment.depth.belowTransducer": 10.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 4.974188369319593, "navigation.gnss.horizontalDilution": 1.3, "navigation.courseOverGroundMagnetic": 0.2373647783254262, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964045}
},
{
"time" : "2022-12-13 20:42:04.609",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.38208281666667,
"longitude" : 2.2788272,
"speedoverground" : 4.2,
"courseovergroundtrue" : 10.7,
"windspeedapparent" : 10.0,
"anglespeedapparent" : -39.2,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.18675023000603386, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.18675023000603386, "environment.depth.belowKeel": 12.4, "navigation.speedThroughWater": 2.1606672140356946, "environment.water.temperature": 281.15, "environment.depth.belowSurface": 12.4, "environment.wind.directionTrue": 5.223770452411769, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10, "propulsion.engine_2.revolutions": 10, "environment.depth.belowTransducer": 12.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 5.223770452411769, "navigation.gnss.horizontalDilution": 1.6, "navigation.courseOverGroundMagnetic": 0.18675023000603386, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964109}
},
{
"time" : "2022-12-13 20:43:04.645",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.383208116666665,
"longitude" : 2.2791273833333334,
"speedoverground" : 4.1,
"courseovergroundtrue" : 11.2,
"windspeedapparent" : 6.5,
"anglespeedapparent" : -10.8,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.19547687626799803, "environment.wind.speedTrue": 1.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.19547687626799803, "environment.depth.belowKeel": 14.4, "navigation.speedThroughWater": 2.109222756558654, "environment.water.temperature": 280.95, "environment.depth.belowSurface": 14.4, "environment.wind.directionTrue": 5.967280713931119, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.403333333333334, "propulsion.engine_2.revolutions": 10.2, "environment.depth.belowTransducer": 14.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 5.967280713931119, "navigation.gnss.horizontalDilution": 1.7, "navigation.courseOverGroundMagnetic": 0.19547687626799803, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964164}
},
{
"time" : "2022-12-13 20:44:04.683",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.38424145,
"longitude" : 2.27946345,
"speedoverground" : 4.2,
"courseovergroundtrue" : 13.6,
"windspeedapparent" : 7.0,
"anglespeedapparent" : -12.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.2373647783254262, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.2373647783254262, "environment.depth.belowKeel": 11.8, "navigation.speedThroughWater": 2.1606672140356946, "environment.water.temperature": 280.95, "environment.depth.belowSurface": 11.8, "environment.wind.directionTrue": 5.967280713931119, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.403333333333334, "propulsion.engine_2.revolutions": 10, "environment.depth.belowTransducer": 11.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 5.967280713931119, "navigation.gnss.horizontalDilution": 1.3, "navigation.courseOverGroundMagnetic": 0.2373647783254262, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964225}
},
{
"time" : "2022-12-13 20:45:04.722",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.385386716666666,
"longitude" : 2.2798840166666667,
"speedoverground" : 4.2,
"courseovergroundtrue" : 15.8,
"windspeedapparent" : 5.2,
"anglespeedapparent" : -34.4,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.2757620218780687, "environment.wind.speedTrue": 1.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.2757620218780687, "environment.depth.belowKeel": 15.1, "navigation.speedThroughWater": 2.1606672140356946, "environment.water.temperature": 280.75, "environment.depth.belowSurface": 15.1, "environment.wind.directionTrue": 4.241150083314601, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.2, "propulsion.engine_2.revolutions": 11.04, "environment.depth.belowTransducer": 15.1, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 4.241150083314601, "navigation.gnss.horizontalDilution": 1.2, "navigation.courseOverGroundMagnetic": 0.2757620218780687, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964290}
},
{
"time" : "2022-12-13 20:46:04.743",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.38658911666667,
"longitude" : 2.2802688166666667,
"speedoverground" : 4.6,
"courseovergroundtrue" : 13.6,
"windspeedapparent" : 2.8,
"anglespeedapparent" : 166.2,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.2373647783254262, "environment.wind.speedTrue": 3.1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.2373647783254262, "environment.depth.belowKeel": 10.7, "navigation.speedThroughWater": 2.3664450439438554, "environment.water.temperature": 280.54999999999995, "environment.depth.belowSurface": 10.7, "environment.wind.directionTrue": 3.323106896555967, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.2, "propulsion.engine_2.revolutions": 10.403333333333334, "environment.depth.belowTransducer": 10.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 3.323106896555967, "navigation.gnss.horizontalDilution": 1.5, "navigation.courseOverGroundMagnetic": 0.2373647783254262, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964355}
},
{
"time" : "2022-12-13 20:47:04.759",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.387908966666664,
"longitude" : 2.2806784166666665,
"speedoverground" : 4.6,
"courseovergroundtrue" : 13.6,
"windspeedapparent" : 8.2,
"anglespeedapparent" : 138.2,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.2373647783254262, "environment.wind.speedTrue": 4.4, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.2373647783254262, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.3664450439438554, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 3.0141836188824342, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 10.403333333333334, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 3.0141836188824342, "navigation.gnss.horizontalDilution": 1.5, "navigation.courseOverGroundMagnetic": 0.2373647783254262, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964414}
},
{
"time" : "2022-12-13 20:48:04.770",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.389180233333335,
"longitude" : 2.28109,
"speedoverground" : 4.7,
"courseovergroundtrue" : 15.0,
"windspeedapparent" : 3.6,
"anglespeedapparent" : 60.8,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.261799387858926, "environment.wind.speedTrue": 2.1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.261799387858926, "environment.depth.belowKeel": 8.8, "navigation.speedThroughWater": 2.417889501420896, "environment.water.temperature": 279.84999999999997, "environment.depth.belowSurface": 8.8, "environment.wind.directionTrue": 2.733185609247187, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.2, "propulsion.engine_2.revolutions": 10.2, "environment.depth.belowTransducer": 8.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 2.733185609247187, "navigation.gnss.horizontalDilution": 1.7, "navigation.courseOverGroundMagnetic": 0.261799387858926, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964474}
},
{
"time" : "2022-12-13 20:49:04.782",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.39048306666667,
"longitude" : 2.28150255,
"speedoverground" : 4.8,
"courseovergroundtrue" : 12.3,
"windspeedapparent" : 5.2,
"anglespeedapparent" : 27.3,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.21467549804431932, "environment.wind.speedTrue": 1.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.21467549804431932, "environment.depth.belowKeel": 7.3, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 280.04999999999995, "environment.depth.belowSurface": 7.3, "environment.wind.directionTrue": 1.8500490075364102, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.486666666666668, "propulsion.engine_2.revolutions": 10.611666666666668, "environment.depth.belowTransducer": 7.3, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.8500490075364102, "navigation.gnss.horizontalDilution": 2, "navigation.courseOverGroundMagnetic": 0.21467549804431932, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964534}
},
{
"time" : "2022-12-13 20:50:04.811",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.3917979,
"longitude" : 2.28186645,
"speedoverground" : 4.8,
"courseovergroundtrue" : 10.2,
"windspeedapparent" : 8.3,
"anglespeedapparent" : 35.3,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.17802358374406965, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.17802358374406965, "environment.depth.belowKeel": 4.9, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 280.54999999999995, "environment.depth.belowSurface": 4.9, "environment.wind.directionTrue": 1.380555438642736, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 10, "environment.depth.belowTransducer": 4.9, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.380555438642736, "navigation.gnss.horizontalDilution": 2.3, "navigation.courseOverGroundMagnetic": 0.17802358374406965, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964595}
},
{
"time" : "2022-12-13 20:51:04.862",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.39308273333333,
"longitude" : 2.2821629833333335,
"speedoverground" : 5.0,
"courseovergroundtrue" : 10.2,
"windspeedapparent" : 8.6,
"anglespeedapparent" : 34.5,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.17802358374406965, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.17802358374406965, "environment.depth.belowKeel": 3.7, "navigation.speedThroughWater": 2.572222873852017, "environment.water.temperature": 280.65, "environment.depth.belowSurface": 3.7, "environment.wind.directionTrue": 1.380555438642736, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.486666666666668, "propulsion.engine_2.revolutions": 10.2, "environment.depth.belowTransducer": 3.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.380555438642736, "navigation.gnss.horizontalDilution": 2.3, "navigation.courseOverGroundMagnetic": 0.17802358374406965, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964654}
},
{
"time" : "2022-12-13 20:52:04.904",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.394408983333335,
"longitude" : 2.2825271833333334,
"speedoverground" : 4.8,
"courseovergroundtrue" : 11.2,
"windspeedapparent" : 9.5,
"anglespeedapparent" : 46.9,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.19547687626799803, "environment.wind.speedTrue": 3.7, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.19547687626799803, "environment.depth.belowKeel": 4.5, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 280.34999999999997, "environment.depth.belowSurface": 4.5, "environment.wind.directionTrue": 1.5219271080865564, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 10.403333333333334, "environment.depth.belowTransducer": 4.5, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.5219271080865564, "navigation.gnss.horizontalDilution": 2.3, "navigation.courseOverGroundMagnetic": 0.19547687626799803, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964714}
},
{
"time" : "2022-12-13 20:53:04.922",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.39573106666667,
"longitude" : 2.2829267166666667,
"speedoverground" : 4.9,
"courseovergroundtrue" : 12.3,
"windspeedapparent" : 10.2,
"anglespeedapparent" : 42.4,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.21467549804431932, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.21467549804431932, "environment.depth.belowKeel": 4.5, "navigation.speedThroughWater": 2.5207784163749767, "environment.water.temperature": 280.65, "environment.depth.belowSurface": 4.5, "environment.wind.directionTrue": 1.679006740801912, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 10, "environment.depth.belowTransducer": 4.5, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.679006740801912, "navigation.gnss.horizontalDilution": 3.4, "navigation.courseOverGroundMagnetic": 0.21467549804431932, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964775}
},
{
"time" : "2022-12-13 20:54:04.947",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.39700681666667,
"longitude" : 2.2833958666666665,
"speedoverground" : 4.9,
"courseovergroundtrue" : 16.5,
"windspeedapparent" : 8.0,
"anglespeedapparent" : 35.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.28797932664481857, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.28797932664481857, "environment.depth.belowKeel": 4.9, "navigation.speedThroughWater": 2.5207784163749767, "environment.water.temperature": 280.65, "environment.depth.belowSurface": 4.9, "environment.wind.directionTrue": 1.5219271080865564, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 10, "environment.depth.belowTransducer": 4.9, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.5219271080865564, "navigation.gnss.horizontalDilution": 4.4, "navigation.courseOverGroundMagnetic": 0.28797932664481857, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964835}
},
{
"time" : "2022-12-13 20:55:04.978",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.39837505,
"longitude" : 2.283934583333333,
"speedoverground" : 4.9,
"courseovergroundtrue" : 16.5,
"windspeedapparent" : 9.4,
"anglespeedapparent" : 27.9,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.28797932664481857, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.28797932664481857, "environment.depth.belowKeel": 6, "navigation.speedThroughWater": 2.5207784163749767, "environment.water.temperature": 280.65, "environment.depth.belowSurface": 6, "environment.wind.directionTrue": 1.253146403218059, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 10.2, "environment.depth.belowTransducer": 6, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.253146403218059, "navigation.gnss.horizontalDilution": 4.7, "navigation.courseOverGroundMagnetic": 0.28797932664481857, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964895}
},
{
"time" : "2022-12-13 20:56:04.996",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.39972915,
"longitude" : 2.2844581333333336,
"speedoverground" : 5.2,
"courseovergroundtrue" : 16.5,
"windspeedapparent" : 10.3,
"anglespeedapparent" : 23.8,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.28797932664481857, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.28797932664481857, "environment.depth.belowKeel": 5.4, "navigation.speedThroughWater": 2.675111788806098, "environment.water.temperature": 280.84999999999997, "environment.depth.belowSurface": 5.4, "environment.wind.directionTrue": 1.1362093433077387, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.486666666666668, "propulsion.engine_2.revolutions": 10.2, "environment.depth.belowTransducer": 5.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.1362093433077387, "navigation.gnss.horizontalDilution": 3.8, "navigation.courseOverGroundMagnetic": 0.28797932664481857, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670964954}
},
{
"time" : "2022-12-13 20:57:05.017",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.401043683333334,
"longitude" : 2.284932,
"speedoverground" : 5.3,
"courseovergroundtrue" : 15.0,
"windspeedapparent" : 14.3,
"anglespeedapparent" : 33.6,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.261799387858926, "environment.wind.speedTrue": 5.3, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.261799387858926, "environment.depth.belowKeel": 4.9, "navigation.speedThroughWater": 2.726556246283138, "environment.water.temperature": 280.65, "environment.depth.belowSurface": 4.9, "environment.wind.directionTrue": 1.1362093433077387, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 10.2, "environment.depth.belowTransducer": 4.9, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.1362093433077387, "navigation.gnss.horizontalDilution": 3.8, "navigation.courseOverGroundMagnetic": 0.261799387858926, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965014}
},
{
"time" : "2022-12-13 20:58:05.043",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.40248723333333,
"longitude" : 2.2853501666666665,
"speedoverground" : 5.2,
"courseovergroundtrue" : 11.2,
"windspeedapparent" : 25.2,
"anglespeedapparent" : 36.0,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.19547687626799803, "environment.wind.speedTrue": 7.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.19547687626799803, "environment.depth.belowKeel": 5.4, "navigation.speedThroughWater": 2.675111788806098, "environment.water.temperature": 280.65, "environment.depth.belowSurface": 5.4, "environment.wind.directionTrue": 1.0297442589117756, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.2, "propulsion.engine_2.revolutions": 10.2, "environment.depth.belowTransducer": 5.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.0297442589117756, "navigation.gnss.horizontalDilution": 4.4, "navigation.courseOverGroundMagnetic": 0.19547687626799803, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965075}
},
{
"time" : "2022-12-13 20:59:05.063",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.40396921666667,
"longitude" : 2.28573555,
"speedoverground" : 5.6,
"courseovergroundtrue" : 10.2,
"windspeedapparent" : 14.6,
"anglespeedapparent" : 27.6,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.17802358374406965, "environment.wind.speedTrue": 3.7, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.17802358374406965, "environment.depth.belowKeel": 5.4, "navigation.speedThroughWater": 2.8808896187142587, "environment.water.temperature": 280.65, "environment.depth.belowSurface": 5.4, "environment.wind.directionTrue": 1.0297442589117756, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.825, "propulsion.engine_2.revolutions": 10.611666666666668, "environment.depth.belowTransducer": 5.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.0297442589117756, "navigation.gnss.horizontalDilution": 4.4, "navigation.courseOverGroundMagnetic": 0.17802358374406965, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965135}
},
{
"time" : "2022-12-13 21:00:05.096",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.40549068333333,
"longitude" : 2.2861892666666668,
"speedoverground" : 5.5,
"courseovergroundtrue" : 13.6,
"windspeedapparent" : 15.4,
"anglespeedapparent" : 20.0,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.2373647783254262, "environment.wind.speedTrue": 5.3, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.2373647783254262, "environment.depth.belowKeel": 4.9, "navigation.speedThroughWater": 2.829445161237219, "environment.water.temperature": 280.65, "environment.depth.belowSurface": 4.9, "environment.wind.directionTrue": 0.7696902003052424, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.403333333333334, "propulsion.engine_2.revolutions": 10.825, "environment.depth.belowTransducer": 4.9, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.7696902003052424, "navigation.gnss.horizontalDilution": 4.7, "navigation.courseOverGroundMagnetic": 0.2373647783254262, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965195}
},
{
"time" : "2022-12-13 21:01:05.130",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.406966833333335,
"longitude" : 2.2866105,
"speedoverground" : 5.5,
"courseovergroundtrue" : 10.2,
"windspeedapparent" : 19.4,
"anglespeedapparent" : 24.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.17802358374406965, "environment.wind.speedTrue": 3.7, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.17802358374406965, "environment.depth.belowKeel": 4.5, "navigation.speedThroughWater": 2.829445161237219, "environment.water.temperature": 280.54999999999995, "environment.depth.belowSurface": 4.5, "environment.wind.directionTrue": 0.9337511500301693, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10, "propulsion.engine_2.revolutions": 12.19, "environment.depth.belowTransducer": 4.5, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.9337511500301693, "navigation.gnss.horizontalDilution": 5, "navigation.courseOverGroundMagnetic": 0.17802358374406965, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965255}
},
{
"time" : "2022-12-13 21:02:05.156",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.40843818333333,
"longitude" : 2.2869834833333336,
"speedoverground" : 5.3,
"courseovergroundtrue" : 10.2,
"windspeedapparent" : 14.6,
"anglespeedapparent" : 29.0,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.17802358374406965, "environment.wind.speedTrue": 5.3, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.17802358374406965, "environment.depth.belowKeel": 4.9, "navigation.speedThroughWater": 2.726556246283138, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 4.9, "environment.wind.directionTrue": 0.9337511500301693, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.825, "propulsion.engine_2.revolutions": 11.716666666666667, "environment.depth.belowTransducer": 4.9, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.9337511500301693, "navigation.gnss.horizontalDilution": 3.3, "navigation.courseOverGroundMagnetic": 0.17802358374406965, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965315}
},
{
"time" : "2022-12-13 21:03:05.202",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.40989965,
"longitude" : 2.287289433333333,
"speedoverground" : 5.4,
"courseovergroundtrue" : 9.2,
"windspeedapparent" : 14.4,
"anglespeedapparent" : 26.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.16057029122014124, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.16057029122014124, "environment.depth.belowKeel": 6, "navigation.speedThroughWater": 2.7780007037601786, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 6, "environment.wind.directionTrue": 1.1362093433077387, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.403333333333334, "propulsion.engine_2.revolutions": 11.261666666666667, "environment.depth.belowTransducer": 6, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.1362093433077387, "navigation.gnss.horizontalDilution": 3.8, "navigation.courseOverGroundMagnetic": 0.16057029122014124, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965375}
},
{
"time" : "2022-12-13 21:04:05.224",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.411323816666666,
"longitude" : 2.287555033333333,
"speedoverground" : 5.1,
"courseovergroundtrue" : 7.6,
"windspeedapparent" : 9.3,
"anglespeedapparent" : 22.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.1326450231818558, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.1326450231818558, "environment.depth.belowKeel": 5.4, "navigation.speedThroughWater": 2.6236673313290573, "environment.water.temperature": 279.95, "environment.depth.belowSurface": 5.4, "environment.wind.directionTrue": 0.9337511500301693, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.261666666666667, "propulsion.engine_2.revolutions": 10.825, "environment.depth.belowTransducer": 5.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.9337511500301693, "navigation.gnss.horizontalDilution": 3.3, "navigation.courseOverGroundMagnetic": 0.1326450231818558, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965435}
},
{
"time" : "2022-12-13 21:05:05.253",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.412672,
"longitude" : 2.2878124166666667,
"speedoverground" : 4.7,
"courseovergroundtrue" : 8.4,
"windspeedapparent" : 16.5,
"anglespeedapparent" : 24.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.14660765720099855, "environment.wind.speedTrue": 5.3, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.14660765720099855, "environment.depth.belowKeel": 4.5, "navigation.speedThroughWater": 2.417889501420896, "environment.water.temperature": 279.65, "environment.depth.belowSurface": 4.5, "environment.wind.directionTrue": 0.7696902003052424, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.261666666666667, "propulsion.engine_2.revolutions": 10.825, "environment.depth.belowTransducer": 4.5, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.7696902003052424, "navigation.gnss.horizontalDilution": 5, "navigation.courseOverGroundMagnetic": 0.14660765720099855, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965495}
},
{
"time" : "2022-12-13 21:06:05.281",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.413960216666666,
"longitude" : 2.288052583333333,
"speedoverground" : 4.8,
"courseovergroundtrue" : 7.6,
"windspeedapparent" : 19.1,
"anglespeedapparent" : 24.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.1326450231818558, "environment.wind.speedTrue": 7.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.1326450231818558, "environment.depth.belowKeel": 3.3, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 279.65, "environment.depth.belowSurface": 3.3, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.716666666666667, "propulsion.engine_2.revolutions": 11.716666666666667, "environment.depth.belowTransducer": 3.3, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 3.1, "navigation.courseOverGroundMagnetic": 0.1326450231818558, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965555}
},
{
"time" : "2022-12-13 21:07:05.315",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.41527805,
"longitude" : 2.288307083333333,
"speedoverground" : 4.8,
"courseovergroundtrue" : 7.6,
"windspeedapparent" : 22.1,
"anglespeedapparent" : 22.3,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.1326450231818558, "environment.wind.speedTrue": 5.3, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.1326450231818558, "environment.depth.belowKeel": 4, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 279.54999999999995, "environment.depth.belowSurface": 4, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.261666666666667, "propulsion.engine_2.revolutions": 12.681666666666667, "environment.depth.belowTransducer": 4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 2.7, "navigation.courseOverGroundMagnetic": 0.1326450231818558, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965615}
},
{
"time" : "2022-12-13 21:08:05.353",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.41658073333333,
"longitude" : 2.2885240166666665,
"speedoverground" : 4.7,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 16.6,
"anglespeedapparent" : 12.4,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 4.9, "navigation.speedThroughWater": 2.417889501420896, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 4.9, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.716666666666667, "propulsion.engine_2.revolutions": 14.860000000000001, "environment.depth.belowTransducer": 4.9, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 3.1, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965675}
},
{
"time" : "2022-12-13 21:09:05.371",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.41785333333333,
"longitude" : 2.2887258333333333,
"speedoverground" : 4.5,
"courseovergroundtrue" : 6.2,
"windspeedapparent" : 8.6,
"anglespeedapparent" : 9.2,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.10821041364835607, "environment.wind.speedTrue": 1.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.10821041364835607, "environment.depth.belowKeel": 6, "navigation.speedThroughWater": 2.3150005864668155, "environment.water.temperature": 279.25, "environment.depth.belowSurface": 6, "environment.wind.directionTrue": 0.5742133240372442, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.403333333333334, "propulsion.engine_2.revolutions": 13.195, "environment.depth.belowTransducer": 6, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5742133240372442, "navigation.gnss.horizontalDilution": 2.7, "navigation.courseOverGroundMagnetic": 0.10821041364835607, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965735}
},
{
"time" : "2022-12-13 21:10:05.404",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.41911275,
"longitude" : 2.28890385,
"speedoverground" : 4.6,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 7.2,
"anglespeedapparent" : 7.8,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 7.3, "navigation.speedThroughWater": 2.3664450439438554, "environment.water.temperature": 279.25, "environment.depth.belowSurface": 7.3, "environment.wind.directionTrue": 0.5742133240372442, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 12.681666666666667, "environment.depth.belowTransducer": 7.3, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5742133240372442, "navigation.gnss.horizontalDilution": 2.7, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965795}
},
{
"time" : "2022-12-13 21:11:05.414",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.42043938333333,
"longitude" : 2.2891021,
"speedoverground" : 4.8,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 7.5,
"anglespeedapparent" : 9.6,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 7.3, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 279.54999999999995, "environment.depth.belowSurface": 7.3, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 12.681666666666667, "environment.depth.belowTransducer": 7.3, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 4.1, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965855}
},
{
"time" : "2022-12-13 21:12:05.470",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.42173171666666,
"longitude" : 2.2892923166666668,
"speedoverground" : 4.5,
"courseovergroundtrue" : 5.7,
"windspeedapparent" : 7.3,
"anglespeedapparent" : 14.8,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.09948376738639188, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.09948376738639188, "environment.depth.belowKeel": 7.3, "navigation.speedThroughWater": 2.3150005864668155, "environment.water.temperature": 279.54999999999995, "environment.depth.belowSurface": 7.3, "environment.wind.directionTrue": 0.7696902003052424, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 12.681666666666667, "environment.depth.belowTransducer": 7.3, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.7696902003052424, "navigation.gnss.horizontalDilution": 5, "navigation.courseOverGroundMagnetic": 0.09948376738639188, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965915}
},
{
"time" : "2022-12-13 21:13:05.493",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.42296415,
"longitude" : 2.28942895,
"speedoverground" : 4.4,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 6.9,
"anglespeedapparent" : 12.4,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 1.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 11.8, "navigation.speedThroughWater": 2.263556128989775, "environment.water.temperature": 279.84999999999997, "environment.depth.belowSurface": 11.8, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.2, "propulsion.engine_2.revolutions": 11.716666666666667, "environment.depth.belowTransducer": 11.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 4.1, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670965975}
},
{
"time" : "2022-12-13 21:14:05.507",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.42416923333333,
"longitude" : 2.2895500166666665,
"speedoverground" : 4.4,
"courseovergroundtrue" : 4.7,
"windspeedapparent" : 11.3,
"anglespeedapparent" : 13.3,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.08203047486246347, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08203047486246347, "environment.depth.belowKeel": 13, "navigation.speedThroughWater": 2.263556128989775, "environment.water.temperature": 280.04999999999995, "environment.depth.belowSurface": 13, "environment.wind.directionTrue": 0.5201081172130663, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 11.261666666666667, "environment.depth.belowTransducer": 13, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5201081172130663, "navigation.gnss.horizontalDilution": 4.7, "navigation.courseOverGroundMagnetic": 0.08203047486246347, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966035}
},
{
"time" : "2022-12-13 21:15:05.532",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.42538771666667,
"longitude" : 2.2896824166666665,
"speedoverground" : 4.5,
"courseovergroundtrue" : 4.7,
"windspeedapparent" : 9.1,
"anglespeedapparent" : 18.6,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.08203047486246347, "environment.wind.speedTrue": 2.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08203047486246347, "environment.depth.belowKeel": 14.4, "navigation.speedThroughWater": 2.3150005864668155, "environment.water.temperature": 279.84999999999997, "environment.depth.belowSurface": 14.4, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 12.19, "environment.depth.belowTransducer": 14.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 3.6, "navigation.courseOverGroundMagnetic": 0.08203047486246347, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966095}
},
{
"time" : "2022-12-13 21:16:05.578",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.42659741666667,
"longitude" : 2.2898227,
"speedoverground" : 4.4,
"courseovergroundtrue" : 4.7,
"windspeedapparent" : 11.2,
"anglespeedapparent" : 19.6,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.08203047486246347, "environment.wind.speedTrue": 3.7, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08203047486246347, "environment.depth.belowKeel": 13, "navigation.speedThroughWater": 2.263556128989775, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 13, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 12.681666666666667, "environment.depth.belowTransducer": 13, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 5, "navigation.courseOverGroundMagnetic": 0.08203047486246347, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966155}
},
{
"time" : "2022-12-13 21:17:05.597",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.42780106666667,
"longitude" : 2.2899329666666666,
"speedoverground" : 4.3,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 12.5,
"anglespeedapparent" : 15.5,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 1.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 14.4, "navigation.speedThroughWater": 2.2121116715127345, "environment.water.temperature": 279.95, "environment.depth.belowSurface": 14.4, "environment.wind.directionTrue": 0.8482300166629202, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 12.19, "environment.depth.belowTransducer": 14.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.8482300166629202, "navigation.gnss.horizontalDilution": 2.7, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966215}
},
{
"time" : "2022-12-13 21:18:05.608",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.42899953333333,
"longitude" : 2.2900571666666667,
"speedoverground" : 4.3,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 9.2,
"anglespeedapparent" : 32.1,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 3.1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 15.8, "navigation.speedThroughWater": 2.2121116715127345, "environment.water.temperature": 279.84999999999997, "environment.depth.belowSurface": 15.8, "environment.wind.directionTrue": 1.0297442589117756, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 11.716666666666667, "environment.depth.belowTransducer": 15.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.0297442589117756, "navigation.gnss.horizontalDilution": 3.1, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966275}
},
{
"time" : "2022-12-13 21:19:05.630",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.43017308333334,
"longitude" : 2.290175666666667,
"speedoverground" : 4.2,
"courseovergroundtrue" : 4.7,
"windspeedapparent" : 12.2,
"anglespeedapparent" : 26.6,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.08203047486246347, "environment.wind.speedTrue": 4.4, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08203047486246347, "environment.depth.belowKeel": 11.8, "navigation.speedThroughWater": 2.1606672140356946, "environment.water.temperature": 279.95, "environment.depth.belowSurface": 11.8, "environment.wind.directionTrue": 0.7696902003052424, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 13.728333333333333, "environment.depth.belowTransducer": 11.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.7696902003052424, "navigation.gnss.horizontalDilution": 3.6, "navigation.courseOverGroundMagnetic": 0.08203047486246347, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966335}
},
{
"time" : "2022-12-13 21:20:05.651",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.431364,
"longitude" : 2.2902968333333336,
"speedoverground" : 4.2,
"courseovergroundtrue" : 4.7,
"windspeedapparent" : 9.9,
"anglespeedapparent" : 14.2,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.08203047486246347, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08203047486246347, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.1606672140356946, "environment.water.temperature": 279.95, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 13.195, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 3.6, "navigation.courseOverGroundMagnetic": 0.08203047486246347, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966395}
},
{
"time" : "2022-12-13 21:21:05.683",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.43257,
"longitude" : 2.2904335666666666,
"speedoverground" : 4.4,
"courseovergroundtrue" : 4.7,
"windspeedapparent" : 8.1,
"anglespeedapparent" : 19.1,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.08203047486246347, "environment.wind.speedTrue": 2.1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08203047486246347, "environment.depth.belowKeel": 11.8, "navigation.speedThroughWater": 2.263556128989775, "environment.water.temperature": 279.65, "environment.depth.belowSurface": 11.8, "environment.wind.directionTrue": 0.7696902003052424, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.486666666666668, "propulsion.engine_2.revolutions": 12.681666666666667, "environment.depth.belowTransducer": 11.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.7696902003052424, "navigation.gnss.horizontalDilution": 2.4, "navigation.courseOverGroundMagnetic": 0.08203047486246347, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966455}
},
{
"time" : "2022-12-13 21:22:05.702",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.4338153,
"longitude" : 2.2905634333333333,
"speedoverground" : 4.4,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 7.6,
"anglespeedapparent" : 10.9,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 13, "navigation.speedThroughWater": 2.263556128989775, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 13, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 13.195, "environment.depth.belowTransducer": 13, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 1.8, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966515}
},
{
"time" : "2022-12-13 21:23:05.714",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.43504795,
"longitude" : 2.2906984,
"speedoverground" : 4.5,
"courseovergroundtrue" : 4.7,
"windspeedapparent" : 8.0,
"anglespeedapparent" : 21.0,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.08203047486246347, "environment.wind.speedTrue": 2.1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08203047486246347, "environment.depth.belowKeel": 13, "navigation.speedThroughWater": 2.3150005864668155, "environment.water.temperature": 279.65, "environment.depth.belowSurface": 13, "environment.wind.directionTrue": 0.8482300166629202, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.2, "propulsion.engine_2.revolutions": 13.728333333333333, "environment.depth.belowTransducer": 13, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.8482300166629202, "navigation.gnss.horizontalDilution": 1.6, "navigation.courseOverGroundMagnetic": 0.08203047486246347, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966575}
},
{
"time" : "2022-12-13 21:24:05.728",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.436295183333336,
"longitude" : 2.2908305666666666,
"speedoverground" : 4.5,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 7.9,
"anglespeedapparent" : 20.9,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 11.8, "navigation.speedThroughWater": 2.3150005864668155, "environment.water.temperature": 279.54999999999995, "environment.depth.belowSurface": 11.8, "environment.wind.directionTrue": 1.0297442589117756, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.2, "propulsion.engine_2.revolutions": 14.281666666666666, "environment.depth.belowTransducer": 11.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 1.0297442589117756, "navigation.gnss.horizontalDilution": 1.4, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966635}
},
{
"time" : "2022-12-13 21:25:05.748",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.437534766666666,
"longitude" : 2.2909366166666665,
"speedoverground" : 4.5,
"courseovergroundtrue" : 3.1,
"windspeedapparent" : 7.9,
"anglespeedapparent" : 14.2,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.054105206824178034, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.054105206824178034, "environment.depth.belowKeel": 11.8, "navigation.speedThroughWater": 2.3150005864668155, "environment.water.temperature": 279.84999999999997, "environment.depth.belowSurface": 11.8, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10, "propulsion.engine_2.revolutions": 13.195, "environment.depth.belowTransducer": 11.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 0.9, "navigation.courseOverGroundMagnetic": 0.054105206824178034, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966695}
},
{
"time" : "2022-12-13 21:26:05.787",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.43881773333333,
"longitude" : 2.2910521833333335,
"speedoverground" : 4.6,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 8.5,
"anglespeedapparent" : 11.0,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 17.5, "navigation.speedThroughWater": 2.3664450439438554, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 17.5, "environment.wind.directionTrue": 0.5742133240372442, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.825, "propulsion.engine_2.revolutions": 13.728333333333333, "environment.depth.belowTransducer": 17.5, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5742133240372442, "navigation.gnss.horizontalDilution": 1.4, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966755}
},
{
"time" : "2022-12-13 21:27:05.827",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.4401189,
"longitude" : 2.2911686833333333,
"speedoverground" : 4.7,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 7.0,
"anglespeedapparent" : 7.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 1.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 23.4, "navigation.speedThroughWater": 2.417889501420896, "environment.water.temperature": 279.54999999999995, "environment.depth.belowSurface": 23.4, "environment.wind.directionTrue": 0.47123889814606673, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10, "propulsion.engine_2.revolutions": 14.281666666666666, "environment.depth.belowTransducer": 23.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.47123889814606673, "navigation.gnss.horizontalDilution": 1.2, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966815}
},
{
"time" : "2022-12-13 21:28:05.867",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.441560683333336,
"longitude" : 2.291303533333333,
"speedoverground" : 4.9,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 7.5,
"anglespeedapparent" : 11.8,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 28.4, "navigation.speedThroughWater": 2.5207784163749767, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 28.4, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.403333333333334, "propulsion.engine_2.revolutions": 16.085, "environment.depth.belowTransducer": 28.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 1.1, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966875}
},
{
"time" : "2022-12-13 21:29:05.889",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.44287495,
"longitude" : 2.291422783333333,
"speedoverground" : 4.7,
"courseovergroundtrue" : 3.8,
"windspeedapparent" : 10.4,
"anglespeedapparent" : 12.2,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.0663225115909279, "environment.wind.speedTrue": 1.5, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.0663225115909279, "environment.depth.belowKeel": 28.4, "navigation.speedThroughWater": 2.417889501420896, "environment.water.temperature": 279.54999999999995, "environment.depth.belowSurface": 28.4, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.825, "propulsion.engine_2.revolutions": 18.113333333333333, "environment.depth.belowTransducer": 28.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 1.2, "navigation.courseOverGroundMagnetic": 0.0663225115909279, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966935}
},
{
"time" : "2022-12-13 21:30:05.922",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.44416415,
"longitude" : 2.2915161166666667,
"speedoverground" : 4.7,
"courseovergroundtrue" : 2.9,
"windspeedapparent" : 10.1,
"anglespeedapparent" : 20.9,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.050614548319392355, "environment.wind.speedTrue": 3.1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.050614548319392355, "environment.depth.belowKeel": 23.4, "navigation.speedThroughWater": 2.417889501420896, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 23.4, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.825, "propulsion.engine_2.revolutions": 15.46, "environment.depth.belowTransducer": 23.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 1.4, "navigation.courseOverGroundMagnetic": 0.050614548319392355, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670966995}
},
{
"time" : "2022-12-13 21:31:05.937",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.44544285,
"longitude" : 2.2916172833333333,
"speedoverground" : 4.6,
"courseovergroundtrue" : 3.5,
"windspeedapparent" : 25.5,
"anglespeedapparent" : 23.5,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.06108652383374939, "environment.wind.speedTrue": 9.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.06108652383374939, "environment.depth.belowKeel": 19.3, "navigation.speedThroughWater": 2.3664450439438554, "environment.water.temperature": 279.25, "environment.depth.belowSurface": 19.3, "environment.wind.directionTrue": 0.5742133240372442, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.825, "propulsion.engine_2.revolutions": 16.085, "environment.depth.belowTransducer": 19.3, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5742133240372442, "navigation.gnss.horizontalDilution": 1.6, "navigation.courseOverGroundMagnetic": 0.06108652383374939, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967055}
},
{
"time" : "2022-12-13 21:32:05.953",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.44671025,
"longitude" : 2.2917142166666666,
"speedoverground" : 4.6,
"courseovergroundtrue" : 3.1,
"windspeedapparent" : 22.0,
"anglespeedapparent" : 17.4,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.054105206824178034, "environment.wind.speedTrue": 4.4, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.054105206824178034, "environment.depth.belowKeel": 21.2, "navigation.speedThroughWater": 2.3664450439438554, "environment.water.temperature": 279.54999999999995, "environment.depth.belowSurface": 21.2, "environment.wind.directionTrue": 0.5201081172130663, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.825, "propulsion.engine_2.revolutions": 16.735, "environment.depth.belowTransducer": 21.2, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5201081172130663, "navigation.gnss.horizontalDilution": 1.4, "navigation.courseOverGroundMagnetic": 0.054105206824178034, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967114}
},
{
"time" : "2022-12-13 21:33:05.972",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.447963533333336,
"longitude" : 2.2918140833333336,
"speedoverground" : 4.4,
"courseovergroundtrue" : 3.5,
"windspeedapparent" : 22.0,
"anglespeedapparent" : 21.8,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.06108652383374939, "environment.wind.speedTrue": 6.4, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.06108652383374939, "environment.depth.belowKeel": 23.4, "navigation.speedThroughWater": 2.263556128989775, "environment.water.temperature": 279.25, "environment.depth.belowSurface": 23.4, "environment.wind.directionTrue": 0.5742133240372442, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.825, "propulsion.engine_2.revolutions": 16.085, "environment.depth.belowTransducer": 23.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5742133240372442, "navigation.gnss.horizontalDilution": 1.6, "navigation.courseOverGroundMagnetic": 0.06108652383374939, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967175}
},
{
"time" : "2022-12-13 21:34:05.994",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.44916808333333,
"longitude" : 2.2919039666666667,
"speedoverground" : 4.3,
"courseovergroundtrue" : 3.1,
"windspeedapparent" : 21.7,
"anglespeedapparent" : 24.7,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.054105206824178034, "environment.wind.speedTrue": 6.4, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.054105206824178034, "environment.depth.belowKeel": 23.4, "navigation.speedThroughWater": 2.2121116715127345, "environment.water.temperature": 279.04999999999995, "environment.depth.belowSurface": 23.4, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.261666666666667, "propulsion.engine_2.revolutions": 18.845000000000002, "environment.depth.belowTransducer": 23.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 1.6, "navigation.courseOverGroundMagnetic": 0.054105206824178034, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967235}
},
{
"time" : "2022-12-13 21:35:06.024",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.45040101666667,
"longitude" : 2.2919925833333332,
"speedoverground" : 4.5,
"courseovergroundtrue" : 3.5,
"windspeedapparent" : 14.3,
"anglespeedapparent" : 24.1,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.06108652383374939, "environment.wind.speedTrue": 4.4, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.06108652383374939, "environment.depth.belowKeel": 21.2, "navigation.speedThroughWater": 2.3150005864668155, "environment.water.temperature": 278.95, "environment.depth.belowSurface": 21.2, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10, "propulsion.engine_2.revolutions": 20.398333333333333, "environment.depth.belowTransducer": 21.2, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 1.8, "navigation.courseOverGroundMagnetic": 0.06108652383374939, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967295}
},
{
"time" : "2022-12-13 21:36:06.057",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.451662666666664,
"longitude" : 2.2920915833333333,
"speedoverground" : 4.6,
"courseovergroundtrue" : 3.1,
"windspeedapparent" : 29.1,
"anglespeedapparent" : 39.0,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.054105206824178034, "environment.wind.speedTrue": 13.2, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.054105206824178034, "environment.depth.belowKeel": 19.3, "navigation.speedThroughWater": 2.3664450439438554, "environment.water.temperature": 279.04999999999995, "environment.depth.belowSurface": 19.3, "environment.wind.directionTrue": 0.8482300166629202, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 19.60666666666667, "environment.depth.belowTransducer": 19.3, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.8482300166629202, "navigation.gnss.horizontalDilution": 1.8, "navigation.courseOverGroundMagnetic": 0.054105206824178034, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967355}
},
{
"time" : "2022-12-13 21:37:06.080",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.45293165,
"longitude" : 2.2921954833333333,
"speedoverground" : 4.7,
"courseovergroundtrue" : 3.8,
"windspeedapparent" : 44.2,
"anglespeedapparent" : 26.1,
"status" : "sailing",
"metrics" : {"navigation.headingTrue": 0.0663225115909279, "environment.wind.speedTrue": 20.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.0663225115909279, "environment.depth.belowKeel": 17.5, "navigation.speedThroughWater": 2.417889501420896, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 17.5, "environment.wind.directionTrue": 0.5742133240372442, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 22.08, "environment.depth.belowTransducer": 17.5, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5742133240372442, "navigation.gnss.horizontalDilution": 2.1, "navigation.courseOverGroundMagnetic": 0.0663225115909279, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967415}
},
{
"time" : "2022-12-13 21:38:06.100",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.45424523333333,
"longitude" : 2.2922960833333335,
"speedoverground" : 4.8,
"courseovergroundtrue" : 3.1,
"windspeedapparent" : 37.6,
"anglespeedapparent" : 14.2,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.054105206824178034, "environment.wind.speedTrue": 4.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.054105206824178034, "environment.depth.belowKeel": 15.8, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 15.8, "environment.wind.directionTrue": 0.42760566683624573, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 23.9, "environment.depth.belowTransducer": 15.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.42760566683624573, "navigation.gnss.horizontalDilution": 1.6, "navigation.courseOverGroundMagnetic": 0.054105206824178034, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967475}
},
{
"time" : "2022-12-13 21:39:06.118",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.4555779,
"longitude" : 2.292398116666667,
"speedoverground" : 4.8,
"courseovergroundtrue" : 3.5,
"windspeedapparent" : 15.7,
"anglespeedapparent" : 10.8,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.06108652383374939, "environment.wind.speedTrue": 3.3, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.06108652383374939, "environment.depth.belowKeel": 15.8, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 279.45, "environment.depth.belowSurface": 15.8, "environment.wind.directionTrue": 0.38746309403121043, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.2, "propulsion.engine_2.revolutions": 22.08, "environment.depth.belowTransducer": 15.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.38746309403121043, "navigation.gnss.horizontalDilution": 1.4, "navigation.courseOverGroundMagnetic": 0.06108652383374939, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967535}
},
{
"time" : "2022-12-13 21:40:06.142",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.45691458333334,
"longitude" : 2.2925072833333333,
"speedoverground" : 4.9,
"courseovergroundtrue" : 3.1,
"windspeedapparent" : 15.7,
"anglespeedapparent" : 15.7,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.054105206824178034, "environment.wind.speedTrue": 4.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.054105206824178034, "environment.depth.belowKeel": 15.8, "navigation.speedThroughWater": 2.5207784163749767, "environment.water.temperature": 279.65, "environment.depth.belowSurface": 15.8, "environment.wind.directionTrue": 0.47123889814606673, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 25.87, "environment.depth.belowTransducer": 15.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.47123889814606673, "navigation.gnss.horizontalDilution": 0.8, "navigation.courseOverGroundMagnetic": 0.054105206824178034, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967595}
},
{
"time" : "2022-12-13 21:41:06.155",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.458240233333335,
"longitude" : 2.2926219333333333,
"speedoverground" : 4.7,
"courseovergroundtrue" : 3.8,
"windspeedapparent" : 12.4,
"anglespeedapparent" : 9.2,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.0663225115909279, "environment.wind.speedTrue": 1.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.0663225115909279, "environment.depth.belowKeel": 14.4, "navigation.speedThroughWater": 2.417889501420896, "environment.water.temperature": 279.95, "environment.depth.belowSurface": 14.4, "environment.wind.directionTrue": 0.47123889814606673, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 10.611666666666668, "propulsion.engine_2.revolutions": 26.916666666666668, "environment.depth.belowTransducer": 14.4, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.47123889814606673, "navigation.gnss.horizontalDilution": 0.8, "navigation.courseOverGroundMagnetic": 0.0663225115909279, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967655}
},
{
"time" : "2022-12-13 21:42:06.187",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.45955073333333,
"longitude" : 2.2927578,
"speedoverground" : 4.8,
"courseovergroundtrue" : 4.7,
"windspeedapparent" : 9.8,
"anglespeedapparent" : 12.4,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.08203047486246347, "environment.wind.speedTrue": 1.6, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08203047486246347, "environment.depth.belowKeel": 13, "navigation.speedThroughWater": 2.4693339588979364, "environment.water.temperature": 279.84999999999997, "environment.depth.belowSurface": 13, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 25.87, "environment.depth.belowTransducer": 13, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 0.6, "navigation.courseOverGroundMagnetic": 0.08203047486246347, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967715}
},
{
"time" : "2022-12-13 21:43:06.208",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46092023333333,
"longitude" : 2.2929017833333334,
"speedoverground" : 5.0,
"courseovergroundtrue" : 4.2,
"windspeedapparent" : 8.2,
"anglespeedapparent" : 11.7,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.07330382860049928, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.07330382860049928, "environment.depth.belowKeel": 13, "navigation.speedThroughWater": 2.572222873852017, "environment.water.temperature": 279.84999999999997, "environment.depth.belowSurface": 13, "environment.wind.directionTrue": 0.5742133240372442, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 28.003333333333334, "environment.depth.belowTransducer": 13, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5742133240372442, "navigation.gnss.horizontalDilution": 0.5, "navigation.courseOverGroundMagnetic": 0.07330382860049928, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967775}
},
{
"time" : "2022-12-13 21:44:06.237",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46235585,
"longitude" : 2.2930669666666668,
"speedoverground" : 5.3,
"courseovergroundtrue" : 5.1,
"windspeedapparent" : 10.6,
"anglespeedapparent" : 13.7,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.08901179187203483, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.08901179187203483, "environment.depth.belowKeel": 11.8, "navigation.speedThroughWater": 2.726556246283138, "environment.water.temperature": 279.65, "environment.depth.belowSurface": 11.8, "environment.wind.directionTrue": 0.698131700957136, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 25.87, "environment.depth.belowTransducer": 11.8, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.698131700957136, "navigation.gnss.horizontalDilution": 0.6, "navigation.courseOverGroundMagnetic": 0.08901179187203483, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967835}
},
{
"time" : "2022-12-13 21:45:06.284",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46385398333334,
"longitude" : 2.2932485833333334,
"speedoverground" : 5.4,
"courseovergroundtrue" : 5.7,
"windspeedapparent" : 7.9,
"anglespeedapparent" : 7.3,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.09948376738639188, "environment.wind.speedTrue": 1, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.09948376738639188, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.7780007037601786, "environment.water.temperature": 280.04999999999995, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 0.5742133240372442, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 11.04, "propulsion.engine_2.revolutions": 23.9, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.5742133240372442, "navigation.gnss.horizontalDilution": 0.5, "navigation.courseOverGroundMagnetic": 0.09948376738639188, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967895}
},
{
"time" : "2022-12-13 21:46:06.327",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46533328333334,
"longitude" : 2.2934791,
"speedoverground" : 5.5,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 9.3,
"anglespeedapparent" : 11.3,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.829445161237219, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 12.433333333333334, "propulsion.engine_2.revolutions": 22.971666666666668, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 0.6, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967955}
},
{
"time" : "2022-12-13 21:47:06.327",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46533328333334,
"longitude" : 2.2934791,
"speedoverground" : 5.5,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 9.3,
"anglespeedapparent" : 11.3,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.829445161237219, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 12.433333333333334, "propulsion.engine_2.revolutions": 22.971666666666668, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 0.6, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967955}
},
{
"time" : "2022-12-13 21:48:06.327",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46533328333334,
"longitude" : 2.2934791,
"speedoverground" : 5.5,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 9.3,
"anglespeedapparent" : 11.3,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.829445161237219, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 12.433333333333334, "propulsion.engine_2.revolutions": 22.971666666666668, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 0.6, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967955}
},
{
"time" : "2022-12-13 21:49:06.327",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46533328333334,
"longitude" : 2.2934791,
"speedoverground" : 5.5,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 9.3,
"anglespeedapparent" : 11.3,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.829445161237219, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 12.433333333333334, "propulsion.engine_2.revolutions": 22.971666666666668, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 0.6, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967955}
},
{
"time" : "2022-12-13 21:50:06.327",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46533328333334,
"longitude" : 2.2934791,
"speedoverground" : 5.5,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 9.3,
"anglespeedapparent" : 11.3,
"status" : "motoring",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.829445161237219, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 12.433333333333334, "propulsion.engine_2.revolutions": 22.971666666666668, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 0.6, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967955}
},
{
"time" : "2022-12-13 21:51:06.327",
"client_id" : "vessels.urn:mrn:imo:mmsi:787654321",
"latitude" : 41.46533328333334,
"longitude" : 2.2934791,
"speedoverground" : 5.5,
"courseovergroundtrue" : 6.9,
"windspeedapparent" : 9.3,
"anglespeedapparent" : 11.3,
"status" : "moored",
"metrics" : {"navigation.headingTrue": 0.12042771841510595, "environment.wind.speedTrue": 1.8, "navigation.gnss.satellites": 4, "navigation.headingMagnetic": 0.12042771841510595, "environment.depth.belowKeel": 9.7, "navigation.speedThroughWater": 2.829445161237219, "environment.water.temperature": 280.25, "environment.depth.belowSurface": 9.7, "environment.wind.directionTrue": 0.6318091893662081, "navigation.gnss.antennaAltitude": 2, "navigation.gnss.differentialAge": 0, "propulsion.engine_1.revolutions": 12.433333333333334, "propulsion.engine_2.revolutions": 22.971666666666668, "environment.depth.belowTransducer": 9.7, "navigation.gnss.geoidalSeparation": 0, "environment.wind.directionMagnetic": 0.6318091893662081, "navigation.gnss.horizontalDilution": 0.6, "navigation.courseOverGroundMagnetic": 0.12042771841510595, "environment.depth.surfaceToTransducer": 0.3, "navigation.gnss.differentialReference": 0, "navigation.magneticVariationAgeOfService": 1670967955}
}
]}

12
tests/package.json Normal file
View File

@@ -0,0 +1,12 @@
{
"scripts": {
"tests": "mocha index.js"
},
"dependencies": {
"mocha": "^10.2.0",
"mochawesome": "^7.1.3",
"moment": "^2.29.4",
"should": "^13.2.3",
"supertest": "^6.3.3"
}
}

85
tests/sql/badges.sql Normal file
View File

@@ -0,0 +1,85 @@
---------------------------------------------------------------------------
-- Listing
--
-- List current database
select current_database();
-- connect to the DB
\c signalk
-- output display format
\x on
SELECT v.vessel_id as "vessel_id" FROM auth.vessels v WHERE v.owner_email = 'demo+kapla@openplotter.cloud' \gset
--\echo :"vessel_id"
SELECT set_config('vessel.id', :'vessel_id', false) IS NOT NULL as vessel_id;
\echo 'Insert new api.logbook for badges'
INSERT INTO api.logbook
(id, active, "name", "_from", "_from_lat", "_from_lng", "_to", "_to_lat", "_to_lng", track_geom, track_geog, track_geojson, "_from_time", "_to_time", distance, duration, avg_speed, max_speed, max_wind_speed, notes, vessel_id)
VALUES
(nextval('api.logbook_id_seq'), false, 'Tropics Zone', NULL, NULL, NULL, NULL, NULL, NULL, 'SRID=4326;LINESTRING (-63.151124640791096 14.01074681627324, -77.0912026418618 12.870995731013664)'::public.geometry, NULL, NULL, NOW(), NOW(), 123, NULL, NULL, NULL, NULL, NULL, current_setting('vessel.id', false)),
(nextval('api.logbook_id_seq'), false, 'Alaska Zone', NULL, NULL, NULL, NULL, NULL, NULL, 'SRID=4326;LINESTRING (-143.5773697471158 59.4404631255976, -152.35402122385003 56.58243132943173)'::public.geometry, NULL, NULL, NOW(), NOW(), 1234, NULL, NULL, NULL, NULL, NULL, current_setting('vessel.id', false));
\echo 'Set config'
SELECT set_config('user.email', 'demo+kapla@openplotter.cloud', false);
--SELECT set_config('vessel.client_id', 'vessels.urn:mrn:imo:mmsi:123456789', false);
\echo 'Process badge'
SELECT badges_logbook_fn(5);
SELECT badges_logbook_fn(6);
SELECT badges_geom_fn(5);
SELECT badges_geom_fn(6);
\echo 'Check badges for user'
SELECT jsonb_object_keys ( a.preferences->'badges' ) FROM auth.accounts a;
\echo 'Check details from vessel_id kapla'
--SELECT get_user_settings_from_vesselid_fn('vessels.urn:mrn:imo:mmsi:123456789'::TEXT);
SELECT
json_build_object(
'boat', v.name,
'recipient', a.first,
'email', v.owner_email,
--'settings', a.preferences,
'pushover_key', a.preferences->'pushover_key'
--'badges', a.preferences->'badges'
) as user_settings
FROM auth.accounts a, auth.vessels v, api.metadata m
WHERE m.vessel_id = v.vessel_id
AND m.vessel_id = current_setting('vessel.id', false)
AND lower(a.email) = current_setting('user.email', false);
\echo 'Insert new api.moorages for badges'
INSERT INTO api.moorages
(id,"name",country,stay_id,stay_code,stay_duration,reference_count,latitude,longitude,geog,home_flag,notes,vessel_id)
VALUES
(5,'Badge Mooring Pro',NULL,5,3,'11 days 00:39:56.418',1,NULL,NULL,NULL,false,'Badge Mooring Pro',current_setting('vessel.id', false)),
(6,'Badge Anchormaster',NULL,5,2,'26 days 00:49:56.418',1,NULL,NULL,NULL,false,'Badge Anchormaster',current_setting('vessel.id', false));
\echo 'Set config'
SELECT set_config('user.email', 'demo+aava@openplotter.cloud', false);
--SELECT set_config('vessel.client_id', 'vessels.urn:mrn:imo:mmsi:787654321', false);
SELECT v.vessel_id as "vessel_id" FROM auth.vessels v WHERE v.owner_email = 'demo+aava@openplotter.cloud' \gset
--\echo :"vessel_id"
SELECT set_config('vessel.id', :'vessel_id', false) IS NOT NULL as vessel_id;
\echo 'Process badge'
SELECT badges_moorages_fn();
\echo 'Check details from vessel_id aava'
--SELECT get_user_settings_from_vesselid_fn('vessels.urn:mrn:imo:mmsi:787654321'::TEXT);
SELECT
json_build_object(
'boat', v.name,
'recipient', a.first,
'email', v.owner_email,
--'settings', a.preferences,
'pushover_key', a.preferences->'pushover_key'
--'badges', a.preferences->'badges'
) as user_settings
FROM auth.accounts a, auth.vessels v, api.metadata m
WHERE m.vessel_id = v.vessel_id
AND m.vessel_id = current_setting('vessel.id', false)
AND lower(a.email) = current_setting('user.email', false);

View File

@@ -0,0 +1,82 @@
current_database
------------------
signalk
(1 row)
You are now connected to database "signalk" as user "username".
Expanded display is on.
-[ RECORD 1 ]
vessel_id | t
Insert new api.logbook for badges
INSERT 0 2
Set config
-[ RECORD 1 ]----------------------------
set_config | demo+kapla@openplotter.cloud
Process badge
-[ RECORD 1 ]-----+-
badges_logbook_fn |
-[ RECORD 1 ]-----+-
badges_logbook_fn |
-[ RECORD 1 ]--+-
badges_geom_fn |
-[ RECORD 1 ]--+-
badges_geom_fn |
Check badges for user
-[ RECORD 1 ]-----+------------------
jsonb_object_keys | Helmsman
-[ RECORD 2 ]-----+------------------
jsonb_object_keys | Wake Maker
-[ RECORD 3 ]-----+------------------
jsonb_object_keys | Balearic Sea
-[ RECORD 4 ]-----+------------------
jsonb_object_keys | Stormtrooper
-[ RECORD 5 ]-----+------------------
jsonb_object_keys | Gulf of Finland
-[ RECORD 6 ]-----+------------------
jsonb_object_keys | Helmsman
-[ RECORD 7 ]-----+------------------
jsonb_object_keys | Wake Maker
-[ RECORD 8 ]-----+------------------
jsonb_object_keys | Club Alaska
-[ RECORD 9 ]-----+------------------
jsonb_object_keys | Stormtrooper
-[ RECORD 10 ]----+------------------
jsonb_object_keys | Captain Award
-[ RECORD 11 ]----+------------------
jsonb_object_keys | Caribbean Sea
-[ RECORD 12 ]----+------------------
jsonb_object_keys | Gulf of Alaska
-[ RECORD 13 ]----+------------------
jsonb_object_keys | Gulf of Finland
-[ RECORD 14 ]----+------------------
jsonb_object_keys | Navigator Award
-[ RECORD 15 ]----+------------------
jsonb_object_keys | Tropical Traveler
Check details from vessel_id kapla
-[ RECORD 1 ]-+-----------------------------------------------------------------------------------------------------------------
user_settings | {"boat" : "kapla", "recipient" : "First_kapla", "email" : "demo+kapla@openplotter.cloud", "pushover_key" : null}
Insert new api.moorages for badges
INSERT 0 2
Set config
-[ RECORD 1 ]---------------------------
set_config | demo+aava@openplotter.cloud
-[ RECORD 1 ]
vessel_id | t
Process badge
-[ RECORD 1 ]------+-
badges_moorages_fn |
Check details from vessel_id aava
-[ RECORD 1 ]-+--------------------------------------------------------------------------------------------------------------
user_settings | {"boat" : "aava", "recipient" : "first_aava", "email" : "demo+aava@openplotter.cloud", "pushover_key" : null}

View File

@@ -0,0 +1,43 @@
---------------------------------------------------------------------------
-- Listing
--
-- List current database
select current_database();
-- connect to the DB
\c signalk
-- output display format
\x on
-- set user_id
SELECT a.user_id as "user_id" FROM auth.accounts a WHERE a.email = 'demo+kapla@openplotter.cloud' \gset
--\echo :"user_id"
SELECT set_config('user.id', :'user_id', false) IS NOT NULL as user_id;
-- set vessel_id
SELECT v.vessel_id as "vessel_id" FROM auth.vessels v WHERE v.owner_email = 'demo+kapla@openplotter.cloud' \gset
--\echo :"vessel_id"
SELECT set_config('vessel.id', :'vessel_id', false) IS NOT NULL as vessel_id;
-- Test logbook for user
\echo 'logbook'
SELECT count(*) FROM api.logbook WHERE vessel_id = current_setting('vessel.id', false);
\echo 'logbook'
SELECT name,_from_time IS NOT NULL AS _from_time,_to_time IS NOT NULL AS _to_time, track_geojson IS NOT NULL AS track_geojson, track_gpx IS NOT NULL AS track_gpx, track_geom, distance,duration,avg_speed,max_speed,max_wind_speed,notes,extra FROM api.logbook WHERE vessel_id = current_setting('vessel.id', false);
-- Test stays for user
\echo 'stays'
SELECT count(*) FROM api.stays WHERE vessel_id = current_setting('vessel.id', false);
\echo 'stays'
SELECT active,name,geog,stay_code FROM api.stays WHERE vessel_id = current_setting('vessel.id', false);
-- Test event logs view for user
\echo 'eventlogs_view'
select count(*) from api.eventlogs_view;
-- Test event logs view for user
\echo 'stats_logs_fn'
select api.stats_logs_fn(null, null);
select api.stats_logs_fn('2022-01-01'::text,'2022-06-12'::text);

View File

@@ -0,0 +1,79 @@
current_database
------------------
signalk
(1 row)
You are now connected to database "signalk" as user "username".
Expanded display is on.
-[ RECORD 1 ]
user_id | t
-[ RECORD 1 ]
vessel_id | t
logbook
-[ RECORD 1 ]
count | 2
logbook
-[ RECORD 1 ]--+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | Bollsta to Strandallén
_from_time | t
_to_time | t
track_geojson | t
track_gpx | t
track_geom | 0102000020E61000001A00000020D26F5F0786374030BB270F0B094E400C6E7ED60F843740AA60545227084E40D60FC48C03823740593CE27D42074E407B39D9F322803740984C158C4A064E4091ED7C3F357E3740898BB63D54054E40A8A1208B477C37404BA3DC9059044E404C5CB4EDA17A3740C4F856115B034E40A9A44E4013793740D8F0F44A59024E40E4839ECDAA773740211FF46C56014E405408D147067637408229F03B73004E40787AA52C43743740F90FE9B7AFFF4D40F8098D4D18723740C217265305FF4D4084E82303537037409A2D464AA0FE4D4022474DCE636F37402912396A72FE4D408351499D806E374088CFB02B40FE4D4076711B0DE06D3740B356C7040FFE4D404EAC66B0BC6E374058A835CD3BFE4D40D7A3703D0A6F3740D3E10EC15EFE4D4087602F277B6E3740A779C7293AFE4D4087602F277B6E3740A779C7293AFE4D402063EE5A426E3740B5A679C729FE4D40381DEE10EC6D37409ECA7C1A0AFE4D40E2C46A06CB6B37400A43F7BF36FD4D4075931804566E3740320BDAD125FD4D409A2D464AA06E37404A5658830AFD4D40029A081B9E6E37404A5658830AFD4D40
distance | 7.17
duration | 00:25:00
avg_speed | 3.6961538461538455
max_speed | 6.1
max_wind_speed | 22.1
notes | new log note
extra | {"metrics": {"propulsion.main.runTime": 10}, "observations": {"seaState": -1, "visibility": -1, "cloudCoverage": -1}}
-[ RECORD 2 ]--+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | Knipan to Ekenäs
_from_time | t
_to_time | t
track_geojson | t
track_gpx | t
track_geom | 0102000020E6100000130000004806A6C0EF6C3740DA1B7C6132FD4D40FE65F7E461693740226C787AA5FC4D407DD3E10EC1663740B29DEFA7C6FB4D40898BB63D5465374068479724BCFA4D409A5271F6E1633740B6847CD0B3F94D40431CEBE236623740E9263108ACF84D402C6519E2585F37407E678EBFC7F74D4096218E75715B374027C5B45C23F74D402AA913D044583740968DE1C46AF64D405AF5B9DA8A5537407BEF829B9FF54D407449C2ABD253374086C954C1A8F44D407D1A0AB278543740F2B0506B9AF34D409D11A5BDC15737406688635DDCF24D4061C3D32B655937402CAF6F3ADCF14D408988888888583740B3319C58CDF04D4021FAC8C0145837408C94405DB7EF4D40B8F9593F105B37403DC0804BEDEE4D40DE4C5FE2A25D3740AE47E17A14EE4D40DE4C5FE2A25D3740AE47E17A14EE4D40
distance | 8.6862
duration | 00:18:00
avg_speed | 6.026315789473684
max_speed | 6.5
max_wind_speed | 37.2
notes |
extra | {"metrics": {"propulsion.main.runTime": 11}, "observations": {"seaState": -1, "visibility": -1, "cloudCoverage": -1}}
stays
-[ RECORD 1 ]
count | 3
stays
-[ RECORD 1 ]-------------------------------------------------
active | f
name | Bollsta
geog | 0101000020E6100000B0DEBBE0E68737404DA938FBF0094E40
stay_code | 2
-[ RECORD 2 ]-------------------------------------------------
active | f
name | Strandallén
geog | 0101000020E6100000029A081B9E6E37404A5658830AFD4D40
stay_code | 1
-[ RECORD 3 ]-------------------------------------------------
active | t
name | Ekenäs
geog | 0101000020E6100000DE4C5FE2A25D3740AE47E17A14EE4D40
stay_code | 2
eventlogs_view
-[ RECORD 1 ]
count | 13
stats_logs_fn
-[ RECORD 1 ]-+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
stats_logs_fn | {"count": 4, "max_speed": 7.1, "max_distance": 8.6862, "max_duration": "01:11:00", "max_speed_id": 3, "sum_duration": "02:37:00", "max_wind_speed": 44.2, "max_distance_id": 2, "max_wind_speed_id": 4}
-[ RECORD 1 ]-+-
stats_logs_fn |

View File

@@ -0,0 +1,20 @@
---------------------------------------------------------------------------
-- Listing
--
-- List current database
select current_database();
-- connect to the DB
\c signalk
-- output display format
\x on
-- Check the number of process pending
-- Should be 22
SELECT count(*) as jobs from public.process_queue pq where pq.processed is null;
--set role scheduler
SELECT public.run_cron_jobs();
-- Check any pending job
SELECT count(*) as any_pending_jobs from public.process_queue pq where pq.processed is null;

View File

@@ -0,0 +1,16 @@
current_database
------------------
signalk
(1 row)
You are now connected to database "signalk" as user "username".
Expanded display is on.
-[ RECORD 1 ]
jobs | 28
-[ RECORD 1 ]-+-
run_cron_jobs |
-[ RECORD 1 ]----+--
any_pending_jobs | 0

79
tests/sql/grafana.sql Normal file
View File

@@ -0,0 +1,79 @@
---------------------------------------------------------------------------
-- Listing
--
-- List current database
select current_database();
-- connect to the DB
\c signalk
-- output display format
\x on
--
-- grafana_auth
SET ROLE grafana_auth;
\echo 'ROLE grafana_auth current_setting'
SELECT current_user, current_setting('user.email', true), current_setting('vessel.client_id', true), current_setting('vessel.id', true);
--SELECT a.pass,v.name,m.client_id FROM auth.accounts a JOIN auth.vessels v ON a.email = 'demo+kapla@openplotter.cloud' AND a.role = 'user_role' AND cast(a.preferences->>'email_valid' as Boolean) = True AND v.owner_email = a.email JOIN api.metadata m ON m.vessel_id = v.vessel_id;
--SELECT a.pass,v.name,m.client_id FROM auth.accounts a JOIN auth.vessels v ON a.email = 'demo+kapla@openplotter.cloud' AND a.role = 'user_role' AND v.owner_email = a.email JOIN api.metadata m ON m.vessel_id = v.vessel_id;
\echo 'link vessel and user based on current_setting'
SELECT v.name,m.client_id FROM auth.accounts a JOIN auth.vessels v ON a.role = 'user_role' AND v.owner_email = a.email JOIN api.metadata m ON m.vessel_id = v.vessel_id;
\echo 'auth.accounts details'
SELECT a.userid IS NOT NULL AS userid, a.user_id IS NOT NULL AS user_id, a.email, a.first, a.last, a.pass IS NOT NULL AS pass, a.role, a.preferences->'telegram'->'chat' AS telegram, a.preferences->'pushover_user_key' AS pushover_user_key FROM auth.accounts AS a;
\echo 'auth.vessels details'
--SELECT 'SELECT ' || STRING_AGG('v.' || column_name, ', ') || ' FROM auth.vessels AS v' FROM information_schema.columns WHERE table_name = 'vessels' AND table_schema = 'auth' AND column_name NOT IN ('created_at', 'updated_at');
SELECT v.vessel_id IS NOT NULL AS vessel_id, v.owner_email, v.mmsi, v.name, v.role FROM auth.vessels AS v;
\echo 'api.metadata details'
--
SELECT m.id, m.name, m.mmsi, m.client_id, m.length, m.beam, m.height, m.ship_type, m.plugin_version, m.signalk_version, m.time IS NOT NULL AS time, m.active FROM api.metadata AS m;
--
-- grafana
SET ROLE grafana;
\echo 'ROLE grafana current_setting'
\echo 'Set current_setting value'
SET "user.email" = 'demo+kapla@openplotter.cloud';
--SET vessel.client_id = 'vessels.urn:mrn:imo:mmsi:123456789';
--select v.vessel_id FROM auth.vessels v WHERE v.owner_email = 'demo+kapla@openplotter.cloud';
SELECT v.vessel_id as "vessel_id" FROM auth.vessels v WHERE v.owner_email = 'demo+kapla@openplotter.cloud' \gset
--\echo :"vessel_id"
SELECT set_config('vessel.id', :'vessel_id', false) IS NOT NULL as vessel_id;
--SELECT current_user, current_setting('user.email', true), current_setting('vessel.client_id', true), current_setting('vessel.id', true);
SELECT current_user, current_setting('user.email', true), current_setting('vessel.client_id', true);
SELECT v.name AS __text, m.client_id AS __value FROM auth.vessels v JOIN api.metadata m ON v.owner_email = 'demo+kapla@openplotter.cloud' and m.vessel_id = v.vessel_id;
\echo 'auth.vessels details'
--SELECT * FROM auth.vessels v;
SELECT v.vessel_id IS NOT NULL AS vessel_id, v.owner_email, v.mmsi, v.name, v.role FROM auth.vessels AS v;
--SELECT * FROM api.metadata m;
\echo 'api.metadata details'
SELECT m.id, m.name, m.mmsi, m.client_id, m.length, m.beam, m.height, m.ship_type, m.plugin_version, m.signalk_version, m.time IS NOT NULL AS time, m.active FROM api.metadata AS m;
\echo 'api.logs_view'
--SELECT * FROM api.logbook l;
--SELECT * FROM api.logs_view l;
SELECT l.id, "Name", "From", "To", "Distance", "Duration" FROM api.logs_view AS l;
--SELECT * FROM api.log_view l;
\echo 'api.stays'
--SELECT * FROM api.stays s;
SELECT m.id, m.vessel_id IS NOT NULL AS vessel_id, m.active, m.name, m.latitude, m.longitude, m.geog, m.arrived IS NOT NULL AS arrived, m.departed IS NOT NULL AS departed, m.duration, m.stay_code, m.notes FROM api.stays AS m;
\echo 'stays_view'
--SELECT * FROM api.stays_view s;
SELECT m.id, m.name IS NOT NULL AS name, m.moorage, m.moorage_id, m.duration, m.stayed_at, m.stayed_at_id, m.arrived IS NOT NULL AS arrived, m.departed IS NOT NULL AS departed, m.notes FROM api.stays_view AS m;
\echo 'api.moorages'
--SELECT * FROM api.moorages m;
SELECT m.id, m.vessel_id IS NOT NULL AS vessel_id, m.name, m.country, m.stay_id, m.stay_code, m.stay_duration, m.reference_count, m.latitude, m.longitude, m.geog, m.home_flag, m.notes FROM api.moorages AS m;
\echo 'api.moorages_view'
SELECT * FROM api.moorages_view s;

View File

@@ -0,0 +1,253 @@
current_database
------------------
signalk
(1 row)
You are now connected to database "signalk" as user "username".
Expanded display is on.
SET
ROLE grafana_auth current_setting
-[ RECORD 1 ]---+-------------
current_user | grafana_auth
current_setting |
current_setting |
current_setting |
link vessel and user based on current_setting
-[ RECORD 1 ]----------------------------------------------------------------
name | kapla
client_id | vessels.urn:mrn:signalk:uuid:5b4f7543-7153-4840-b139-761310b242fd
-[ RECORD 2 ]----------------------------------------------------------------
name | aava
client_id | vessels.urn:mrn:imo:mmsi:787654321
auth.accounts details
-[ RECORD 1 ]-----+-----------------------------
userid | t
user_id | t
email | demo+kapla@openplotter.cloud
first | First_kapla
last | Last_kapla
pass | t
role | user_role
telegram |
pushover_user_key |
-[ RECORD 2 ]-----+-----------------------------
userid | t
user_id | t
email | demo+aava@openplotter.cloud
first | first_aava
last | last_aava
pass | t
role | user_role
telegram |
pushover_user_key |
auth.vessels details
-[ RECORD 1 ]-----------------------------
vessel_id | t
owner_email | demo+kapla@openplotter.cloud
mmsi |
name | kapla
role | vessel_role
-[ RECORD 2 ]-----------------------------
vessel_id | t
owner_email | demo+aava@openplotter.cloud
mmsi | 787654321
name | aava
role | vessel_role
api.metadata details
-[ RECORD 1 ]---+------------------------------------------------------------------
id | 1
name | kapla
mmsi | 123456789
client_id | vessels.urn:mrn:signalk:uuid:5b4f7543-7153-4840-b139-761310b242fd
length | 12
beam | 10
height | 24
ship_type | 36
plugin_version | 0.0.1
signalk_version | signalk_version
time | t
active | t
-[ RECORD 2 ]---+------------------------------------------------------------------
id | 2
name | aava
mmsi | 787654321
client_id | vessels.urn:mrn:imo:mmsi:787654321
length | 12
beam | 10
height | 24
ship_type | 37
plugin_version | 1.0.2
signalk_version | 1.20.0
time | t
active | t
SET
ROLE grafana current_setting
Set current_setting value
SET
-[ RECORD 1 ]
vessel_id | t
-[ RECORD 1 ]---+-----------------------------
current_user | grafana
current_setting | demo+kapla@openplotter.cloud
current_setting |
-[ RECORD 1 ]--------------------------------------------------------------
__text | kapla
__value | vessels.urn:mrn:signalk:uuid:5b4f7543-7153-4840-b139-761310b242fd
auth.vessels details
-[ RECORD 1 ]-----------------------------
vessel_id | t
owner_email | demo+kapla@openplotter.cloud
mmsi |
name | kapla
role | vessel_role
api.metadata details
-[ RECORD 1 ]---+------------------------------------------------------------------
id | 1
name | kapla
mmsi | 123456789
client_id | vessels.urn:mrn:signalk:uuid:5b4f7543-7153-4840-b139-761310b242fd
length | 12
beam | 10
height | 24
ship_type | 36
plugin_version | 0.0.1
signalk_version | signalk_version
time | t
active | t
api.logs_view
-[ RECORD 1 ]--------------
id | 2
Name | Knipan to Ekenäs
From | Knipan
To | Ekenäs
Distance | 8.6862
Duration | 00:18:00
-[ RECORD 2 ]--------------
id | 1
Name | patch log name 3
From | Bollsta
To | Strandallén
Distance | 7.17
Duration | 00:25:00
api.stays
-[ RECORD 1 ]-------------------------------------------------
id | 1
vessel_id | t
active | f
name | patch stay name 3
latitude | 60.077666666666666
longitude | 23.530866666666668
geog | 0101000020E6100000B0DEBBE0E68737404DA938FBF0094E40
arrived | t
departed | t
duration |
stay_code | 2
notes | new stay note 3
-[ RECORD 2 ]-------------------------------------------------
id | 2
vessel_id | t
active | f
name | Strandallén
latitude | 59.97688333333333
longitude | 23.4321
geog | 0101000020E6100000029A081B9E6E37404A5658830AFD4D40
arrived | t
departed | t
duration |
stay_code | 1
notes |
-[ RECORD 3 ]-------------------------------------------------
id | 3
vessel_id | t
active | t
name | Ekenäs
latitude | 59.86
longitude | 23.365766666666666
geog | 0101000020E6100000DE4C5FE2A25D3740AE47E17A14EE4D40
arrived | t
departed | f
duration |
stay_code | 2
notes |
stays_view
-[ RECORD 1 ]+------------------
id | 2
name | t
moorage | Strandallén
moorage_id | 2
duration | 00:03:00
stayed_at | Unknow
stayed_at_id | 1
arrived | t
departed | t
notes |
-[ RECORD 2 ]+------------------
id | 1
name | t
moorage | patch stay name 3
moorage_id | 1
duration | 00:02:00
stayed_at | Anchor
stayed_at_id | 2
arrived | t
departed | t
notes | new stay note 3
api.moorages
-[ RECORD 1 ]---+---------------------------------------------------
id | 1
vessel_id | t
name | patch moorage name 3
country |
stay_id | 1
stay_code | 2
stay_duration | 00:02:00
reference_count | 1
latitude | 60.077666666666666
longitude | 23.530866666666668
geog | 0101000020E6100000B0DEBBE0E68737404DA938FBF0094E40
home_flag | t
notes | new moorage note 3
-[ RECORD 2 ]---+---------------------------------------------------
id | 2
vessel_id | t
name | Strandallén
country |
stay_id | 2
stay_code | 1
stay_duration | 00:03:00
reference_count | 1
latitude | 59.97688333333333
longitude | 23.4321
geog | 0101000020E6100000029A081B9E6E37404A5658830AFD4D40
home_flag | f
notes |
api.moorages_view
-[ RECORD 1 ]-------+---------------------
id | 1
moorage | patch moorage name 3
default_stay | Anchor
default_stay_id | 2
total_stay | 0
arrivals_departures | 1
-[ RECORD 2 ]-------+---------------------
id | 2
moorage | Strandallén
default_stay | Unknow
default_stay_id | 1
total_stay | 0
arrivals_departures | 1

53
tests/sql/monitoring.sql Normal file
View File

@@ -0,0 +1,53 @@
---------------------------------------------------------------------------
-- Listing
--
-- List current database
select current_database();
-- connect to the DB
\c signalk
-- output display format
\x on
\echo 'Set vessel_id and vessel.name'
-- set vessel_id
SELECT v.vessel_id as "vessel_id" FROM auth.vessels v WHERE v.owner_email = 'demo+kapla@openplotter.cloud' \gset
--\echo :"vessel_id"
SELECT set_config('vessel.id', :'vessel_id', false) IS NOT NULL as vessel_id;
-- set name
SELECT v.name as "name" FROM auth.vessels v WHERE v.owner_email = 'demo+kapla@openplotter.cloud' \gset
--\echo :"vessel_id"
SELECT set_config('vessel.name', :'name', false) IS NOT NULL as name;
\echo 'Test monitoring_view for user'
-- Test monitoring for user
--select * from api.monitoring_view;
select count(*) from api.monitoring_view;
\echo 'Test monitoring_view2 for user'
-- Test monitoring for user
--select * from api.monitoring_view2;
select count(*) from api.monitoring_view2;
\echo 'Test monitoring_view3 for user'
-- Test monitoring for user
--select * from api.monitoring_view3;
select count(*) from api.monitoring_view3;
\echo 'Test monitoring_voltage for user'
-- Test monitoring for user
--select * from api.monitoring_voltage;
select count(*) from api.monitoring_voltage;
\echo 'Test monitoring_temperatures for user'
-- Test monitoring for user
--select * from api.monitoring_temperatures;
select count(*) from api.monitoring_temperatures;
\echo 'Test monitoring_humidity for user'
-- Test monitoring for user
--select * from api.monitoring_humidity;
select count(*) from api.monitoring_humidity;

View File

@@ -0,0 +1,38 @@
current_database
------------------
signalk
(1 row)
You are now connected to database "signalk" as user "username".
Expanded display is on.
Set vessel_id and vessel.name
-[ RECORD 1 ]
vessel_id | t
-[ RECORD 1 ]
name | t
Test monitoring_view for user
-[ RECORD 1 ]
count | 1
Test monitoring_view2 for user
-[ RECORD 1 ]
count | 21
Test monitoring_view3 for user
-[ RECORD 1 ]
count | 3682
Test monitoring_voltage for user
-[ RECORD 1 ]
count | 46
Test monitoring_temperatures for user
-[ RECORD 1 ]
count | 119
Test monitoring_humidity for user
-[ RECORD 1 ]
count | 0

26
tests/sql/otp.sql Normal file
View File

@@ -0,0 +1,26 @@
---------------------------------------------------------------------------
-- Listing
--
-- List current database
select current_database();
-- connect to the DB
\c signalk
-- output display format
\x on
--
--
\echo 'Count auth.accounts'
SELECT count(*) from auth.accounts;
\echo 'Settings auth.accounts'
SELECT preferences->'email_notifications' as email_notifications from auth.accounts;
SELECT preferences->'phone_notifications' as phone_notifications from auth.accounts;
SELECT preferences->'telegram'->'chat'->'id' as telegram from auth.accounts;
--SELECT preferences->'telegram'->'date' - INTERVAL 5 minutes from auth.accounts;
SELECT count(*)
FROM auth.accounts
WHERE preferences->'telegram'->'chat'->'id' is null;

30
tests/sql/otp.sql.output Normal file
View File

@@ -0,0 +1,30 @@
current_database
------------------
signalk
(1 row)
You are now connected to database "signalk" as user "username".
Expanded display is on.
Count auth.accounts
-[ RECORD 1 ]
count | 2
Settings auth.accounts
-[ RECORD 1 ]-------+------
email_notifications | false
-[ RECORD 2 ]-------+------
email_notifications | false
-[ RECORD 1 ]-------+------
phone_notifications | false
-[ RECORD 2 ]-------+------
phone_notifications | false
-[ RECORD 1 ]--------
telegram | 1234567890
-[ RECORD 2 ]--------
telegram | 9876543210
-[ RECORD 1 ]
count | 0

90
tests/sql/summary.sql Normal file
View File

@@ -0,0 +1,90 @@
---------------------------------------------------------------------------
-- Listing
--
-- List current database
select current_database();
-- connect to the DB
\c signalk
-- output display format
\x on
-- List PostgreSQL version
--SELECT version();
-- check only version number to remove arch details
SHOW server_version;
-- List Postgis version
SELECT postgis_full_version();
-- List of installed extensions
-- \dx
--SELECT extname,extversion FROM pg_extension;
SELECT e.extname AS "Name", e.extversion AS "Version", n.nspname AS "Schema", c.description AS "Description"
FROM pg_catalog.pg_extension e
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass
ORDER BY 1;
-- List of installed extensions available for upgrade
SELECT name, default_version, installed_version FROM pg_available_extensions where default_version <> installed_version;
-- List Language
\echo 'List Language'
SELECT * FROM pg_language;
-- List of databases
-- ICU Missing entry in some system?
--\l
SELECT datname,datconnlimit,datcollate,datctype,datallowconn FROM pg_database;
-- List of relations
\echo 'List of relations'
\dtables
-- List tables from schema api
select t.table_name as schema_api
from information_schema.tables t
where t.table_schema = 'api'
and t.table_type = 'BASE TABLE'
order by t.table_name;
-- List tables from schema public
select t.table_name as schema_public
from information_schema.tables t
where t.table_schema = 'public'
and t.table_type = 'BASE TABLE'
order by t.table_name;
-- List tables from schema auth
select t.table_name as schema_auth
from information_schema.tables t
where t.table_schema = 'auth'
and t.table_type = 'BASE TABLE'
order by t.table_name;
-- List tables from schema jwt
select t.table_name as schema_jwt
from information_schema.tables t
where t.table_schema = 'jwt'
and t.table_type = 'BASE TABLE'
order by t.table_name;
-- List Row Security Policies - todo reduce and improve output
\echo 'List Row Security Policies'
select * from pg_policies;
-- Test functions
\echo 'Test nominatim reverse_geocode_py_fn'
SELECT public.reverse_geocode_py_fn('nominatim', 1.4440116666666667, 38.82985166666667);
\echo 'Test geoip reverse_geoip_py_fn'
--SELECT reverse_geoip_py_fn('62.74.13.231');
-- List details product versions
SELECT api.versions_fn();
SELECT * FROM api.versions_view;
-- List application settings
--SELECT * IS NOT NULl FROM public.app_settings;

View File

@@ -0,0 +1,608 @@
current_database
------------------
signalk
(1 row)
You are now connected to database "signalk" as user "username".
Expanded display is on.
-[ RECORD 1 ]--+-------------------------------
server_version | 15.4 (Debian 15.4-1.pgdg110+1)
-[ RECORD 1 ]--------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
postgis_full_version | POSTGIS="3.4.0 0874ea3" [EXTENSION] PGSQL="150" GEOS="3.9.0-CAPI-1.16.2" PROJ="7.2.1 NETWORK_ENABLED=OFF URL_ENDPOINT=https://cdn.proj.org USER_WRITABLE_DIRECTORY=/var/lib/postgresql/.local/share/proj DATABASE_PATH=/usr/share/proj/proj.db" LIBXML="2.9.10" LIBJSON="0.15" LIBPROTOBUF="1.3.3" WAGYU="0.5.0 (Internal)"
-[ RECORD 1 ]--------------------------------------------------------------------------------------
Name | citext
Version | 1.6
Schema | public
Description | data type for case-insensitive character strings
-[ RECORD 2 ]--------------------------------------------------------------------------------------
Name | jsonb_plpython3u
Version | 1.0
Schema | public
Description | transform between jsonb and plpython3u
-[ RECORD 3 ]--------------------------------------------------------------------------------------
Name | moddatetime
Version | 1.0
Schema | public
Description | functions for tracking last modification time
-[ RECORD 4 ]--------------------------------------------------------------------------------------
Name | pg_stat_statements
Version | 1.10
Schema | public
Description | track planning and execution statistics of all SQL statements executed
-[ RECORD 5 ]--------------------------------------------------------------------------------------
Name | pgcrypto
Version | 1.3
Schema | public
Description | cryptographic functions
-[ RECORD 6 ]--------------------------------------------------------------------------------------
Name | plpgsql
Version | 1.0
Schema | pg_catalog
Description | PL/pgSQL procedural language
-[ RECORD 7 ]--------------------------------------------------------------------------------------
Name | plpython3u
Version | 1.0
Schema | pg_catalog
Description | PL/Python3U untrusted procedural language
-[ RECORD 8 ]--------------------------------------------------------------------------------------
Name | postgis
Version | 3.4.0
Schema | public
Description | PostGIS geometry and geography spatial types and functions
-[ RECORD 9 ]--------------------------------------------------------------------------------------
Name | timescaledb
Version | 2.11.2
Schema | public
Description | Enables scalable inserts and complex queries for time-series data (Community Edition)
-[ RECORD 10 ]-------------------------------------------------------------------------------------
Name | uuid-ossp
Version | 1.1
Schema | public
Description | generate universally unique identifiers (UUIDs)
(0 rows)
List Language
-[ RECORD 1 ]-+-----------
oid | 12
lanname | internal
lanowner | 10
lanispl | f
lanpltrusted | f
lanplcallfoid | 0
laninline | 0
lanvalidator | 2246
lanacl |
-[ RECORD 2 ]-+-----------
oid | 13
lanname | c
lanowner | 10
lanispl | f
lanpltrusted | f
lanplcallfoid | 0
laninline | 0
lanvalidator | 2247
lanacl |
-[ RECORD 3 ]-+-----------
oid | 14
lanname | sql
lanowner | 10
lanispl | f
lanpltrusted | t
lanplcallfoid | 0
laninline | 0
lanvalidator | 2248
lanacl |
-[ RECORD 4 ]-+-----------
oid | 13542
lanname | plpgsql
lanowner | 10
lanispl | t
lanpltrusted | t
lanplcallfoid | 13539
laninline | 13540
lanvalidator | 13541
lanacl |
-[ RECORD 5 ]-+-----------
oid | 18174
lanname | plpython3u
lanowner | 10
lanispl | t
lanpltrusted | t
lanplcallfoid | 18171
laninline | 18172
lanvalidator | 18173
lanacl |
-[ RECORD 1 ]+-----------
datname | postgres
datconnlimit | -1
datcollate | en_US.utf8
datctype | en_US.utf8
datallowconn | t
-[ RECORD 2 ]+-----------
datname | template1
datconnlimit | -1
datcollate | en_US.utf8
datctype | en_US.utf8
datallowconn | t
-[ RECORD 3 ]+-----------
datname | template0
datconnlimit | -1
datcollate | en_US.utf8
datctype | en_US.utf8
datallowconn | f
-[ RECORD 4 ]+-----------
datname | signalk
datconnlimit | 100
datcollate | en_US.utf8
datctype | en_US.utf8
datallowconn | t
List of relations
List of relations
-[ RECORD 1 ]---------------------------------
Schema | public
Name | aistypes
Type | table
Owner | username
-[ RECORD 2 ]---------------------------------
Schema | public
Name | app_settings
Type | table
Owner | username
-[ RECORD 3 ]---------------------------------
Schema | public
Name | badges
Type | table
Owner | username
-[ RECORD 4 ]---------------------------------
Schema | public
Name | email_templates
Type | table
Owner | username
-[ RECORD 5 ]---------------------------------
Schema | public
Name | geocoders
Type | table
Owner | username
-[ RECORD 6 ]---------------------------------
Schema | public
Name | iso3166
Type | table
Owner | username
-[ RECORD 7 ]---------------------------------
Schema | public
Name | mid
Type | table
Owner | username
-[ RECORD 8 ]---------------------------------
Schema | public
Name | ne_10m_geography_marine_polys
Type | table
Owner | username
-[ RECORD 9 ]---------------------------------
Schema | public
Name | ne_10m_geography_marine_polys_gid_seq
Type | sequence
Owner | username
-[ RECORD 10 ]--------------------------------
Schema | public
Name | process_queue
Type | table
Owner | username
-[ RECORD 11 ]--------------------------------
Schema | public
Name | process_queue_id_seq
Type | sequence
Owner | username
-[ RECORD 12 ]--------------------------------
Schema | public
Name | spatial_ref_sys
Type | table
Owner | username
-[ RECORD 1 ]--------
schema_api | logbook
-[ RECORD 2 ]--------
schema_api | metadata
-[ RECORD 3 ]--------
schema_api | metrics
-[ RECORD 4 ]--------
schema_api | moorages
-[ RECORD 5 ]--------
schema_api | stays
-[ RECORD 6 ]--------
schema_api | stays_at
-[ RECORD 1 ]-+------------------------------
schema_public | aistypes
-[ RECORD 2 ]-+------------------------------
schema_public | app_settings
-[ RECORD 3 ]-+------------------------------
schema_public | badges
-[ RECORD 4 ]-+------------------------------
schema_public | email_templates
-[ RECORD 5 ]-+------------------------------
schema_public | geocoders
-[ RECORD 6 ]-+------------------------------
schema_public | iso3166
-[ RECORD 7 ]-+------------------------------
schema_public | mid
-[ RECORD 8 ]-+------------------------------
schema_public | ne_10m_geography_marine_polys
-[ RECORD 9 ]-+------------------------------
schema_public | process_queue
-[ RECORD 10 ]+------------------------------
schema_public | spatial_ref_sys
-[ RECORD 1 ]---------
schema_auth | accounts
-[ RECORD 2 ]---------
schema_auth | otp
-[ RECORD 3 ]---------
schema_auth | vessels
(0 rows)
List Row Security Policies
-[ RECORD 1 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metadata
policyname | admin_all
permissive | PERMISSIVE
roles | {username}
cmd | ALL
qual | true
with_check | true
-[ RECORD 2 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metadata
policyname | api_vessel_role
permissive | PERMISSIVE
roles | {vessel_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | true
-[ RECORD 3 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metadata
policyname | api_user_role
permissive | PERMISSIVE
roles | {user_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, true))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 4 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metadata
policyname | api_scheduler_role
permissive | PERMISSIVE
roles | {scheduler}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 5 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metadata
policyname | grafana_role
permissive | PERMISSIVE
roles | {grafana}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | false
-[ RECORD 6 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metadata
policyname | grafana_proxy_role
permissive | PERMISSIVE
roles | {grafana_auth}
cmd | ALL
qual | true
with_check | false
-[ RECORD 7 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metrics
policyname | admin_all
permissive | PERMISSIVE
roles | {username}
cmd | ALL
qual | true
with_check | true
-[ RECORD 8 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metrics
policyname | api_vessel_role
permissive | PERMISSIVE
roles | {vessel_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | true
-[ RECORD 9 ]------------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | moorages
policyname | admin_all
permissive | PERMISSIVE
roles | {username}
cmd | ALL
qual | true
with_check | true
-[ RECORD 10 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metrics
policyname | api_user_role
permissive | PERMISSIVE
roles | {user_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, true))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 11 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metrics
policyname | api_scheduler_role
permissive | PERMISSIVE
roles | {scheduler}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 12 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | metrics
policyname | grafana_role
permissive | PERMISSIVE
roles | {grafana}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | false
-[ RECORD 13 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | logbook
policyname | admin_all
permissive | PERMISSIVE
roles | {username}
cmd | ALL
qual | true
with_check | true
-[ RECORD 14 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | logbook
policyname | api_vessel_role
permissive | PERMISSIVE
roles | {vessel_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | true
-[ RECORD 15 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | logbook
policyname | api_user_role
permissive | PERMISSIVE
roles | {user_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, true))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 16 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | auth
tablename | vessels
policyname | grafana_proxy_role
permissive | PERMISSIVE
roles | {grafana_auth}
cmd | ALL
qual | true
with_check | false
-[ RECORD 17 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | auth
tablename | accounts
policyname | admin_all
permissive | PERMISSIVE
roles | {username}
cmd | ALL
qual | true
with_check | true
-[ RECORD 18 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | logbook
policyname | api_scheduler_role
permissive | PERMISSIVE
roles | {scheduler}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 19 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | logbook
policyname | grafana_role
permissive | PERMISSIVE
roles | {grafana}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | false
-[ RECORD 20 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | stays
policyname | admin_all
permissive | PERMISSIVE
roles | {username}
cmd | ALL
qual | true
with_check | true
-[ RECORD 21 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | stays
policyname | api_vessel_role
permissive | PERMISSIVE
roles | {vessel_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | true
-[ RECORD 22 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | stays
policyname | api_user_role
permissive | PERMISSIVE
roles | {user_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, true))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 23 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | stays
policyname | api_scheduler_role
permissive | PERMISSIVE
roles | {scheduler}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 24 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | stays
policyname | grafana_role
permissive | PERMISSIVE
roles | {grafana}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | false
-[ RECORD 25 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | moorages
policyname | api_vessel_role
permissive | PERMISSIVE
roles | {vessel_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | true
-[ RECORD 26 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | moorages
policyname | api_user_role
permissive | PERMISSIVE
roles | {user_role}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, true))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 27 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | moorages
policyname | api_scheduler_role
permissive | PERMISSIVE
roles | {scheduler}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | (vessel_id = current_setting('vessel.id'::text, false))
-[ RECORD 28 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | api
tablename | moorages
policyname | grafana_role
permissive | PERMISSIVE
roles | {grafana}
cmd | ALL
qual | (vessel_id = current_setting('vessel.id'::text, false))
with_check | false
-[ RECORD 29 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | auth
tablename | vessels
policyname | admin_all
permissive | PERMISSIVE
roles | {username}
cmd | ALL
qual | true
with_check | true
-[ RECORD 30 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | auth
tablename | vessels
policyname | api_user_role
permissive | PERMISSIVE
roles | {user_role}
cmd | ALL
qual | ((vessel_id = current_setting('vessel.id'::text, true)) AND ((owner_email)::text = current_setting('user.email'::text, true)))
with_check | ((vessel_id = current_setting('vessel.id'::text, true)) AND ((owner_email)::text = current_setting('user.email'::text, true)))
-[ RECORD 31 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | auth
tablename | vessels
policyname | grafana_role
permissive | PERMISSIVE
roles | {grafana}
cmd | ALL
qual | ((owner_email)::text = current_setting('user.email'::text, true))
with_check | false
-[ RECORD 32 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | auth
tablename | accounts
policyname | api_user_role
permissive | PERMISSIVE
roles | {user_role}
cmd | ALL
qual | ((email)::text = current_setting('user.email'::text, true))
with_check | ((email)::text = current_setting('user.email'::text, true))
-[ RECORD 33 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | auth
tablename | accounts
policyname | api_scheduler_role
permissive | PERMISSIVE
roles | {scheduler}
cmd | ALL
qual | ((email)::text = current_setting('user.email'::text, true))
with_check | ((email)::text = current_setting('user.email'::text, true))
-[ RECORD 34 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | auth
tablename | accounts
policyname | grafana_proxy_role
permissive | PERMISSIVE
roles | {grafana_auth}
cmd | ALL
qual | true
with_check | false
-[ RECORD 35 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | public
tablename | process_queue
policyname | admin_all
permissive | PERMISSIVE
roles | {username}
cmd | ALL
qual | true
with_check | true
-[ RECORD 36 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | public
tablename | process_queue
policyname | api_vessel_role
permissive | PERMISSIVE
roles | {vessel_role}
cmd | ALL
qual | ((ref_id = current_setting('user.id'::text, true)) OR (ref_id = current_setting('vessel.id'::text, true)))
with_check | true
-[ RECORD 37 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | public
tablename | process_queue
policyname | api_user_role
permissive | PERMISSIVE
roles | {user_role}
cmd | ALL
qual | ((ref_id = current_setting('user.id'::text, true)) OR (ref_id = current_setting('vessel.id'::text, true)))
with_check | ((ref_id = current_setting('user.id'::text, true)) OR (ref_id = current_setting('vessel.id'::text, true)))
-[ RECORD 38 ]-----------------------------------------------------------------------------------------------------------------------------
schemaname | public
tablename | process_queue
policyname | api_scheduler_role
permissive | PERMISSIVE
roles | {scheduler}
cmd | ALL
qual | true
with_check | false
Test nominatim reverse_geocode_py_fn
-[ RECORD 1 ]---------+-------
reverse_geocode_py_fn | España
Test geoip reverse_geoip_py_fn
-[ RECORD 1 ]----------------------------------------------------------------------------------------------------------------------------------------------
versions_fn | {"api_version" : "0.2.3", "sys_version" : "PostgreSQL 15.4", "timescaledb" : "2.11.2", "postgis" : "3.4.0", "postgrest" : "PostgREST 11.2.0"}
-[ RECORD 1 ]-----------------
api_version | 0.2.3
sys_version | PostgreSQL 15.4
timescaledb | 2.11.2
postgis | 3.4.0
postgrest | PostgREST 11.2.0

48
tests/sql/telegram.sql Normal file
View File

@@ -0,0 +1,48 @@
---------------------------------------------------------------------------
-- Listing
--
-- List current database
select current_database();
-- connect to the DB
\c signalk
-- output display format
\x on
--
-- telegram
SET ROLE username;
-- Does chat id session exist?
SELECT auth.telegram_session_exists_fn(1234567890);
SELECT auth.telegram_session_exists_fn(9876543210);
SELECT auth.telegram_session_exists_fn(1472583690);
-- Assign vessel_id var
SELECT v.vessel_id as "vessel_id_kapla" FROM auth.vessels v WHERE v.owner_email = 'demo+kapla@openplotter.cloud' \gset
SELECT v.vessel_id as "vessel_id_aava" FROM auth.vessels v WHERE v.owner_email = 'demo+aava@openplotter.cloud' \gset
SET ROLE api_anonymous;
SELECT api.telegram(1234567890::BIGINT) IS NOT NULL as telegram_session;
SELECT api.telegram(9876543210::BIGINT) IS NOT NULL as telegram_session;
SELECT api.telegram(1472583690::BIGINT) IS NULL as telegram_session;
SET ROLE user_role;
SET "user.email" = 'demo+kapla@openplotter.cloud';
--SET vessel.id = 'f94e995cf4d3';
SELECT set_config('vessel.id', :'vessel_id_kapla', false) IS NOT NULL as vessel_id;
SET vessel.name = 'kapla';
--SET vessel.client_id = 'vessels.urn:mrn:imo:mmsi:123456789';
--SELECT * FROM api.vessels_view v;
SELECT name, mmsi, created_at IS NOT NULL as created_at, last_contact IS NOT NULL as last_contact FROM api.vessels_view v;
SELECT name,geojson,watertemperature,insidetemperature,outsidetemperature FROM api.monitoring_view m;
SET "user.email" = 'demo+aava@openplotter.cloud';
SELECT set_config('vessel.id', :'vessel_id_aava', false) IS NOT NULL as vessel_id;
--SET vessel.id = '341dcfa30afb';
SET vessel.name = 'aava';
--SET vessel.client_id = 'vessels.urn:mrn:imo:mmsi:787654321';
--SELECT * FROM api.vessels_view v;
SELECT name, mmsi, created_at IS NOT NULL as created_at, last_contact IS NOT NULL as last_contact FROM api.vessels_view v;
SELECT name,geojson,watertemperature,insidetemperature,outsidetemperature FROM api.monitoring_view m;

View File

@@ -0,0 +1,64 @@
current_database
------------------
signalk
(1 row)
You are now connected to database "signalk" as user "username".
Expanded display is on.
SET
-[ RECORD 1 ]--------------+--
telegram_session_exists_fn | f
-[ RECORD 1 ]--------------+--
telegram_session_exists_fn | f
-[ RECORD 1 ]--------------+--
telegram_session_exists_fn | f
SET
-[ RECORD 1 ]----+--
telegram_session | f
-[ RECORD 1 ]----+--
telegram_session | f
-[ RECORD 1 ]----+--
telegram_session | t
SET
SET
-[ RECORD 1 ]
vessel_id | t
SET
-[ RECORD 1 ]+------
name | kapla
mmsi |
created_at | t
last_contact | t
-[ RECORD 1 ]------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | kapla
geojson | {"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.365766667, 59.86]}, "properties": {"name": "kapla", "latitude": 59.86, "longitude": 23.365766666666666}}
watertemperature |
insidetemperature |
outsidetemperature |
SET
-[ RECORD 1 ]
vessel_id | t
SET
-[ RECORD 1 ]+----------
name | aava
mmsi | 787654321
created_at | t
last_contact | t
-[ RECORD 1 ]------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
name | aava
geojson | {"type": "Feature", "geometry": {"type": "Point", "coordinates": [2.2934791, 41.465333283]}, "properties": {"name": "aava", "latitude": 41.46533328333334, "longitude": 2.2934791}}
watertemperature | 280.25
insidetemperature |
outsidetemperature |

143
tests/tests.sh Normal file
View File

@@ -0,0 +1,143 @@
# PostgSail Unit test
if [[ -z "${PGSAIL_DB_URI}" ]]; then
echo "PGSAIL_DB_URI is undefined"
exit 1
fi
if [[ -z "${PGSAIL_API_URI}" ]]; then
echo "PGSAIL_API_URI is undefined"
exit 1
fi
#npm install
npm install -g pnpm && pnpm install
# settings
export mymocha="./node_modules/mocha/bin/_mocha"
mkdir -p output/ && rm -rf output/*
$mymocha index.js --reporter ./node_modules/mochawesome --reporter-options reportDir=output/,reportFilename=report1.html
if [ $? -eq 0 ]; then
echo OK
else
echo mocha index.js
exit 1
fi
$mymocha index2.js --reporter ./node_modules/mochawesome --reporter-options reportDir=output/,reportFilename=report2.html
if [ $? -eq 0 ]; then
echo OK
else
echo mocha index2.js
exit 1
fi
# https://www.postgresql.org/docs/current/app-psql.html
# run cron jobs
#psql -U ${POSTGRES_USER} -h 172.30.0.1 signalk < sql/cron_run_jobs.sql > output/cron_run_jobs.sql.output
psql ${PGSAIL_DB_URI} < sql/cron_run_jobs.sql > output/cron_run_jobs.sql.output
diff sql/cron_run_jobs.sql.output output/cron_run_jobs.sql.output > /dev/null
#diff -u sql/cron_run_jobs.sql.output output/cron_run_jobs.sql.output | wc -l
#echo 0
if [ $? -eq 0 ]; then
echo OK
else
echo SQL cron_run_jobs.sql FAILED
diff -u sql/cron_run_jobs.sql.output output/cron_run_jobs.sql.output
exit 1
fi
# handle post processing
#psql -U ${POSTGRES_USER} -h 172.30.0.1 signalk < sql/cron_post_jobs.sql > output/cron_post_jobs.sql.output
psql ${PGSAIL_DB_URI} < sql/cron_post_jobs.sql > output/cron_post_jobs.sql.output
diff sql/cron_post_jobs.sql.output output/cron_post_jobs.sql.output > /dev/null
#diff -u sql/cron_post_jobs.sql.output output/cron_post_jobs.sql.output | wc -l
#echo 0
if [ $? -eq 0 ]; then
echo OK
else
echo SQL cron_post_jobs.sql FAILED
diff -u sql/cron_post_jobs.sql.output output/cron_post_jobs.sql.output
exit 1
fi
$mymocha index3.js --reporter ./node_modules/mochawesome --reporter-options reportDir=output/,reportFilename=report3.html
#echo 0
if [ $? -eq 0 ]; then
echo OK
else
echo mocha index3.js
exit 1
fi
# Grafana Auth Proxy and role unit tests
psql ${PGSAIL_DB_URI} < sql/grafana.sql > output/grafana.sql.output
diff sql/grafana.sql.output output/grafana.sql.output > /dev/null
#diff -u sql/grafana.sql.output output/grafana.sql.output | wc -l
#echo 0
if [ $? -eq 0 ]; then
echo OK
else
echo SQL grafana.sql FAILED
diff -u sql/grafana.sql.output output/grafana.sql.output
exit 1
fi
# Telegram and role unit tests
psql ${PGSAIL_DB_URI} < sql/telegram.sql > output/telegram.sql.output
diff sql/telegram.sql.output output/telegram.sql.output > /dev/null
#diff -u sql/telegram.sql.output output/telegram.sql.output | wc -l
#echo 0
if [ $? -eq 0 ]; then
echo OK
else
echo SQL telegram.sql FAILED
diff -u sql/telegram.sql.output output/telegram.sql.output
exit 1
fi
# Badges unit tests
psql ${PGSAIL_DB_URI} < sql/badges.sql > output/badges.sql.output
diff sql/badges.sql.output output/badges.sql.output > /dev/null
#diff -u sql/badges.sql.output output/badges.sql.output | wc -l
#echo 0
if [ $? -eq 0 ]; then
echo OK
else
echo SQL badges.sql FAILED
diff -u sql/badges.sql.output output/badges.sql.output
exit
fi
# Summary unit tests
psql ${PGSAIL_DB_URI} < sql/summary.sql > output/summary.sql.output
diff sql/summary.sql.output output/summary.sql.output > /dev/null
#diff -u sql/summary.sql.output output/summary.sql.output | wc -l
#echo 0
if [ $? -eq 0 ]; then
echo OK
else
echo SQL summary.sql FAILED
diff -u sql/summary.sql.output output/summary.sql.output
exit 1
fi
$mymocha index4.js --reporter ./node_modules/mochawesome --reporter-options reportDir=output/,reportFilename=report4.html
if [ $? -eq 0 ]; then
echo OK
else
echo mocha index4.js
exit 1
fi
# Monitoring unit tests
psql ${PGSAIL_DB_URI} < sql/monitoring.sql > output/monitoring.sql.output
diff sql/monitoring.sql.output output/monitoring.sql.output > /dev/null
#diff -u sql/monitoring.sql.output output/monitoring.sql.output | wc -l
#echo 0
if [ $? -eq 0 ]; then
echo OK
else
echo SQL monitoring.sql FAILED
diff -u sql/monitoring.sql.output output/monitoring.sql.output
exit 1
fi