diff --git a/showcase-dev/examples/datasource-sweapifetch/datasource-sweapifetch.html b/showcase-dev/examples/datasource-consysapi/datasource-consysapi.html
similarity index 100%
rename from showcase-dev/examples/datasource-sweapifetch/datasource-sweapifetch.html
rename to showcase-dev/examples/datasource-consysapi/datasource-consysapi.html
diff --git a/showcase-dev/examples/datasource-sweapifetch/datasource-sweapifetch.js b/showcase-dev/examples/datasource-consysapi/datasource-consysapi.js
similarity index 76%
rename from showcase-dev/examples/datasource-sweapifetch/datasource-sweapifetch.js
rename to showcase-dev/examples/datasource-consysapi/datasource-consysapi.js
index 4ee4225ca1..199a296213 100644
--- a/showcase-dev/examples/datasource-sweapifetch/datasource-sweapifetch.js
+++ b/showcase-dev/examples/datasource-consysapi/datasource-consysapi.js
@@ -1,9 +1,9 @@
import {EventType} from 'osh-js/core/event/EventType';
-// #region snippet_datasource_sweapifetch
-import SweApiFetch from "osh-js/core/datasource/sweapi/SweApi.datasource.js";
+// #region snippet_datasource_consysapi
+import ConSysApi from "osh-js/core/datasource/consysapi/ConSysApi.datasource.js";
import {Mode} from "osh-js/core/datasource/Mode";
-let gpsDataSource = new SweApiFetch("android-GPS", {
+let gpsDataSource = new ConSysApi("android-GPS", {
endpointUrl: 'api.georobotix.io/ogc/t18/api',
resource: '/datastreams/o7pce3e60s0ie/observations',
tls: true,
@@ -15,7 +15,7 @@ let gpsDataSource = new SweApiFetch("android-GPS", {
mode : Mode.REAL_TIME
});
-// #endregion snippet_datasource_sweapifetch
+// #endregion snippet_datasource_consysapi
gpsDataSource.subscribe(async (message) => {
let dataEvent;
diff --git a/showcase-dev/examples/datasource-sweapifetch/package.json b/showcase-dev/examples/datasource-consysapi/package.json
similarity index 100%
rename from showcase-dev/examples/datasource-sweapifetch/package.json
rename to showcase-dev/examples/datasource-consysapi/package.json
diff --git a/showcase-dev/examples/datasource-sweapifetch/webpack.config.js b/showcase-dev/examples/datasource-consysapi/webpack.config.js
similarity index 90%
rename from showcase-dev/examples/datasource-sweapifetch/webpack.config.js
rename to showcase-dev/examples/datasource-consysapi/webpack.config.js
index bbda5fc140..2ca343f4d5 100644
--- a/showcase-dev/examples/datasource-sweapifetch/webpack.config.js
+++ b/showcase-dev/examples/datasource-consysapi/webpack.config.js
@@ -8,10 +8,10 @@ const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
// Tell Webpack which file kicks off our app.
- entry: path.resolve(__dirname,'./datasource-sweapifetch.js'),
+ entry: path.resolve(__dirname,'./datasource-consysapi.js'),
// Tell Weback to output our bundle to ./dist/bundle.js
output: {
- filename: 'bundle.datasource.sweapifetch.js',
+ filename: 'bundle.datasource.consysapi.js',
path: path.resolve(__dirname, 'dist')
},
// Tell Webpack which directories to look in to resolve import statements.
@@ -53,7 +53,7 @@ module.exports = {
compress: true,
port: 9000,
hot: true,
- index: 'datasource-sweapifetch.html',
+ index: 'datasource-consysapi.html',
https:true
},
devtool: 'source-map',
@@ -74,8 +74,8 @@ module.exports = {
// by the Webpack dev server. We can give it a template file (written in EJS)
// and it will handle injecting our bundle for us.
new HtmlWebpackPlugin({
- filename: "datasource-sweapifetch.html",
- template: path.resolve(__dirname, 'datasource-sweapifetch.html')
+ filename: "datasource-consysapi.html",
+ template: path.resolve(__dirname, 'datasource-consysapi.html')
}),
new CopyWebpackPlugin([
{ from: path.resolve(__dirname,'data'), to: 'data'}
diff --git a/showcase-dev/examples/datasynchronizer-dynamic-add-remove-realtime/datasynchronizer-dynamic-add-remove-realtime.js b/showcase-dev/examples/datasynchronizer-dynamic-add-remove-realtime/datasynchronizer-dynamic-add-remove-realtime.js
index 912a8a3b6a..901610e7a4 100644
--- a/showcase-dev/examples/datasynchronizer-dynamic-add-remove-realtime/datasynchronizer-dynamic-add-remove-realtime.js
+++ b/showcase-dev/examples/datasynchronizer-dynamic-add-remove-realtime/datasynchronizer-dynamic-add-remove-realtime.js
@@ -1,5 +1,5 @@
import {EventType} from 'osh-js/core/event/EventType';
-import SweApiDatasource from "osh-js/core/datasource/sweapi/SweApi.datasource.js";
+import ConSysApi from "osh-js/core/datasource/consysapi/ConSysApi.datasource.js";
import {Mode} from "osh-js/core/datasource/Mode";
import DataSynchronizer from "../../../source/core/timesync/DataSynchronizer";
@@ -14,19 +14,19 @@ const commonDatasourceOpts = {
},
};
-const ds0 = new SweApiDatasource('MISB Drone - Video', {
+const ds0 = new ConSysApi('MISB Drone - Video', {
...commonDatasourceOpts,
resource: '/datastreams/h225hesual08g/observations',
responseFormat: 'application/swe+binary',
});
-const ds1 = new SweApiDatasource('MISB UAS - Platform Location', {
+const ds1 = new ConSysApi('MISB UAS - Platform Location', {
...commonDatasourceOpts,
resource: '/datastreams/o7pce3e60s0ie/observations',
responseFormat: 'application/swe+json',
});
-const ds2 = new SweApiDatasource('MISB UAS - Platform Attitude', {
+const ds2 = new ConSysApi('MISB UAS - Platform Attitude', {
...commonDatasourceOpts,
resource: '/datastreams/mlme3gtdfepvc/observations',
responseFormat: 'application/swe+json',
diff --git a/showcase-dev/examples/datasynchronizer-dynamic-add-remove-replay/datasynchronizer-dynamic-add-remove-replay.js b/showcase-dev/examples/datasynchronizer-dynamic-add-remove-replay/datasynchronizer-dynamic-add-remove-replay.js
index 5be98782da..2097f31666 100644
--- a/showcase-dev/examples/datasynchronizer-dynamic-add-remove-replay/datasynchronizer-dynamic-add-remove-replay.js
+++ b/showcase-dev/examples/datasynchronizer-dynamic-add-remove-replay/datasynchronizer-dynamic-add-remove-replay.js
@@ -1,5 +1,5 @@
import {EventType} from 'osh-js/core/event/EventType';
-import SweApiDatasource from "osh-js/core/datasource/sweapi/SweApi.datasource.js";
+import ConSysApi from "osh-js/core/datasource/consysapi/ConSysApi.datasource.js";
import {Mode} from "osh-js/core/datasource/Mode";
import DataSynchronizer from "../../../source/core/timesync/DataSynchronizer";
@@ -18,19 +18,19 @@ const commonDatasourceOpts = {
prefetchBatchSize: 50
};
-const ds0 = new SweApiDatasource('MISB Drone - Video', {
+const ds0 = new ConSysApi('MISB Drone - Video', {
...commonDatasourceOpts,
resource: '/datastreams/8ni90dbu4uf0g/observations',
responseFormat: 'application/swe+binary',
});
-const ds1 = new SweApiDatasource('MISB UAS - Platform Location', {
+const ds1 = new ConSysApi('MISB UAS - Platform Location', {
...commonDatasourceOpts,
resource: '/datastreams/fled6eics1cl4/observations',
responseFormat: 'application/swe+json',
});
-const ds2 = new SweApiDatasource('MISB UAS - Platform Attitude', {
+const ds2 = new ConSysApi('MISB UAS - Platform Attitude', {
...commonDatasourceOpts,
resource: '/datastreams/adheadf9nghts/observations',
responseFormat: 'application/swe+json',
diff --git a/showcase-dev/examples/mqtt-utility/mqtt-utility.js b/showcase-dev/examples/mqtt-utility/mqtt-utility.js
index c6046f97a1..51c73b2784 100644
--- a/showcase-dev/examples/mqtt-utility/mqtt-utility.js
+++ b/showcase-dev/examples/mqtt-utility/mqtt-utility.js
@@ -1,6 +1,6 @@
import MqttProvider from "osh-js/core/mqtt/MqttProvider";
import {randomUUID} from "osh-js/core/utils/Utils";
-import ObservationFilter from "../../../source/core/sweapi/observation/ObservationFilter";
+import ObservationFilter from "../../../source/core/consysapi/observation/ObservationFilter";
const textAreaElement0 = document.getElementById("data-container0");
const textAreaElement1 = document.getElementById("data-container1");
diff --git a/showcase-dev/examples/switch-realtime-batch/switch-realtime-batch.html b/showcase-dev/examples/switch-realtime-batch/switch-realtime-batch.html
index 19afc9fbcc..e786514090 100644
--- a/showcase-dev/examples/switch-realtime-batch/switch-realtime-batch.html
+++ b/showcase-dev/examples/switch-realtime-batch/switch-realtime-batch.html
@@ -29,7 +29,7 @@
diff --git a/showcase-dev/examples/switch-realtime-batch/switch-realtime-batch.js b/showcase-dev/examples/switch-realtime-batch/switch-realtime-batch.js
index 02fe90a551..1f760b8206 100644
--- a/showcase-dev/examples/switch-realtime-batch/switch-realtime-batch.js
+++ b/showcase-dev/examples/switch-realtime-batch/switch-realtime-batch.js
@@ -4,7 +4,7 @@ import CurveLayer from 'osh-js/core/ui/layer/CurveLayer.js';
import SosGetResult from 'osh-js/core/datasource/sos/SosGetResult.datasource.js';
import {Mode} from 'osh-js/core/datasource/Mode';
import DataSynchronizer from "../../../source/core/timesync/DataSynchronizer";
-import SweApiDatasource from "../../../source/core/datasource/sweapi/SweApi.datasource";
+import ConSysApi from "../../../source/core/datasource/consysapi/ConSysApi.datasource";
import {EventType} from "../../../source/core/event/EventType";
function getRandomArbitrary(min, max) {
@@ -17,7 +17,7 @@ const dataContentElt = document.getElementById("data-content");
const masterTimeElt = document.getElementById("master-time");
let initSos = false;
-let initSweapi = false;
+let initConsysapi = false;
let chartDataSource = new SosGetResult("weather", {
endpointUrl: "sensiasoft.net/sensorhub/sos",
@@ -38,7 +38,7 @@ const sosDataSynchronizer = new DataSynchronizer({
});
async function startSosExample() {
- await sweapiDataSynchronizer.disconnect();
+ await consysapiDataSynchronizer.disconnect();
replayButtonElt.onclick = async () => {
await sosDataSynchronizer.setTimeRange(
new Date(Date.now() - 60 * 1000 * 60 * 2).toISOString(),
@@ -105,19 +105,19 @@ const commonDatasourceOpts = {
prefetchBatchSize: 250
};
-const droneLocationDataSource = new SweApiDatasource('MISB UAS - Platform Location', {
+const droneLocationDataSource = new ConSysApi('MISB UAS - Platform Location', {
...commonDatasourceOpts,
resource: '/datastreams/fled6eics1cl4/observations',
responseFormat: 'application/swe+json',
});
-const droneOrientationDataSource = new SweApiDatasource('MISB UAS - Platform Attitude', {
+const droneOrientationDataSource = new ConSysApi('MISB UAS - Platform Attitude', {
...commonDatasourceOpts,
resource: '/datastreams/adheadf9nghts/observations',
responseFormat: 'application/swe+json',
});
-const sweapiDataSynchronizer = new DataSynchronizer({
+const consysapiDataSynchronizer = new DataSynchronizer({
replaySpeed: 2,
masterTimeRefreshRate: 250,
startTime: START_TIME,
@@ -125,11 +125,11 @@ const sweapiDataSynchronizer = new DataSynchronizer({
dataSources: [droneOrientationDataSource, droneLocationDataSource]
});
-async function startSweApiExample() {
+async function startConSysApiExample() {
await sosDataSynchronizer.disconnect();
replayButtonElt.onclick = async () => {
- await sweapiDataSynchronizer.setMode(Mode.REPLAY);
- // await sweapiDataSynchronizer.setTimeRange(
+ await consysapiDataSynchronizer.setMode(Mode.REPLAY);
+ // await consysapiDataSynchronizer.setTimeRange(
// START_TIME,
// END_TIME,
// 2.0,
@@ -138,12 +138,12 @@ async function startSweApiExample() {
// );
replayButtonElt.disabled = true;
realtimeButtonElt.disabled = false;
- await sweapiDataSynchronizer.connect();
+ await consysapiDataSynchronizer.connect();
}
realtimeButtonElt.onclick = async () => {
- await sweapiDataSynchronizer.setMode(Mode.REAL_TIME);
- // await sweapiDataSynchronizer.setTimeRange(
+ await consysapiDataSynchronizer.setMode(Mode.REAL_TIME);
+ // await consysapiDataSynchronizer.setTimeRange(
// 'now',
// '2055-01-01',
// 1.0,
@@ -153,11 +153,11 @@ async function startSweApiExample() {
realtimeButtonElt.disabled = true;
replayButtonElt.disabled = false;
- await sweapiDataSynchronizer.connect();
+ await consysapiDataSynchronizer.connect();
}
- sweapiDataSynchronizer.subscribe(message => displayData(message), [EventType.DATA]);
- sweapiDataSynchronizer.subscribe(message => displayMasterTime(message), [EventType.MASTER_TIME]);
+ consysapiDataSynchronizer.subscribe(message => displayData(message), [EventType.DATA]);
+ consysapiDataSynchronizer.subscribe(message => displayMasterTime(message), [EventType.MASTER_TIME]);
}
const listBoxElement = document.getElementById('services');
@@ -165,8 +165,8 @@ listBoxElement.onchange = (event) => {
let value = event.target.value;
if(value === 'sos') {
startSosExample();
- } else if(value === 'sweapi') {
- startSweApiExample()
+ } else if(value === 'consysapi') {
+ startConSysApiExample()
}
}
diff --git a/showcase-dev/index.js b/showcase-dev/index.js
index b5190e2cf1..a1ae7c7c47 100644
--- a/showcase-dev/index.js
+++ b/showcase-dev/index.js
@@ -21,13 +21,13 @@ var samples = [
url: "datasource-file"
},
{
- name: "DataSource SweApiFetch",
- description: "Display GPS data using the SweApiFetch datasource",
- url: "datasource-sweapifetch"
+ name: "Connected Systems DataSource",
+ description: "Display GPS data using the ConSysApi datasource",
+ url: "datasource-consysapi"
},
{
- name: "DataSource SweApiFetch Json",
- description: "Display data using the SweApiFetch datasource in JSON format",
+ name: "SOS DataSource Swe Json",
+ description: "Display data using the SOS datasource in SWE JSON format",
url: "datasource-swejson"
},
{
@@ -56,8 +56,8 @@ var samples = [
url: "multi-datasources-synchronized"
},
{
- name: 'Switch between Replay & realtime using SOS or SWEAPI service',
- description: 'Switch between Replay & realtime using SOS or SWEAPI service',
+ name: 'Switch between Replay & realtime using SOS or Connected Systems API service',
+ description: 'Switch between Replay & realtime using SOS or Connected Systems API service',
url: 'switch-realtime-batch'
},
{
diff --git a/showcase-dev/webpack.config.js b/showcase-dev/webpack.config.js
index 6868f0d1ea..29f0ec0e49 100644
--- a/showcase-dev/webpack.config.js
+++ b/showcase-dev/webpack.config.js
@@ -77,7 +77,7 @@ module.exports = [{
let directories = [
'datasource-audio',
'datasource-file',
- 'datasource-sweapifetch',
+ 'datasource-consysapi',
'datasource-swejson',
'datasource-video',
'datasources-synchronized',
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/.browserslistrc b/showcase/examples/chart-archive-realtime-synchronized-consysapi/.browserslistrc
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/.browserslistrc
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/.browserslistrc
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/.eslintignore b/showcase/examples/chart-archive-realtime-synchronized-consysapi/.eslintignore
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/.eslintignore
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/.eslintignore
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/.eslintrc.js b/showcase/examples/chart-archive-realtime-synchronized-consysapi/.eslintrc.js
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/.eslintrc.js
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/.eslintrc.js
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/.gitignore b/showcase/examples/chart-archive-realtime-synchronized-consysapi/.gitignore
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/.gitignore
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/.gitignore
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/README.md b/showcase/examples/chart-archive-realtime-synchronized-consysapi/README.md
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/README.md
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/README.md
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/babel.config.js b/showcase/examples/chart-archive-realtime-synchronized-consysapi/babel.config.js
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/babel.config.js
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/babel.config.js
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/chart-archive-realtime-synchronized-sweapi.html b/showcase/examples/chart-archive-realtime-synchronized-consysapi/chart-archive-realtime-synchronized-consysapi.html
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/chart-archive-realtime-synchronized-sweapi.html
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/chart-archive-realtime-synchronized-consysapi.html
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/chart-archive-realtime-synchronized-sweapi.js b/showcase/examples/chart-archive-realtime-synchronized-consysapi/chart-archive-realtime-synchronized-consysapi.js
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/chart-archive-realtime-synchronized-sweapi.js
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/chart-archive-realtime-synchronized-consysapi.js
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/favicon.ico b/showcase/examples/chart-archive-realtime-synchronized-consysapi/favicon.ico
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/favicon.ico
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/favicon.ico
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/android-chrome-192x192.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/android-chrome-192x192.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/android-chrome-192x192.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/android-chrome-192x192.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/android-chrome-512x512.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/android-chrome-512x512.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/android-chrome-512x512.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/android-chrome-512x512.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/android-chrome-maskable-192x192.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/android-chrome-maskable-192x192.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/android-chrome-maskable-192x192.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/android-chrome-maskable-192x192.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/android-chrome-maskable-512x512.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/android-chrome-maskable-512x512.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/android-chrome-maskable-512x512.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/android-chrome-maskable-512x512.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-120x120.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-120x120.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-120x120.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-120x120.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-152x152.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-152x152.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-152x152.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-152x152.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-180x180.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-180x180.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-180x180.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-180x180.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-60x60.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-60x60.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-60x60.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-60x60.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-76x76.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-76x76.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon-76x76.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon-76x76.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/apple-touch-icon.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/apple-touch-icon.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/favicon-16x16.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/favicon-16x16.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/favicon-16x16.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/favicon-16x16.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/favicon-32x32.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/favicon-32x32.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/favicon-32x32.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/favicon-32x32.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/msapplication-icon-144x144.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/msapplication-icon-144x144.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/msapplication-icon-144x144.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/msapplication-icon-144x144.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/mstile-150x150.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/mstile-150x150.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/mstile-150x150.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/mstile-150x150.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/safari-pinned-tab.svg b/showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/safari-pinned-tab.svg
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/img/icons/safari-pinned-tab.svg
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/img/icons/safari-pinned-tab.svg
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/main.js b/showcase/examples/chart-archive-realtime-synchronized-consysapi/main.js
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/main.js
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/main.js
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/package.json b/showcase/examples/chart-archive-realtime-synchronized-consysapi/package.json
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/package.json
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/package.json
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/patches/nouislider+14.4.0.patch b/showcase/examples/chart-archive-realtime-synchronized-consysapi/patches/nouislider+14.4.0.patch
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/patches/nouislider+14.4.0.patch
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/patches/nouislider+14.4.0.patch
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/robots.txt b/showcase/examples/chart-archive-realtime-synchronized-consysapi/robots.txt
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/robots.txt
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/robots.txt
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/src/App.vue b/showcase/examples/chart-archive-realtime-synchronized-consysapi/src/App.vue
similarity index 94%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/src/App.vue
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/src/App.vue
index a97607cb1b..c28dd9a64e 100644
--- a/showcase/examples/chart-archive-realtime-synchronized-sweapi/src/App.vue
+++ b/showcase/examples/chart-archive-realtime-synchronized-consysapi/src/App.vue
@@ -18,7 +18,7 @@ import TimeController from 'osh-js/vue/components/TimeController.vue';
import DataSynchronizer from 'osh-js/core/timesync/DataSynchronizer';
import {Mode} from 'osh-js/core/datasource/Mode';
-import SweApiDatasource from "osh-js/core/datasource/sweapi/SweApi.datasource";
+import ConSysApi from "osh-js/core/datasource/consysapi/ConSysApi.datasource.js";
export default {
components: {
@@ -55,7 +55,7 @@ export default {
prefetchBatchSize: 250
};
- const chartDataSource1 = new SweApiDatasource('Simulated Weather Sensor - weather', {
+ const chartDataSource1 = new ConSysApi('Simulated Weather Sensor - weather', {
...commonDatasourceOpts,
resource: '/datastreams/0tsop3f16nvp8/observations',
responseFormat: 'application/swe+json',
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/src/assets/logo.png b/showcase/examples/chart-archive-realtime-synchronized-consysapi/src/assets/logo.png
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/src/assets/logo.png
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/src/assets/logo.png
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/src/config/index.js b/showcase/examples/chart-archive-realtime-synchronized-consysapi/src/config/index.js
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/src/config/index.js
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/src/config/index.js
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/src/main.js b/showcase/examples/chart-archive-realtime-synchronized-consysapi/src/main.js
similarity index 100%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/src/main.js
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/src/main.js
diff --git a/showcase/examples/chart-archive-realtime-synchronized-sweapi/webpack.config.js b/showcase/examples/chart-archive-realtime-synchronized-consysapi/webpack.config.js
similarity index 90%
rename from showcase/examples/chart-archive-realtime-synchronized-sweapi/webpack.config.js
rename to showcase/examples/chart-archive-realtime-synchronized-consysapi/webpack.config.js
index c8e2b0315f..9c2d627a55 100644
--- a/showcase/examples/chart-archive-realtime-synchronized-sweapi/webpack.config.js
+++ b/showcase/examples/chart-archive-realtime-synchronized-consysapi/webpack.config.js
@@ -8,9 +8,9 @@ const path = require('path');
// Now, using the cesiumConfig in your real configuration
const config = {
- entry: path.resolve(__dirname,'chart-archive-realtime-synchronized-sweapi.js'),
+ entry: path.resolve(__dirname,'chart-archive-realtime-synchronized-consysapi.js'),
output: {
- filename: 'bundle.chart-archive-realtime-synchronized-sweapi.js',
+ filename: 'bundle.chart-archive-realtime-synchronized-consysapi.js',
path: path.resolve(__dirname, 'dist'),
},
@@ -85,15 +85,15 @@ const config = {
compress: true,
port: 9000,
hot: true,
- index: 'chart-archive-realtime-synchronized-sweapi.html',
+ index: 'chart-archive-realtime-synchronized-consysapi.html',
https:true
},
plugins: [
new VueLoaderPlugin(),
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
- template: path.resolve(__dirname, 'chart-archive-realtime-synchronized-sweapi.html'),
- filename: './chart-archive-realtime-synchronized-sweapi.html',
+ template: path.resolve(__dirname, 'chart-archive-realtime-synchronized-consysapi.html'),
+ filename: './chart-archive-realtime-synchronized-consysapi.html',
favicon: path.resolve(__dirname,'favicon.ico')
}),
new DefinePlugin({
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/.browserslistrc b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/.browserslistrc
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/.browserslistrc
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/.browserslistrc
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/.eslintignore b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/.eslintignore
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/.eslintignore
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/.eslintignore
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/.eslintrc.js b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/.eslintrc.js
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/.eslintrc.js
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/.eslintrc.js
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/.gitignore b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/.gitignore
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/.gitignore
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/.gitignore
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/README.md b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/README.md
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/README.md
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/README.md
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/babel.config.js b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/babel.config.js
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/babel.config.js
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/babel.config.js
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/favicon.ico b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/favicon.ico
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/favicon.ico
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/favicon.ico
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-192x192.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-192x192.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-192x192.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-192x192.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-512x512.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-512x512.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-512x512.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-512x512.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-maskable-192x192.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-maskable-192x192.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-maskable-192x192.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-maskable-192x192.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-maskable-512x512.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-maskable-512x512.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-maskable-512x512.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/android-chrome-maskable-512x512.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-120x120.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-120x120.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-120x120.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-120x120.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-152x152.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-152x152.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-152x152.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-152x152.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-180x180.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-180x180.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-180x180.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-180x180.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-60x60.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-60x60.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-60x60.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-60x60.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-76x76.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-76x76.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-76x76.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon-76x76.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/apple-touch-icon.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/favicon-16x16.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/favicon-16x16.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/favicon-16x16.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/favicon-16x16.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/favicon-32x32.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/favicon-32x32.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/favicon-32x32.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/favicon-32x32.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/msapplication-icon-144x144.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/msapplication-icon-144x144.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/msapplication-icon-144x144.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/msapplication-icon-144x144.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/mstile-150x150.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/mstile-150x150.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/mstile-150x150.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/mstile-150x150.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/safari-pinned-tab.svg b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/safari-pinned-tab.svg
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/img/icons/safari-pinned-tab.svg
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/img/icons/safari-pinned-tab.svg
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/main.js b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/main.js
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/main.js
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/main.js
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/package.json b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/package.json
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/package.json
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/package.json
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/patches/nouislider+14.4.0.patch b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/patches/nouislider+14.4.0.patch
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/patches/nouislider+14.4.0.patch
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/patches/nouislider+14.4.0.patch
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/robots.txt b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/robots.txt
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/robots.txt
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/robots.txt
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/App.vue b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/App.vue
similarity index 93%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/App.vue
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/App.vue
index 4d505c0e22..08a7919ccd 100644
--- a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/App.vue
+++ b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/App.vue
@@ -19,7 +19,7 @@
import TimeController from 'osh-js/vue/components/TimeController.vue';
import FFMPEGView from 'osh-js/core/ui/view/video/FFMPEGView';
import DataSynchronizer from 'osh-js/core/timesync/DataSynchronizer';
-import SweApiFetch from 'osh-js/core/datasource/sweapi/SweApi.datasource.js';
+import ConSysApi from 'osh-js/core/datasource/consysapi/ConSysApi.datasource.js';
import {Mode} from 'osh-js/core/datasource/Mode';
import VideoView from 'osh-js/core/ui/view/video/VideoView';
import VideoDataLayer from 'osh-js/core/ui/layer/VideoDataLayer';
@@ -49,19 +49,19 @@ export default {
prefetchBatchSize: 250
};
- const dataSource0 = new SweApiFetch("drone-Video", {
+ const dataSource0 = new ConSysApi("drone-Video", {
...opts
});
- const dataSource1 = new SweApiFetch("drone-Video1", {
+ const dataSource1 = new ConSysApi("drone-Video1", {
...opts
});
- const dataSource2 = new SweApiFetch("drone-Video2", {
+ const dataSource2 = new ConSysApi("drone-Video2", {
...opts
});
- const dataSource3 = new SweApiFetch("drone-Video3", {
+ const dataSource3 = new ConSysApi("drone-Video3", {
...opts
});
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/assets/logo.png b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/assets/logo.png
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/assets/logo.png
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/assets/logo.png
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/config/index.js b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/config/index.js
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/config/index.js
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/config/index.js
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/main.js b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/main.js
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/src/main.js
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/src/main.js
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/video-with-control-vuejs-synchronized.html b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/video-with-control-vuejs-synchronized.html
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/video-with-control-vuejs-synchronized.html
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/video-with-control-vuejs-synchronized.html
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/video-with-control-vuejs-synchronized.js b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/video-with-control-vuejs-synchronized.js
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/video-with-control-vuejs-synchronized.js
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/video-with-control-vuejs-synchronized.js
diff --git a/showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/webpack.config.js b/showcase/examples/consysapi-video-with-control-vuejs-synchronized/webpack.config.js
similarity index 100%
rename from showcase/examples/sensorwebapi-video-with-control-vuejs-synchronized/webpack.config.js
rename to showcase/examples/consysapi-video-with-control-vuejs-synchronized/webpack.config.js
diff --git a/showcase/examples/mqtt/mqtt.js b/showcase/examples/mqtt/mqtt.js
index e7fd0c9a61..a11c67f40a 100644
--- a/showcase/examples/mqtt/mqtt.js
+++ b/showcase/examples/mqtt/mqtt.js
@@ -1,5 +1,5 @@
// create data source for Android phone GPS
-import SweApiFetch from 'osh-js/core/datasource/sweapi/SweApi.datasource.js';
+import ConSysApi from 'osh-js/core/datasource/consysapi/ConSysApi.datasource.js';
import PointMarkerLayer from 'osh-js/core/ui/layer/PointMarkerLayer.js';
import LeafletView from 'osh-js/core/ui/view/map/LeafletView.js';
import ChartJsView from 'osh-js/core/ui/view/chart/ChartJsView';
@@ -16,7 +16,7 @@ const mqttProps = {
password: 'WR6zlso9h#'
};
-let gpsDataSource = new SweApiFetch("android-GPS", {
+let gpsDataSource = new ConSysApi("android-GPS", {
endpointUrl: 'api.georobotix.io/ogc/t18/api',
resource: '/datastreams/rbnag2hrc04mm/observations',
tls: true,
@@ -25,7 +25,7 @@ let gpsDataSource = new SweApiFetch("android-GPS", {
mode: Mode.REAL_TIME
});
-const isaDataSource = new SweApiFetch("ISA-bio-sensor", {
+const isaDataSource = new ConSysApi("ISA-bio-sensor", {
endpointUrl: 'api.georobotix.io/ogc/t18/api',
resource: '/datastreams/b4runsn23q66o/observations',
tls: true,
diff --git a/showcase/examples/tasking/tasking.js b/showcase/examples/tasking/tasking.js
index 79453ab3db..f21d037123 100644
--- a/showcase/examples/tasking/tasking.js
+++ b/showcase/examples/tasking/tasking.js
@@ -1,10 +1,10 @@
-import Systems from "osh-js/core/sweapi/system/Systems";
+import Systems from "osh-js/core/consysapi/system/Systems";
import {EventType} from "osh-js/core/event/EventType";
-import ControlFilter from "osh-js/core/sweapi/control/ControlFilter";
-import SweApiFetch from "osh-js/core/datasource/sweapi/SweApi.datasource";
+import ConSysApi from "osh-js/core/datasource/consysapi/ConSysApi.datasource.js";
import PointMarkerLayer from "osh-js/core/ui/layer/PointMarkerLayer";
import LeafletView from "osh-js/core/ui/view/map/LeafletView";
import PolylineLayer from "osh-js/core/ui/layer/PolylineLayer";
+import ControlStreamFilter from "../../../source/core/consysapi/controlstream/ControlStreamFilter";
var prevTime = 0;
@@ -22,7 +22,7 @@ const mqttProps = {
password: password
};
-let gpsDataSource = new SweApiFetch("supersonic drone GPS", {
+let gpsDataSource = new ConSysApi("supersonic drone GPS", {
resource: `/api/datastreams/${posDsId}/observations`,
endpointUrl: 'api.georobotix.io/ogc/t18/api',
protocol: 'ws',
@@ -101,9 +101,9 @@ async function startListening() {
gpsDataSource.connect();
const system = await systems.getSystemById(systemId);
- const control = await system.getControlById(cmdStreamId);
+ const control = await system.getControlStreamById(cmdStreamId);
- control.streamStatus(new ControlFilter({}), async (message) =>{
+ control.streamStatus(new ControlStreamFilter({}), async (message) =>{
textCommandElt.innerHTML = "";
const status = message;
textStatusElt.innerHTML = JSON.stringify(status, null, 2);
diff --git a/showcase/index.html b/showcase/index.html
index 72adfd3df4..90d1bae864 100644
--- a/showcase/index.html
+++ b/showcase/index.html
@@ -201,6 +201,14 @@
height: 64px;
width: 64px;
}
+
+ span.badge {
+ background-color: red;
+ color: white;
+ padding: 4px 8px;
+ text-align: center;
+ border-radius: 0px;
+ }
@@ -224,13 +232,13 @@
+ helo
sample description
-
diff --git a/showcase/index.js b/showcase/index.js
index 2efdf27a73..0ef3665a47 100644
--- a/showcase/index.js
+++ b/showcase/index.js
@@ -7,163 +7,193 @@ var Normalizer = require('prismjs/plugins/normalize-whitespace/prism-normalize-w
var samples = [{
name: "FOI Locations (CesiumJS)",
description: "Display the location of several features of interest on a CesiumJS globe.",
- url: "cesium-fois"
+ url: "cesium-fois",
+ datasourceType: 'SOS',
},
{
name: "Moving Location (CesiumJS)",
description: "Display a moving marker on a CesiumJS globe, tracking the current location of a vehicle.",
- url: "cesium-location"
+ url: "cesium-location",
+ datasourceType: 'SOS',
},
{
name: "Moving Location with custom viewer properties(CesiumJS)",
description: "Display a moving marker on a CesiumJS globe, tracking the current location of a vehicle and define some custom cesium viewer properties.",
- url: "cesium-location-opts"
+ url: "cesium-location-opts",
+ datasourceType: 'SOS',
},
{
name: "Moving Location + path (CesiumJS)",
description: "Display a moving marker and a polyline on a CesiumJS map, showing both the current location of a vehicle and the historical track.",
- url: "cesium-location-path"
+ url: "cesium-location-path",
+ datasourceType: 'SOS',
},
{
name: "Moving Location (Deck.gl)",
description: "Display a moving marker on a Deck.gl canvas, tracking the current location of a vehicle.",
- url: "deckgl-location"
+ url: "deckgl-location",
+ datasourceType: 'SOS',
},
{
name: "Simple Chart (Chart.js)",
description: "Display a chart with time series of weather measurements.",
- url: "chart"
+ url: "chart",
+ datasourceType: 'SOS',
},
{
name: "Moving Location (Leaflet)",
description: "Display a moving marker on a Leaflet map, tracking the current location of a vehicle.",
- url: "leaflet-location"
+ url: "leaflet-location",
+ datasourceType: 'SOS',
},
{
name: "FOI Locations (Leaflet)",
description: "Display the location of several features of interest on a Leaflet map.",
url: "leaflet-location-fois",
- screenshot: "images/screenshots/leaflet-fois.png"
+ screenshot: "images/screenshots/leaflet-fois.png",
+ datasourceType: 'SOS',
},
{
name: "Moving Location + Heading (Leaflet)",
description: "Display a moving marker on a Leaflet map, tracking the current location and heading of a vehicle.",
- url: "leaflet-location-heading"
+ url: "leaflet-location-heading",
+ datasourceType: 'SOS',
},
{
name: "Moving Location + Path (Leaflet)",
description: "Display a moving marker and a polyline on a Leaflet map, showing both the current location of a vehicle and the historical track.",
- url: "leaflet-location-path"
+ url: "leaflet-location-path",
+ datasourceType: 'SOS',
},
{
name: "Moving Location (OpenLayers)",
description: "Display a moving marker on an OpenLayers map, tracking the current location of a vehicle.",
- url: "openlayers-location"
+ url: "openlayers-location",
+ datasourceType: 'SOS',
},
{
name: "Moving Location + Heading (OpenLayers)",
description: "Display a moving marker on an OpenLayers map, tracking the current location and heading of a vehicle.",
- url: "openlayers-location-heading"
+ url: "openlayers-location-heading",
+ datasourceType: 'SOS',
},
{
name: "Moving Location + Path + Heading (Mapbox)",
description: "Display a moving marker and a polyline on a Mapbox map, showing both the current location of a vehicle and the historical track.",
- url: "mapbox-location-path-heading"
+ url: "mapbox-location-path-heading",
+ datasourceType: 'SOS',
},
{
name: "Moving Location + Heading + Video (Leaflet)",
description: "Display a moving marker on an Leaflet map, tracking the current location of a vehicle and its corresponding" +
"video. Create duplicated dataSources running at different time to check there is no collision between data. The " +
"2 datasets are using a DataSynchronizer object. Each one should be independent.",
- url: "video-map-multiple-datasource"
+ url: "video-map-multiple-datasource",
+ datasourceType: 'SOS',
},
{
name: "Z-Index ordering",
description: "Display a moving marker on an Leaflet, DeckGl,Cesium and Openlayers map using a z-Index between markers",
- url: "zIndex-location-path"
+ url: "zIndex-location-path",
+ datasourceType: 'SOS',
},
{
name: "Resizable H264 Video",
description: "Display an H264 video in a simple resizable DIV using our FFMPEG-JS decoder.",
- url: "video-h264"
+ url: "video-h264",
+ datasourceType: 'SOS',
},
{
name: "H264 Video using WebCodecAPI",
description: "Display an H264 video in a simple DIV using Experimental Hardware WebCodecAPI decoder.",
- url: "video-h264-webcodec-api"
+ url: "video-h264-webcodec-api",
+ datasourceType: 'SOS',
},
{
name: "H264 Image draping Video",
description: "Display an H264 video in a simple DIV using our FFMPEG-JS decoder and drap the decoded frame onto the terrain.",
- url: "video-h264-draping"
+ url: "video-h264-draping",
+ datasourceType: 'SOS',
},
{
name: "Resizable MJPEG Video",
description: "Display an MJPEG video in a simple resizable DIV.",
- url: "video-mjpeg"
+ url: "video-mjpeg",
+ datasourceType: 'SOS',
},
{
name: 'VueJs component: Multiple Video with control',
description: 'Display multiple videos using forward/pause/play/backward control using the same DataSynchronizer',
url: 'video-with-control-vuejs-synchronized',
- code: 'vue/App_examples/video-with-control-vuejs-synchronized.vue'
+ code: 'vue/App_examples/video-with-control-vuejs-synchronized.vue',
+ datasourceType: 'SOS',
},
{
name: 'AVL data using multiple ids',
description: 'Display multiple markers corresponding to a unique id provided by the same DataSource',
- url: 'avl'
+ url: 'avl',
+ datasourceType: 'SOS',
},
{
name: 'AVL data using multiple ids and Time controller in VueJS',
description: 'Display multiple markers corresponding to a unique id provided by the same DataSource with a Time controller in VueJS',
url: 'avl-with-control-vuejs',
- code: 'vue/App_examples/avl-with-control-vuejs.vue'
+ code: 'vue/App_examples/avl-with-control-vuejs.vue',
+ datasourceType: 'SOS',
},
{
name: 'ISA Biological & MISB UAS sensor data using MQTT protocol',
description: 'Display biological and GPS sensors from ISA Biological Sensor & MISB UAS using MQTT protocol',
- url: 'mqtt'
+ url: 'mqtt',
+ datasourceType: 'Connected Systems',
},
{
name: "Chart with Time controller (Chart.js)",
description: "Display a chart with time series of weather measurements and time controller.",
url: "chart-archive-realtime",
- code: 'vue/App_examples/chart-archive-realtime.vue'
+ code: 'vue/App_examples/chart-archive-realtime.vue',
+ datasourceType: 'SOS',
},
{
name: "Chart with Time controller (Chart.js) in batch mode",
description: "Display a chart using full batch mode with time series of weather measurements and time controller.",
url: "chart-archive-realtime-batch",
- code: 'vue/App_examples/chart-archive-realtime-batch.vue'
+ code: 'vue/App_examples/chart-archive-realtime-batch.vue',
+ datasourceType: 'SOS',
},
{
name: "Chart with Time controller and Synchronizer (Chart.js)",
description: "Display a chart with time series of weather measurements and time controller.",
url: "chart-archive-realtime-synchronized",
- code: 'vue/App_examples/chart-archive-realtime-synchronized.vue'
+ code: 'vue/App_examples/chart-archive-realtime-synchronized.vue',
+ datasourceType: 'SOS',
},
{
name: "Chart with Time controller and Synchronizer using 'trackRealtime' option(Chart.js)",
description: "Display a chart with time series of weather measurements and time controller and tracking realtime.",
- url: "chart-archive-realtime-synchronized-sweapi",
- code: 'vue/App_examples/chart-archive-realtime-synchronized-sweapi.vue'
+ url: "chart-archive-realtime-synchronized-consysapi",
+ code: 'vue/App_examples/chart-archive-realtime-synchronized-consysapi.vue',
+ datasourceType: 'Connected Systems',
},
{
name: "Audio WebCodec/FFmpeg.js decoding",
description: "Listen audio stream using WebCodec/FFmpeg.js",
- url: "audio"
+ url: "audio",
+ datasourceType: 'SOS',
},
{
name: "Audio WebCodec/FFmpeg.js decoding with time controller",
description: "Listen audio stream using WebCodec/FFmpeg.js with time controller",
url: 'audio-with-control-vuejs',
- code: 'vue/App_examples/audio-with-control-vuejs.vue'
+ code: 'vue/App_examples/audio-with-control-vuejs.vue',
+ datasourceType: 'SOS',
},
{
name: "Audio & Video WebCodec/FFmpeg.js decoding with time controller",
description: "Listen audio stream using WebCodec/FFmpeg.js with time controller and associated Video",
url: 'audio-video-synchronized-with-control-vuejs',
- code: 'vue/App_examples/audio-video-synchronized-with-control-vuejs.vue'
+ code: 'vue/App_examples/audio-video-synchronized-with-control-vuejs.vue',
+ datasourceType: 'SOS',
}
];
@@ -172,6 +202,10 @@ var currentSample;
samples.forEach(s => {
var $newElt = $($("#card-template").html());
$("p.card-text", $newElt).html(s.description);
+
+ $("span.badge", $newElt).text(s.datasourceType);
+ $("span.badge", $newElt).css("background-color", s.datasourceType === "SOS" ? "gray" : "red");
+
$("img", $newElt)
.on("error", e => e.target.src = "https://opensensorhub.files.wordpress.com/2017/08/opensensorhub-logo2.png")
.attr("title", s.name)
diff --git a/showcase/webpack.config.js b/showcase/webpack.config.js
index d84c80b186..7eda5d1c08 100644
--- a/showcase/webpack.config.js
+++ b/showcase/webpack.config.js
@@ -102,7 +102,7 @@ let directories = [
'chart-archive-realtime',
'chart-archive-realtime-batch',
'chart-archive-realtime-synchronized',
- 'chart-archive-realtime-synchronized-sweapi',
+ 'chart-archive-realtime-synchronized-consysapi',
'audio',
'audio-with-control-vuejs',
'audio-video-synchronized-with-control-vuejs',
diff --git a/source/core/OSH.js b/source/core/OSH.js
index 9a7b051afe..69f753a723 100644
--- a/source/core/OSH.js
+++ b/source/core/OSH.js
@@ -9,6 +9,7 @@ export { default as DataSynchronizer } from './timesync/DataSynchronizer.js';
export { default as DataSource } from './datasource/DataSource.js';
export { default as SosGetResult } from './datasource/sos/SosGetResult.js';
export { default as SweApiFetch } from './datasource/sweapi/SweApiFetch.js';
+export { default as ConSysApi } from './datasource/consysapi/ConSysApi.datasource.js'
export { default as OrientationQuaternion } from '../ext/datasource/OrientationQuaternion.js';
export { default as SosGetFois } from './datasource/sos/SosGetFois.js';
export { default as TimeSeriesDataSource } from './datasource/TimeSeriesDataSource.js';
@@ -50,31 +51,59 @@ export { default as AudioFrequencyChartJsVisualizer } from './ui/view/audio/vis
export { default as AudioSpectrogramVisualizer } from './ui/view/audio/visualizer/spectrogram/AudioSpectrogramVisualizer.js';
export { default as AudioRollingSpectrogramCanvasVisualizer } from './ui/view/audio/visualizer/spectrogram/AudioRollingSpectrogramCanvasVisualizer.js';
export { default as View } from './ui/view/View.js';
-export { default as Command } from './sweapi/command/Command.js';
-export { default as Commands } from './sweapi/command/Commands.js';
-export { default as CommandFilter } from './sweapi/command/CommandFilter.js';
-export { default as Control } from './sweapi/control/Control.js';
-export { default as Controls } from './sweapi/control/Controls.js';
-export { default as ControlFilter } from './sweapi/control/ControlFilter.js';
-export { default as DataStream } from './sweapi/datastream/DataStream.js';
-export { default as DataStreams } from './sweapi/datastream/DataStreams.js';
-export { default as DataStreamFilter } from './sweapi/datastream/DataStreamFilter.js';
-export { default as Event } from './sweapi/event/Event.js';
-export { default as Events } from './sweapi/event/Events.js';
-export { default as EventFilter } from './sweapi/event/EventFilter.js';
-export { default as FeatureOfInterest } from './sweapi/featureofinterest/FeatureOfInterest.js';
-export { default as FeatureOfInterests } from './sweapi/featureofinterest/FeatureOfInterests.js';
-export { default as FeatureOfInterestFilter } from './sweapi/featureofinterest/FeatureOfInterestFilter.js';
-export { default as SystemHistoryFilter } from './sweapi/history/SystemHistoryFilter.js';
-export { default as Observation } from './sweapi/observation/Observation.js';
-export { default as Observations } from './sweapi/observation/Observations.js';
-export { default as ObservationFilter } from './sweapi/observation/ObservationFilter.js';
-export { default as System } from './sweapi/system/System.js';
-export { default as Systems } from './sweapi/system/Systems.js';
-export { default as SystemFilter } from './sweapi/system/SystemFilter.js';
-export { default as Collection } from './sweapi/Collection.js';
-export { default as ObservationsCollection } from './sweapi/ObservationsCollection.js';
-export { default as SensorWebApi } from './sweapi/SensorWebApi.js';
+// SWE API
+// export { default as Command } from './sweapi/command/Command.js';
+// export { default as Commands } from './sweapi/command/Commands.js';
+// export { default as CommandFilter } from './sweapi/command/CommandFilter.js';
+// export { default as Control } from './sweapi/control/Control.js';
+// export { default as Controls } from './sweapi/control/Controls.js';
+// export { default as ControlFilter } from './sweapi/control/ControlFilter.js';
+// export { default as DataStream } from './sweapi/datastream/DataStream.js';
+// export { default as DataStreams } from './sweapi/datastream/DataStreams.js';
+// export { default as DataStreamFilter } from './sweapi/datastream/DataStreamFilter.js';
+// export { default as Event } from './sweapi/event/Event.js';
+// export { default as Events } from './sweapi/event/Events.js';
+// export { default as EventFilter } from './sweapi/event/EventFilter.js';
+// export { default as FeatureOfInterest } from './sweapi/featureofinterest/FeatureOfInterest.js';
+// export { default as FeatureOfInterests } from './sweapi/featureofinterest/FeatureOfInterests.js';
+// export { default as FeatureOfInterestFilter } from './sweapi/featureofinterest/FeatureOfInterestFilter.js';
+// export { default as SystemHistoryFilter } from './sweapi/history/SystemHistoryFilter.js';
+// export { default as Observation } from './sweapi/observation/Observation.js';
+// export { default as Observations } from './sweapi/observation/Observations.js';
+// export { default as ObservationFilter } from './sweapi/observation/ObservationFilter.js';
+// export { default as System } from './sweapi/system/System.js';
+// export { default as Systems } from './sweapi/system/Systems.js';
+// export { default as SystemFilter } from './sweapi/system/SystemFilter.js';
+// export { default as Collection } from './sweapi/Collection.js';
+// export { default as ObservationsCollection } from './sweapi/ObservationsCollection.js';
+// export { default as SensorWebApi } from './sweapi/SensorWebApi.js';
+// Connected Systems API
+export { default as Command } from './consysapi/command/Command.js';
+export { default as Commands } from './consysapi/command/Commands.js';
+export { default as CommandFilter } from './consysapi/command/CommandFilter.js';
+export { default as ControlStream } from './consysapi/controlstream/ControlStream.js';
+export { default as ControlStreams } from './consysapi/controlstream/ControlStreams.js';
+export { default as ControlStreamFilter } from './consysapi/controlstream/ControlStreamFilter.js';
+export { default as DataStream } from './consysapi/datastream/DataStream.js';
+export { default as DataStreams } from './consysapi/datastream/DataStreams.js';
+export { default as DataStreamFilter } from './consysapi/datastream/DataStreamFilter.js';
+export { default as Event } from './consysapi/event/Event.js';
+export { default as Events } from './consysapi/event/Events.js';
+export { default as EventFilter } from './consysapi/event/EventFilter.js';
+export { default as SamplingFeature } from './consysapi/samplingfeature/SamplingFeature.js';
+export { default as SamplingFeatures } from './consysapi/samplingfeature/SamplingFeatures.js';
+export { default as SamplingFeatureFilter } from './consysapi/samplingfeature/SamplingFeatureFilter.js';
+export { default as SystemHistoryFilter } from './consysapi/history/SystemHistoryFilter.js';
+export { default as Observation } from './consysapi/observation/Observation.js';
+export { default as Observations } from './consysapi/observation/Observations.js';
+export { default as ObservationFilter } from './consysapi/observation/ObservationFilter.js';
+export { default as System } from './consysapi/system/System.js';
+export { default as Systems } from './consysapi/system/Systems.js';
+export { default as SystemFilter } from './consysapi/system/SystemFilter.js';
+export { default as Collection } from './consysapi/Collection.js';
+export { default as ObservationsCollection } from './consysapi/ObservationsCollection.js';
+export { default as ConnectedSystemsApi } from './consysapi/ConnectedSystemsApi.js';
+
export { default as File } from '../ext/datasource/File.js';
export { default as FileConnector } from '../ext/connector/FileConnector.js';
diff --git a/source/core/connector/MqttConnector.js b/source/core/connector/MqttConnector.js
index 59a8494c48..f49ff5846c 100644
--- a/source/core/connector/MqttConnector.js
+++ b/source/core/connector/MqttConnector.js
@@ -15,10 +15,9 @@
******************************* END LICENSE BLOCK ***************************/
import DataConnector from "./DataConnector";
-import {assertDefined, isDefined, randomUUID} from "../utils/Utils";
+import {isDefined, randomUUID} from "../utils/Utils";
import {Status} from "./Status";
import MqttProvider from "../mqtt/MqttProvider";
-import ObservationFilter from "../sweapi/observation/ObservationFilter";
/**
* Defines the MqttConnector to connect to a remote server by creating a Mqtt channel.
diff --git a/source/core/consysapi/Collection.js b/source/core/consysapi/Collection.js
new file mode 100644
index 0000000000..61dd9bd149
--- /dev/null
+++ b/source/core/consysapi/Collection.js
@@ -0,0 +1,135 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2021 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import SweCollectionDataParser from "../parsers/consysapi/collection/SweCollectionDataParser";
+
+class Collection {
+ /**
+ *
+ */
+ constructor(url, filter, pageSize, parser, responseFormat = 'json') {
+ this.url = url;
+ this.filter = filter;
+ this.pageSize = pageSize;
+ this.parser = parser;
+ this.pageOffset = 0;
+ this.init = false;
+ this.total = 0;
+ this.collectionDataParser = new SweCollectionDataParser(filter.props.format);
+ this.responseFormat = responseFormat;
+ this.currentPage = -1;
+ }
+
+ /**
+ * Check if has next page
+ * @return {boolean}
+ */
+ hasNext() {
+ return this.pageOffset !== -1;
+ }
+
+ async fetchData(offset) {
+ const queryString = `${this.filter.toQueryString()}&offset=${offset}&limit=${this.pageSize}`;
+ const fullUrl = this.url + '?' + queryString;
+
+ const jsonResponse = await fetch(fullUrl, {
+ method: 'GET',
+ credentials: 'include',
+ headers: {}
+ }).then((response) => {
+ if (!response.ok) {
+ const err = new Error(`Got ${response.status} response from ${fullUrl}`);
+ err.response = response;
+ throw err;
+ }
+ if (this.responseFormat === 'json') {
+ return response.json();
+ } else if (this.responseFormat === 'arraybuffer') {
+ return response.arrayBuffer();
+ }
+ });
+
+ return this.parseResponse(jsonResponse);
+ }
+
+ async parseResponse(jsonResponse) {
+ const items = this.collectionDataParser.parseData(jsonResponse);
+ const data = [];
+ if (Array.isArray(items)) {
+ for (let item of items) {
+ data.push(this.parser.parseData(item));
+ }
+ } else {
+ data.push(items);
+ }
+ return data;
+ }
+
+ /**
+ * Fetches next page.
+ * @param page - the number of page to fetch
+ * @return {Promise}
+ */
+ async nextPage() {
+ if (this.hasNext()) {
+ this.currentPage++;
+ this.pageOffset = this.currentPage * this.pageSize;
+ const data = await this.fetchData(this.pageOffset);
+ if (data.length === 0 || data.length < this.pageSize) {
+ this.pageOffset = -1;
+ }
+ return data;
+ } else {
+ throw Error('Has no more pages');
+ }
+ }
+
+ async page(page) {
+ this.currentPage = page;
+ this.pageOffset = this.currentPage * this.pageSize;
+ const data = await this.fetchData(this.pageOffset);
+ if (data.length === 0 || data.length < this.pageSize) {
+ this.pageOffset = -1;
+ }
+ return data;
+ }
+
+ /**
+ * Fetches previous page.
+ * @param page - the number of page to fetch
+ * @return {Promise}
+ */
+ async previousPage() {
+ if (this.hasPrevious()) {
+ this.currentPage--;
+ this.pageOffset = this.currentPage * this.pageSize;
+ return this.fetchData(this.pageOffset);
+ } else {
+ throw Error('Has no more pages');
+ }
+ }
+
+ /**
+ * Check if has previous page
+ * @return {boolean}
+ */
+ hasPrevious() {
+ return this.currentPage > 0;
+ }
+
+}
+
+export default Collection;
diff --git a/source/core/consysapi/ConnectedSystemsApi.js b/source/core/consysapi/ConnectedSystemsApi.js
new file mode 100644
index 0000000000..6ddcf0d891
--- /dev/null
+++ b/source/core/consysapi/ConnectedSystemsApi.js
@@ -0,0 +1,160 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import WebSocketConnector from "../connector/WebSocketConnector";
+import {assertDefined, isDefined} from "../utils/Utils";
+import MqttTopicConnector from "../connector/MqttTopicConnector";
+import MqttConnector from "../connector/MqttConnector";
+
+class ConnectedSystemsApi {
+
+ /**
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ * @param {Object} networkProperties.connectorOpts - Specific connector options
+ */
+ constructor(networkProperties) {
+ assertDefined(networkProperties.endpointUrl, 'endpointUrl');
+ this.networkProperties = networkProperties;
+
+ let endpoint = networkProperties.endpointUrl;
+ if (endpoint.endsWith('/')) {
+ endpoint = endpoint.substring(0, endpoint.length - 1);
+ }
+
+ const tls = (networkProperties.tls) ? 's' : '';
+ this.url = 'http' + tls + '://' + endpoint;
+
+ this._network = {}
+ if (isDefined(networkProperties.connector)) {
+ this._network.stream = {
+ connector: networkProperties.connector,
+ };
+ } else if(isDefined(networkProperties.streamProtocol)){
+ this._network.stream = {
+ connector: this.createStreamConnector(networkProperties)
+ }
+ } else {
+ // default Stream to WS
+ this._network.stream = {
+ connector: this.createStreamConnector({
+ ...networkProperties,
+ streamProtocol: 'ws'
+ })
+ }
+ }
+ }
+
+ baseUrl() {
+ return this.url;
+ }
+
+ stream() {
+ return this._network.stream.connector;
+ }
+
+ createStreamConnector(networkProperties) {
+ assertDefined(networkProperties.streamProtocol, 'streamProtocol');
+
+ let endpoint = networkProperties.endpointUrl;
+ if(networkProperties.streamProtocol === 'mqtt' && isDefined(networkProperties.mqttOpts)) {
+ endpoint = networkProperties.mqttOpts.endpointUrl;
+ }
+
+ if (endpoint.endsWith('/')) {
+ endpoint = endpoint.substring(0, endpoint.length - 1);
+ }
+
+ const tls = (networkProperties.tls) ? 's' : '';
+ const url = networkProperties.streamProtocol + tls + '://' + endpoint;
+
+ if(networkProperties.streamProtocol === 'mqtt') {
+ // return new MqttConnector(url, networkProperties);
+ return new MqttTopicConnector(networkProperties.mqttOpts.bcId, networkProperties);
+ } else if(networkProperties.streamProtocol === 'ws') {
+ return new WebSocketConnector(url);
+ }
+ }
+
+ connect() {
+ this._network.stream.connector.connect();
+ }
+
+ getHeaders() {
+ const headers = {
+ };
+
+ if('connectorOpts' in this.networkProperties){
+ if('username' in this.networkProperties.connectorOpts && 'password' in this.networkProperties.connectorOpts) {
+ headers['Authorization'] = 'Basic ' +
+ btoa(this.networkProperties.connectorOpts.username + ":" + this.networkProperties.connectorOpts.password);
+ } else {
+ for(let key in this.networkProperties.connectorOpts) {
+ headers[key] = this.networkProperties.connectorOpts[key];
+ }
+ }
+ }
+ return headers;
+ }
+
+ fetchAsJson(apiUrl, queryString) {
+ const fullUrl = this.baseUrl() + apiUrl + '?' +queryString;
+
+ const headers = this.getHeaders();
+
+ return fetch(fullUrl, {
+ method: 'GET',
+ credentials: 'include',
+ headers: headers
+ }
+ ).then(function (response) {
+ if (!response.ok) {
+ const err = new Error(`Got ${response.status} response from ${this.baseUrl()}`);
+ err.response = response;
+ throw err;
+ }
+ return response.json();
+ });
+ }
+
+ postAsJson(apiUrl, jsonPayload) {
+ const fullUrl = this.baseUrl() + apiUrl;
+
+ const headers = this.getHeaders();
+
+ headers['Accept'] = 'application/json';
+ headers['Content-Type'] = 'application/json';
+
+ fetch(fullUrl, {
+ method: 'POST',
+ headers: headers,
+ credentials: 'include',
+ body: jsonPayload
+ }).then(function (response) {
+ if (!response.ok) {
+ const err = new Error(`Got ${response.status} response from ${fullUrl}`);
+ err.response = response;
+ throw err;
+ }
+ });
+ }
+}
+export default ConnectedSystemsApi;
diff --git a/source/core/consysapi/Filter.js b/source/core/consysapi/Filter.js
new file mode 100644
index 0000000000..36c78abc74
--- /dev/null
+++ b/source/core/consysapi/Filter.js
@@ -0,0 +1,58 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2021 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import {isDefined} from "../utils/Utils";
+
+class ConnectedSystemsApiFilter {
+ constructor(props) {
+ this.props = props;
+ }
+
+ /**
+ *
+ * @param {string[]} [includes=[]] list of parameters to include - all if omitted
+ * @param {string[]} [excludes=[]] list of parameters to exclude - none if omitted
+ * @return {string}
+ */
+ toQueryString(includes= [], excludes = []) {
+ let queryString = '';
+ let separator = '';
+ excludes.push('replaySpeed');
+ for (let queryParameter in this.props) {
+ if(excludes.includes(queryParameter)) {
+ continue;
+ }
+ if((includes.length === 0 || includes.includes(queryParameter)) && isDefined(this.props[queryParameter])) {
+ // if(Array.isArray(this.props[queryParameter])) {
+ // queryString += separator + queryParameter + '=' + encodeURIComponent(this.props[queryParameter].join());
+ /*} else*/ if(queryParameter === 'f'
+ || queryParameter === 'format'
+ || queryParameter === 'responseFormat'
+ || queryParameter === 'obsFormat'
+ ) {
+ queryString += separator + queryParameter + '=' + this.props[queryParameter].replaceAll('+','%2B');
+ // } else {
+ // queryString += separator + queryParameter + '=' + encodeURIComponent(this.props[queryParameter]);
+ } else {
+ queryString += separator + queryParameter + '=' + this.props[queryParameter];
+ }
+ separator = '&';
+ }
+ }
+ return queryString;
+ }
+}
+export default ConnectedSystemsApiFilter;
diff --git a/source/core/consysapi/ObservationsCollection.js b/source/core/consysapi/ObservationsCollection.js
new file mode 100644
index 0000000000..f24f09d315
--- /dev/null
+++ b/source/core/consysapi/ObservationsCollection.js
@@ -0,0 +1,32 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2021 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import Collection from "./Collection";
+
+class ObservationsCollection extends Collection {
+ /**
+ *
+ */
+ constructor(url, filter, pageSize, parser) {
+ super(url,filter ,pageSize ,parser, 'arraybuffer');
+ }
+
+ async parseResponse(encodedResponse) {
+ return this.parser.parseDataBlock(encodedResponse,this.filter.props.format);
+ }
+}
+
+export default ObservationsCollection;
diff --git a/source/core/consysapi/command/Command.js b/source/core/consysapi/command/Command.js
new file mode 100644
index 0000000000..0d4ddf9e59
--- /dev/null
+++ b/source/core/consysapi/command/Command.js
@@ -0,0 +1,82 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import Collection from "../Collection";
+import API from "../routes.conf";
+import CommandFilter from "./CommandFilter";
+import SweCollectionDataParser from "../../parsers/consysapi/collection/SweCollectionDataParser";
+import ConSysApiResultControlStreamParser from "../../parsers/consysapi/observations/ConSysApiResult.controlstream.parser";
+
+class Command extends ConnectedSystemsApi {
+ /**
+ * @param {Object} properties - the properties of the object
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(properties, networkProperties) {
+ super(networkProperties); // network properties
+ this.properties = properties;
+ this.jsonParser = new SweCollectionDataParser(networkProperties);
+ this.sweParser = new ConSysApiResultControlStreamParser(this);
+ }
+
+ /**
+ * Get all status messages associated to a specific command
+ * route: /systems/{sysid}/controlstreams/{csid}/commands/{cmdid}/status
+ * @param {CommandFilter} [commandFilter== new CommandFilter()] - default Command filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - response as JSON
+ */
+ async searchStatus(commandFilter = new CommandFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.commands.status.replace('{sysid}',this.properties['system@id'])
+ .replace('{csid}', this.properties['controlstream@id'])
+ .replace('{cmdid}', this.properties.id),
+ commandFilter,
+ pageSize,
+ this.jsonParser
+ );
+ }
+
+ /**
+ * Stream all status messages associated to a specific command
+ * route: /systems/{sysid}/controlstreams/{csid}/commands/{cmdid}/status
+ * @param {CommandFilter} [commandFilter== new CommandFilter()] - default Command filter
+ * @param {Function} callback
+ */
+ streamStatus(commandFilter = new CommandFilter(), callback = function(){}) {
+ this.stream().onMessage = async (message) => {
+ const dataBlock = await this.sweParser.parseDataBlock(message,commandFilter.props.format);
+ callback(dataBlock);
+ };
+
+ this.stream().doRequest(
+ API.commands.status.replace('{sysid}',this.properties['system@id'])
+ .replace('{csid}', this.properties['controlstream@id'])
+ .replace('{cmdid}', this.properties.id),
+ commandFilter.toQueryString(),
+ 'arraybuffer'
+ );
+ }
+}
+
+export default Command;
diff --git a/source/core/consysapi/command/CommandFilter.js b/source/core/consysapi/command/CommandFilter.js
new file mode 100644
index 0000000000..3ddb972f97
--- /dev/null
+++ b/source/core/consysapi/command/CommandFilter.js
@@ -0,0 +1,52 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2021 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApiFilter from "../Filter";
+
+class CommandFilter extends ConnectedSystemsApiFilter {
+ /**
+ *
+ * @param {Object} properties - object properties
+ * @param {string[]} [properties.q=undefined] - Comma separated keywords used for full-text search
+ * @param {string[]} [properties.actuableProperty=undefined] - Comma separated list of actuable property URIs to filter command streams
+ * @param {string[]} [properties.select=undefined] - Comma separated list of properties to include or exclude from results (use "!" prefix to exclude)
+ * @param {string[]} [properties.foi=undefined] - Comma separated list of feature of interest IDs to get observations for
+ * @param {string} [properties.format='application/json'] - Mime type designating the format to use to encode the response.
+ * @param {string} [properties.issueTime=undefined] - ISO 8601 time range to filter commands on their issue time. When this parameter is omitted,
+ * no filtering on "issueTime" is applied.
+ * @param {string} [properties.executionTime=undefined] - ISO 8601 time range to filter commands on their execution time.
+ * When this parameter is omitted, no filtering on "executionTime" is applied
+ * @param {string} [properties.reportTime=undefined] - ISO 8601 time range to filter status messages on their report time. When this parameter is omitted,
+ * no filtering on "reportTime" is applied.
+ * @param {string[]} [properties.statusCode=undefined] - Comma separated list of status codes: PENDING, ACCEPTED, REJECTED, SCHEDULED, UPDATED, CANCELED, EXECUTING, FAILED, COMPLETED
+ */
+ constructor(properties) {
+ super({
+ q: undefined,
+ actuableProperty: undefined,
+ select: undefined,
+ foi: undefined,
+ format: 'application/json',
+ issueTime: undefined,
+ executionTime: undefined,
+ reportTime: undefined,
+ statusCode: undefined,
+ ...properties // merge defined properties
+ });
+ //TODO: assertions
+ }
+}
+export default CommandFilter;
diff --git a/source/core/consysapi/command/Commands.js b/source/core/consysapi/command/Commands.js
new file mode 100644
index 0000000000..2db48b3e38
--- /dev/null
+++ b/source/core/consysapi/command/Commands.js
@@ -0,0 +1,66 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConSysApiFetchCommandParser from "../../parsers/consysapi/collection/ConSysApiFetchCommand.parser";
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import Collection from "../Collection";
+import API from "../routes.conf";
+import CommandFilter from "./CommandFilter";
+
+class Commands extends ConnectedSystemsApi {
+ /**
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(networkProperties) {
+ super(networkProperties); // network properties
+ this.conSysApiCommandParser = new ConSysApiFetchCommandParser(networkProperties, undefined);
+ }
+
+ /**
+ * List or search all commands available through this API.
+ * @param {CommandFilter} [commandFilter=new CommandFilter()] - default Command filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A Collection of Command
+ */
+ async searchCommands(commandFilter = new CommandFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.commands.search,
+ commandFilter,
+ pageSize,
+ this.conSysApiCommandParser
+ );
+ }
+
+ /**
+ * Get a specific command resource by ID
+ * @param {string} commandId - ID of requested command
+ * @return {Promise} - The corresponding Command
+ */
+ async getCommandById(commandId) {
+ const apiUrl = API.commands.by_id.replace('{cmdid}',commandId);
+ const jsonData = await this.fetchAsJson(apiUrl, undefined);
+ return this.conSysApiCommandParser.parseData(jsonData);
+ }
+
+}
+
+export default Commands;
diff --git a/source/core/consysapi/controlstream/ControlStream.js b/source/core/consysapi/controlstream/ControlStream.js
new file mode 100644
index 0000000000..82c1c16bf6
--- /dev/null
+++ b/source/core/consysapi/controlstream/ControlStream.js
@@ -0,0 +1,179 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import CommandFilter from "../command/CommandFilter";
+import Collection from "../Collection";
+import API from "../routes.conf";
+import ControlStreamFilter from "./ControlStreamFilter";
+import ObservationsCollection from "../ObservationsCollection";
+import ConSysApiFetchCommandParser from "../../parsers/consysapi/collection/ConSysApiFetchCommand.parser";
+import ConSysApiResultCollectionControlStreamParser
+ from "../../parsers/consysapi/observations/ConSysApiResult.collection.controlstream.parser";
+import ConSysApiResultControlStreamParser from "../../parsers/consysapi/observations/ConSysApiResult.controlstream.parser";
+import ConSysApiControlStreamStatusParser from "../../parsers/consysapi/collection/ConSysApiControlStreamStatus.parser";
+
+class ControlStream extends ConnectedSystemsApi {
+ /**
+ * @param {Object} properties - the properties of the object
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(properties, networkProperties) {
+ super(networkProperties); // network properties
+ this.properties = properties;
+ this.commandParser = new ConSysApiFetchCommandParser(networkProperties, this.properties['system@id']);
+ this.conSysApiResultCollectionControlStreamParser = new ConSysApiResultCollectionControlStreamParser(this);
+ this.conSysApiResultControlStreamParser = new ConSysApiResultControlStreamParser(this);
+ this.conSysApiControlStreamStatusParser = new ConSysApiControlStreamStatusParser();
+ }
+
+ /**
+ * Get the list of commands received by a particular control interface
+ * route: /systems/{sysid}/controlstreams/{csid}/commands
+ * @param {CommandFilter} [commandFilter=new CommandFilter()] - default Command filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - result as JSON
+ */
+ async searchCommands(commandFilter = new CommandFilter(), pageSize= 10) {
+ return new ObservationsCollection(
+ this.baseUrl() + API.controlstreams.commands.replace('{sysid}',
+ this.properties['system@id']).replace('{csid}',this.properties.id),
+ commandFilter,
+ pageSize,
+ this.conSysApiResultCollectionControlStreamParser
+ );
+ }
+
+ /**
+ * Stream all commands received by a particular control interface
+ * route: /systems/{sysid}/controlstreams/{csid}/commands
+ * @param {ControlStreamFilter} [controlStreamFilter= new ControlStreamFilter()] - default ControlStreamStream filter
+ * @param {Function} callback - A callback to get observations
+ */
+ streamCommands(controlStreamFilter = new ControlStreamFilter(), callback = function(){}) {
+ this.stream().onMessage = async (message) => {
+ const dataBlock = await this.conSysApiResultControlStreamParser.parseDataBlock(message,controlStreamFilter.props.format);
+ callback(dataBlock);
+ };
+
+ this.stream().doRequest(
+ API.controlstreams.commands.replace('{sysid}',this.properties['system@id']).replace('{csid}',this.properties.id),
+ controlFilter.toQueryString(),
+ 'arraybuffer'
+ );
+ }
+
+ /**
+ * Get a specific command resource by ID.
+ * route: /systems/{sysid}/controlstreams/{csid}/commands/{cmdid}
+ * @param {String} commandId - the ID of the Command resource
+ * @param {CommandFilter} [commandFilter=new CommandFilter()] - default Command filter
+ * @returns {Promise} - The corresponding Command
+ */
+ async getCommandById(commandId,commandFilter = new CommandFilter()) {
+ const apiUrl = API.controlstreams.command_by_id
+ .replace('{sysid}',this.properties['system@id'])
+ .replace('{csid}', this.properties.id)
+ .replace('{cmdid}', commandId);
+ const queryString = commandFilter.toQueryString(['select', 'obsFormat']); //TODO: check useless obsFormat
+ const jsonData = await this.fetchAsJson(apiUrl, queryString);
+ return this.commandParser.parseData(jsonData);
+ }
+
+ /**
+ * Send a new command to this control interface
+ * route: /systems/{sysid}/controlstreams/{csid}/commands
+ * @param {JSON} jsonPayload - the JSON payload
+ * @param {CommandFilter} [commandFilter=new CommandFilter()] - default Command filter specifying the 'sysid' and 'csid'
+ */
+ postCommand(jsonPayload, commandFilter = new CommandFilter()) {
+ const apiUrl = API.controlstreams.commands
+ .replace('{sysid}',this.properties['system@id'])
+ .replace('{csid}', this.properties.id);
+ this.postAsJson(apiUrl, jsonPayload);
+ }
+
+ /**
+ * Send a new command to this control interface using streaming protocol such like WS or MQTT
+ * route: /systems/{sysid}/controlstreams/{csid}/commands
+ * @param {JSON} jsonPayload - the JSON payload
+ * @param {CommandFilter} [commandFilter=new CommandFilter()] - default Command filter specifying the 'sysid' and 'csid'
+ */
+ publishCommand(payload, commandFilter = new CommandFilter()) {
+ this.stream().publishRequest(
+ API.controlstreams.commands
+ .replace('{sysid}',this.properties['system@id'])
+ .replace('{csid}', this.properties.id),
+ payload
+ );
+ }
+
+ /**
+ * Get all status messages sent by this control interface
+ * route: /systems/{sysid}/controlstreams/{csid}/status
+ * @param {ControlStreamFilter} [controlStreamFilter=new ControlStreamFilter()] - default ControlStream filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A Collection of JSON
+ */
+ async searchStatus(controlStreamFilter = new ControlStreamFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.controlstreams.status.replace('{sysid}',this.properties['system@id']).replace('{csid}',
+ this.properties.id),
+ controlStreamFilter,
+ pageSize,
+ this.conSysApiControlStreamStatusParser
+ );
+ }
+
+ /**
+ * Stream all status messages sent by this control interface
+ * route: /systems/{sysid}/controlstreams/{csid}/status
+ * @param {ControlStreamFilter} [controlStreamFilter= new ControlStreamFilter()] - default ControlStream filter
+ * @param {Function} callback - A callback to get observations
+ */
+ streamStatus(controlStreamFilter = new ControlStreamFilter(), callback = function(){}) {
+ this.stream().onMessage = async (message) => {
+ const dataBlock = await this.conSysApiControlStreamStatusParser.parseData(message, 'arraybuffer');
+ callback(dataBlock);
+ };
+
+ this.stream().doRequest(
+ API.controlstreams.status.replace('{sysid}',this.properties['system@id']).replace('{csid}',this.properties.id),
+ controlStreamFilter.toQueryString(),
+ 'arraybuffer'
+ );
+ }
+
+ /**
+ * Get the detailed schema of command messages in a command stream
+ * route: /systems/{sysid}/controlstreams/{csid}/schema
+ * @param {ControlStreamFilter} [controlStreamFilter= new ControlStreamFilter()] - default ControlStream filter, using 'commandFormat' to select response format
+ * @returns {Promise} - The schema as JSON
+ */
+ async getSchema(controlStreamFilter = new ControlStreamFilter()) {
+ const apiUrl = API.controlstreams.schema.replace('{sysid}',this.properties['system@id']).replace('{csid}',this.properties.id);
+ const queryString = controlStreamFilter.toQueryString(['select', 'commandFormat']);
+ return this.fetchAsJson(apiUrl, queryString);
+ }
+}
+
+export default ControlStream;
diff --git a/source/core/consysapi/controlstream/ControlStreamFilter.js b/source/core/consysapi/controlstream/ControlStreamFilter.js
new file mode 100644
index 0000000000..d2e5f3c141
--- /dev/null
+++ b/source/core/consysapi/controlstream/ControlStreamFilter.js
@@ -0,0 +1,45 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApiFilter from "../Filter";
+
+class ControlStreamFilter extends ConnectedSystemsApiFilter {
+ /**
+ *
+ * @param {Object} properties - object properties
+ * @param {string[]} [properties.q=undefined] - Comma separated keywords used for full-text search
+ * @param {string[]} [properties.actuableProperty=undefined] - Comma separated list of actuable property URIs to filter command streams
+ * @param {string[]} [properties.select=undefined] - Comma separated list of properties to include or exclude from results (use "!" prefix to exclude)
+ * @param {string[]} [properties.foi=undefined] - Comma separated list of feature of interest IDs to get observations for
+ * @param {string} [properties.format='application/json'] - Mime type designating the format to use to encode the response.
+ * @param {string} [properties.issueTime=undefined] - ISO 8601 time range to filter commands on their issue time. When this parameter is omitted,
+ * no filtering on "issueTime" is applied.
+ */
+ constructor(properties) {
+ super({
+ q: undefined,
+ actuableProperty: undefined,
+ observedProperty: undefined,
+ issueTime: undefined,
+ select: undefined,
+ foi: undefined,
+ format: 'application/json',
+ ...properties // merge defined properties
+ });
+ //TODO: assertions
+ }
+}
+export default ControlStreamFilter;
diff --git a/source/core/consysapi/controlstream/ControlStreams.js b/source/core/consysapi/controlstream/ControlStreams.js
new file mode 100644
index 0000000000..8ff8a7249d
--- /dev/null
+++ b/source/core/consysapi/controlstream/ControlStreams.js
@@ -0,0 +1,68 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConSysApiFetchControlStreamParser from "../../parsers/consysapi/collection/ConSysApiFetchControlStream.parser";
+import Collection from "../Collection";
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import API from "../routes.conf";
+import ControlStreamFilter from "./ControlStreamFilter";
+
+class ControlStreams extends ConnectedSystemsApi {
+ /**
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(networkProperties) {
+ super(networkProperties); // network properties
+ this.conSysApiControlStreamParser = new ConSysApiFetchControlStreamParser(networkProperties);
+ }
+
+ /**
+ * List or search all controlstreams available through this API.
+ * @param {ControlStreamFilter} [controlStreamFilter=new ControlStreamFilter()] - default ControlStream filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A Collection of ControlStream
+ */
+ async searchControlStreams(controlStreamFilter = new ControlStreamFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.controlstreams.search,
+ controlStreamFilter,
+ pageSize,
+ this.conSysApiControlStreamParser
+ );
+ }
+
+ /**
+ * Get a specific controlstream resource by ID
+ * @param {string} controlstreamId - ID of requested controlstream
+ * @param {ControlStreamFilter} [controlStreamFilter=new ControlStreamFilter()] - default controlstream filter
+ * @return {Promise} - The corresponding ControlStream
+ */
+ async getControlStreamById(controlstreamId, controlStreamFilter = new ControlStreamFilter()) {
+ const apiUrl = API.controlstreams.by_id.replace('{csid}',controlstreamId);
+ const queryString = controlStreamFilter.toQueryString(['select', 'format']);
+ const jsonData = await this.fetchAsJson(apiUrl, queryString);
+ return this.conSysApiControlStreamParser.parseData(jsonData);
+ }
+
+}
+
+export default ControlStreams;
diff --git a/source/core/consysapi/datastream/DataStream.js b/source/core/consysapi/datastream/DataStream.js
new file mode 100644
index 0000000000..36ff3af4d4
--- /dev/null
+++ b/source/core/consysapi/datastream/DataStream.js
@@ -0,0 +1,93 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import ObservationFilter from "../observation/ObservationFilter";
+import API from "../routes.conf";
+import DataStreamFilter from "./DataStreamFilter";
+import ObservationsCollection from "../ObservationsCollection";
+import ConSysApiResultParser from "../../parsers/consysapi/observations/ConSysApiResult.datastream.parser";
+import ConSysApiResultCollectionDatastreamParser
+ from "../../parsers/consysapi/observations/ConSysApiResult.collection.datastream.parser";
+
+class DataStream extends ConnectedSystemsApi {
+ /**
+ * @param {Object} properties - the properties of the object
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(properties, networkProperties) {
+ super(networkProperties); // network properties
+ this.properties = properties;
+ this.conSysApiResultParser = new ConSysApiResultParser(this);
+ this.conSysApiResultCollectionDatastreamParser = new ConSysApiResultCollectionDatastreamParser(this);
+ }
+
+ /**
+ * Retrieve historical observations from a datastream
+ * route: /datastreams/{id}/observations
+ * @param {ObservationFilter} [observationFilter=new ObservationFilter()] - default ObservationFilter
+ * @param {Function} callback - A callback to get observations
+ */
+ streamObservations(observationFilter = new ObservationFilter(), callback = function(){}) {
+ this.stream().onMessage = async (message) => {
+ const dataBlock = await this.conSysApiResultParser.parseDataBlock(message,observationFilter.props.format);
+ callback(dataBlock);
+ }
+
+ return this.stream().doRequest(
+ API.datastreams.observations.replace('{id}',this.properties.id),
+ observationFilter.toQueryString([], ['phenomenonTime']),
+ 'arraybuffer'
+ );
+ }
+
+ /**
+ * Retrieve historical observations from a datastream
+ * route: /datastreams/{id}/observations
+ * @param {ObservationFilter} [observationFilter=new ObservationFilter()] - default ObservationFilter
+ * @param {Number} [pageSize=10] - default page size
+ * @param {DataSourceParser} [parser=new ConSysApiResultParser()] - default observations parser
+ * @return {Collection} - result observations as JSON
+ */
+ async searchObservations(observationFilter = new ObservationFilter(), pageSize= 10, parser = this.conSysApiResultParser) {
+ return new ObservationsCollection(
+ this.baseUrl() + API.datastreams.observations.replace('{id}',this.properties.id),
+ observationFilter,
+ pageSize,
+ this.conSysApiResultCollectionDatastreamParser
+ );
+ }
+
+ /**
+ * Get the schema of a datastream
+ * route: /datastreams/{id}/schema
+ * @param {DataStreamFilter} [dataStreamFilter=new DataStreamFilter()] - default datastream filter
+ * @return {Promise} - the JSON schema
+ */
+ async getSchema(dataStreamFilter = new DataStreamFilter()) {
+ const apiUrl = API.datastreams.schema.replace('{id}',this.properties.id);
+ const queryString = dataStreamFilter.toQueryString(['select', 'obsFormat']);
+ return this.fetchAsJson(apiUrl, queryString);
+ }
+}
+
+export default DataStream;
diff --git a/source/core/consysapi/datastream/DataStreamFilter.js b/source/core/consysapi/datastream/DataStreamFilter.js
new file mode 100644
index 0000000000..29bc7ec4c8
--- /dev/null
+++ b/source/core/consysapi/datastream/DataStreamFilter.js
@@ -0,0 +1,55 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApiFilter from "../Filter";
+
+class DataStreamFilter extends ConnectedSystemsApiFilter {
+ /**
+ *
+ * @param {Object} properties - object properties
+ * @param {string[]} [properties.q=undefined] - Comma separated keywords used for full-text search
+ * @param {number[]} [properties.bbox=undefined] - BBOX to filter resources on their location
+ * @param {string} [properties.location=undefined] - WKT geometry and operator to filter resources on their location or geometry
+ * @param {string[]} [properties.observedProperty=undefined] - Comma separated list of observed property URIs to get observations for
+ * @param {string[]} [properties.foi=undefined] - Comma separated list of feature of interest IDs to get observations for
+ * @param {string[]} [properties.select=undefined] - Comma separated list of properties to include or exclude from results (use "!" prefix to exclude)
+ * @param {string} [properties.format='application/json'] - Mime type designating the format to use to encode the response.
+ * @param {string} [properties.validTime=undefined] - validTime - ISO 8601 time range to filter resources on their validity time.
+ * When this parameter is omitted, the implicit value is "now", except for "history" collections where the absence of this parameter means no filtering is applied.
+ * @param {string} [properties.resultTime=undefined] - validTime - ISO 8601 time range to filter observations on their result time.
+ * When this parameter is omitted, no filtering on "resultTime" is applied.
+ * @param {string} [properties.phenomenonTime=undefined] - validTime - ISO 8601 time range to filter observations on the phenomenon time.
+ * When this parameter is omitted, no filtering on "phenomenonTime" is applied.
+ */
+ constructor(properties) {
+ super({
+ q: undefined,
+ bbox: undefined,
+ location: undefined,
+ observedProperty: undefined,
+ foi: undefined,
+ select: undefined,
+ format: 'application/json',
+ obsFormat: 'application/om+json',
+ validTime: undefined,
+ phenomenonTime: undefined,
+ resultTime: undefined,
+ ...properties // merge defined properties
+ });
+ //TODO: assertions
+ }
+}
+export default DataStreamFilter;
diff --git a/source/core/consysapi/datastream/DataStreams.js b/source/core/consysapi/datastream/DataStreams.js
new file mode 100644
index 0000000000..14108f25a6
--- /dev/null
+++ b/source/core/consysapi/datastream/DataStreams.js
@@ -0,0 +1,65 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import Collection from "../Collection";
+import DataStreamFilter from "./DataStreamFilter";
+import API from "../routes.conf";
+import ConSysApiDataStreamParser from "../../parsers/consysapi/collection/ConSysApiDataStream.parser";
+
+class DataStreams extends ConnectedSystemsApi {
+ /**
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(networkProperties) {
+ super(networkProperties);
+ this.conSysApiDataStreamParser = new ConSysApiDataStreamParser(networkProperties);
+ }
+
+ /**
+ * List or search all datastreams available through this API.
+ * @param {DataStreamFilter} [dataStreamFilter=new DataStreamFilter()] - default DataStream filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A Collection of DataStream
+ */
+ async searchDataStreams(dataStreamFilter = new DataStreamFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.datastreams.search,
+ dataStreamFilter,
+ pageSize,
+ this.conSysApiDataStreamParser
+ );
+ }
+
+ /**
+ * Get a specific datastream resource by ID
+ * @param {DataStreamFilter} [dataStreamFilter=new DataStreamFilter()] - default datastream filter
+ * @return {Promise} - The corresponding DataStream
+ */
+ async getDataStreamById(datastreamId,dataStreamFilter = new DataStreamFilter()) {
+ const apiUrl = API.datastreams.by_id.replace('{id}',datastreamId);
+ const queryString = dataStreamFilter.toQueryString(['select','format']);
+ const jsonData = await this.fetchAsJson(apiUrl, queryString);
+ return this.conSysApiDataStreamParser.parseData(jsonData);
+ }
+}
+export default DataStreams;
diff --git a/source/core/consysapi/event/Event.js b/source/core/consysapi/event/Event.js
new file mode 100644
index 0000000000..4534184e09
--- /dev/null
+++ b/source/core/consysapi/event/Event.js
@@ -0,0 +1,36 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+
+class Event extends ConnectedSystemsApi {
+ /**
+ * @param {Object} properties - the properties of the object
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(properties, networkProperties) {
+ super(networkProperties); // network properties
+ this.properties = properties;
+ }
+}
+
+export default Event;
diff --git a/source/core/consysapi/event/EventFilter.js b/source/core/consysapi/event/EventFilter.js
new file mode 100644
index 0000000000..dfcc123fee
--- /dev/null
+++ b/source/core/consysapi/event/EventFilter.js
@@ -0,0 +1,42 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApiFilter from "../Filter";
+
+class EventFilter extends ConnectedSystemsApiFilter {
+ /**
+ *
+ * @param {Object} properties - object properties
+ * @param {string[]} [properties.q=undefined] - Comma separated keywords used for full-text search
+ * @param {string[]} [properties.select=undefined] - Comma separated list of properties to include or exclude from results (use "!" prefix to exclude)
+ * @param {string} [properties.format='application/json'] - Mime type designating the format to use to encode the response.
+ * @param {string} [properties.eventTime=undefined] - ISO 8601 time range to filter events on their timestamp. When this parameter
+ * is omitted, no filtering on "eventTime" is applied.
+ * @param {string} [properties.eventType=undefined] - Comma separated list of event type URIs to filter system events.
+ */
+ constructor(properties) {
+ super({
+ q: undefined,
+ eventTime: undefined,
+ eventType: undefined,
+ select: undefined,
+ format: 'application/json',
+ ...properties // merge defined properties
+ });
+ //TODO: assertions
+ }
+}
+export default EventFilter;
diff --git a/source/core/consysapi/event/Events.js b/source/core/consysapi/event/Events.js
new file mode 100644
index 0000000000..7c6da6dea3
--- /dev/null
+++ b/source/core/consysapi/event/Events.js
@@ -0,0 +1,34 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+
+class Events extends ConnectedSystemsApi {
+ /**
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(networkProperties) {
+ super(networkProperties);
+ }
+}
+
+export default Events;
diff --git a/source/core/consysapi/history/SystemHistoryFilter.js b/source/core/consysapi/history/SystemHistoryFilter.js
new file mode 100644
index 0000000000..847891217f
--- /dev/null
+++ b/source/core/consysapi/history/SystemHistoryFilter.js
@@ -0,0 +1,38 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApiFilter from "../Filter";
+
+class SystemHistoryFilter extends ConnectedSystemsApiFilter {
+ /**
+ *
+ * @param {Object} properties - object properties
+ * @param {string[]} [properties.select=undefined] - Comma separated list of properties to include or exclude from results (use "!" prefix to exclude)
+ * @param {string} [properties.format='application/json'] - Mime type designating the format to use to encode the response.
+ * @param {string} [properties.validTime=undefined] - ISO 8601 time range to filter resources on their validity time.
+ * When this parameter is omitted, the implicit value is "now", except for "history" collections where the absence of this parameter means no filtering is applied.
+ */
+ constructor(properties) {
+ super({
+ select: undefined,
+ validTime: undefined,
+ format: 'application/json',
+ ...properties // merge defined properties
+ });
+ //TODO: assertions
+ }
+}
+export default SystemHistoryFilter;
diff --git a/source/core/consysapi/observation/Observation.js b/source/core/consysapi/observation/Observation.js
new file mode 100644
index 0000000000..460a660b06
--- /dev/null
+++ b/source/core/consysapi/observation/Observation.js
@@ -0,0 +1,37 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+
+class Observation extends ConnectedSystemsApi {
+ /**
+ * @param {Object} properties - the properties of the object
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(properties, networkProperties) {
+ super(networkProperties); // network properties
+ this.properties = properties;
+ }
+
+}
+
+export default Observation;
diff --git a/source/core/consysapi/observation/ObservationFilter.js b/source/core/consysapi/observation/ObservationFilter.js
new file mode 100644
index 0000000000..106b7522e2
--- /dev/null
+++ b/source/core/consysapi/observation/ObservationFilter.js
@@ -0,0 +1,45 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+import ConnectedSystemsApiFilter from "../Filter";
+
+class ObservationFilter extends ConnectedSystemsApiFilter {
+ /**
+ *
+ * @param {Object} properties - object properties
+ * @param {any} [properties.phenomenonTime='now'] - time range <00:00:00T00:00:00Z/00:00:00T00:00:00Z> | 'now' | 'latest'
+ * @param {any} [properties.resultTime='now'] - time range <00:00:00T00:00:00Z/00:00:00T00:00:00Z> | 'latest'
+ * @param {string[]} [properties.foi=undefined] - Comma separated list of feature of interest IDs to get observations for
+ * @param {string[]} [properties.select=undefined] - Comma separated list of properties to include or exclude from results (use "!" prefix to exclude)
+ * @param {number[]} [properties.bbox=undefined] - BBOX to filter resources on their location
+ * @param {string} [properties.location=undefined] - WKT geometry and operator to filter resources on their location or geometry
+ * @param {string} [properties.format='application/json'] - Mime type designating the format to use to encode the response.
+ * @param {string} [properties.replaySpeed=undefined] - Mime type designating the format to use to encode the response.
+ */
+ constructor(properties) {
+ super({
+ phenomenonTime: undefined,
+ resultTime: undefined,
+ foi: undefined,
+ select: undefined,
+ bbox: undefined,
+ location: undefined,
+ format: 'application/om+json',
+ replaySpeed: undefined,
+ ...properties // merge defined properties
+ });
+ }
+}
+export default ObservationFilter;
diff --git a/source/core/consysapi/observation/Observations.js b/source/core/consysapi/observation/Observations.js
new file mode 100644
index 0000000000..04ffe7a002
--- /dev/null
+++ b/source/core/consysapi/observation/Observations.js
@@ -0,0 +1,59 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import Collection from "../Collection";
+import ConSysApiFetchObservationParser from "../../parsers/consysapi/collection/ConSysApiFetchObservation.parser";
+import ObservationFilter from "./ObservationFilter";
+import API from "../routes.conf";
+
+class Observations extends ConnectedSystemsApi {
+ /**
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(networkProperties) {
+ super(networkProperties);
+ this.conSysApiFetchObservationParser = new ConSysApiFetchObservationParser(networkProperties);
+ }
+
+ /**
+ * List or search all observations available through this API.
+ * @param {ObservationFilter} [observationFilter=new ObservationFilter()] - default observation filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A Collection of Observation
+ */
+ async searchObservations(observationFilter = new ObservationFilter(), pageSize= 10) {
+ return new Collection(this.baseUrl() + API.observations.search, observationFilter, pageSize,this.conSysApiFetchObservationParser);
+ }
+
+ /**
+ * Get a specific observation resource by ID
+ * @param {string} observationId ID of requested observation
+ * @return {Promise} - corresponding observation
+ */
+ async getObservationById(observationId) {
+ const apiUrl = API.observations.by_id.replace('{id}', observationId);
+ const jsonData = await this.fetchAsJson(apiUrl, undefined);
+ return this.conSysApiFetchObservationParser.parseData(jsonData);
+ }
+}
+export default Observations;
diff --git a/source/core/consysapi/routes.conf.js b/source/core/consysapi/routes.conf.js
new file mode 100644
index 0000000000..46268219b0
--- /dev/null
+++ b/source/core/consysapi/routes.conf.js
@@ -0,0 +1,61 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+const API = {
+ datastreams: {
+ search: '/datastreams',
+ by_id: '/datastreams/{id}',
+ observations: '/datastreams/{id}/observations',
+ schema: '/datastreams/{id}/schema'
+ },
+ systems: {
+ search: '/systems',
+ by_id: '/systems/{sysid}',
+ details: '/systems/{sysid}/details',
+ samplingFeatures: '/systems/{sysid}/samplingFeatures',
+ members: '/systems/{sysid}/members',
+ subsystems: '/systems/{sysid}/subsystems',
+ datastreams: '/systems/{sysid}/datastreams',
+ history_ver: '/systems/{sysid}/history/{ver}',
+ controlstream_by_id: '/systems/{sysid}/controlstreams/{csid}',
+ controlstreams: '/systems/{sysid}/controlstreams',
+ events: '/systems/{sysid}/events',
+ history: '/systems/{sysid}/history',
+ },
+ controlstreams: {
+ search: '/controlstreams',
+ by_id: '/controlstreams/{csid}',
+ commands: '/systems/{sysid}/controlstreams/{csid}/commands',
+ command_by_id: '/systems/{sysid}/controlstreams/{csid}/commands/{cmdid}',
+ status: '/systems/{sysid}/controlstreams/{csid}/status',
+ schema: '/systems/{sysid}/controlstreams/{csid}/schema'
+ },
+ commands: {
+ search: '/commands',
+ by_id: '/commands/{cmdid}',
+ status: '/systems/{sysid}/controlstreams/{csid}/commands/{cmdid}/status'
+ },
+ observations: {
+ search: '/observations',
+ by_id: '/observations/{id}',
+ },
+ samplingFeatures: {
+ search: '/samplingFeatures',
+ by_id: '/samplingFeatures/{id}',
+ },
+};
+
+export default API;
diff --git a/source/core/consysapi/samplingfeature/SamplingFeature.js b/source/core/consysapi/samplingfeature/SamplingFeature.js
new file mode 100644
index 0000000000..4add902243
--- /dev/null
+++ b/source/core/consysapi/samplingfeature/SamplingFeature.js
@@ -0,0 +1,36 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+
+class SamplingFeature extends ConnectedSystemsApi {
+ /**
+ * @param {Object} properties - the properties of the object
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(properties, networkProperties) {
+ super(networkProperties); // network properties
+ this.properties = properties;
+ }
+}
+
+export default SamplingFeature;
diff --git a/source/core/consysapi/samplingfeature/SamplingFeatureFilter.js b/source/core/consysapi/samplingfeature/SamplingFeatureFilter.js
new file mode 100644
index 0000000000..ab2f2148ac
--- /dev/null
+++ b/source/core/consysapi/samplingfeature/SamplingFeatureFilter.js
@@ -0,0 +1,48 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApiFilter from "../Filter";
+
+class SamplingFeatureFilter extends ConnectedSystemsApiFilter {
+ /**
+ *
+ * @param {Object} properties - object properties
+ * @param {string[]} [properties.q=undefined] - Comma separated keywords used for full-text search
+ * @param {number[]} [properties.bbox=undefined] - BBOX to filter resources on their location
+ * @param {string} [properties.location=undefined] - WKT geometry and operator to filter resources on their location or geometry
+ * @param {string} [properties.validTime=undefined] - validTime - ISO 8601 time range to filter resources on their validity time.
+ * When this parameter is omitted, the implicit value is "now", except for "history" collections where the absence of this parameter means no filtering is applied.
+ * @param {string[]} [properties.parent=undefined] - Comma separated list of parent resource IDs to restrict the search to or "*" to include nested resources at any level
+ * @param {string[]} [properties.select=undefined] - Comma separated list of properties to include or exclude from results (use "!" prefix to exclude)
+ * @param {string} [properties.format='application/json'] - Mime type designating the format to use to encode the response.
+ * @param {String[]} [properties.foi=undefined] Comma separated list of feature of interest IDs to get observations for.
+ */
+ constructor(properties) {
+ super({
+ q: undefined,
+ bbox: undefined,
+ location: undefined,
+ validTime: undefined,
+ parent: undefined,
+ select: undefined,
+ foi: undefined,
+ format: 'application/json',
+ ...properties // merge defined properties
+ });
+ //TODO: assertions
+ }
+}
+export default SamplingFeatureFilter;
diff --git a/source/core/consysapi/samplingfeature/SamplingFeatures.js b/source/core/consysapi/samplingfeature/SamplingFeatures.js
new file mode 100644
index 0000000000..3df34eae2e
--- /dev/null
+++ b/source/core/consysapi/samplingfeature/SamplingFeatures.js
@@ -0,0 +1,65 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import SamplingFeatureFilter from "./SamplingFeatureFilter";
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import Collection from "../Collection";
+import API from "../routes.conf";
+import ConSysApiFetchSamplingFeatureParser from "../../parsers/consysapi/collection/ConSysApiFetchSamplingFeature.parser";
+
+class SamplingFeatures extends ConnectedSystemsApi {
+ /**
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(networkProperties) {
+ super(networkProperties);
+ this.conSysApiFetchSamplingFeatureParser = new ConSysApiFetchSamplingFeatureParser(networkProperties);
+ }
+
+ /**
+ * List or search all sampled and sampling features available through this API. By default, only top level features
+ * and collections are listed (i.e. nested members of feature collections are ommitted) unless the "parent" query parameter is set.
+ * route: /samplingFeatures
+ * @param {SamplingFeatureFilter} [samplingFeatureFilter=new SamplingFeatureFilter()] - default SamplingFeature filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A Collection of SamplingFeatures
+ */
+ async searchSamplingFeatures(samplingFeatureFilter = new SamplingFeatureFilter(), pageSize= 10) {
+ return new Collection(this.baseUrl() + API.samplingFeatures.search, samplingFeatureFilter, pageSize,this.conSysApiFetchSamplingFeatureParser);
+ }
+
+ /**
+ * Get a specific feature resource by ID. Note that this will return the description of the feature valid at the current time.
+ * To get the description valid for a past (or future) time, use the "history" sub-collection.
+ * route: /samplingFeatures/{id}
+ * @param {String} fId - The ID of the SamplingFeature resource
+ * @param {SamplingFeatureFilter} [samplingFeatureFilter=new SamplingFeatureFilter()] - default SamplingFeature filter
+ * @return {Promise} - The corresponding SamplingFeatures as JSON
+ */
+ async getSamplingFeatureById(fId,samplingFeatureFilter = new SamplingFeatureFilter()) {
+ const apiUrl = API.samplingFeatures.by_id.replace('{id}',fId);
+ const queryString = samplingFeatureFilter.toQueryString(['select', 'format']);
+ const jsonData = await this.fetchAsJson(apiUrl, queryString);
+ return this.conSysApiFetchSamplingFeatureParser.parseData(jsonData);
+ }
+}
+export default SamplingFeatures;
diff --git a/source/core/consysapi/system/System.js b/source/core/consysapi/system/System.js
new file mode 100644
index 0000000000..e50180ad5b
--- /dev/null
+++ b/source/core/consysapi/system/System.js
@@ -0,0 +1,192 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import SystemFilter from "./SystemFilter";
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import Collection from "../Collection";
+import DataStreamFilter from "../datastream/DataStreamFilter";
+import SamplingFeatureFilter from "../samplingfeature/SamplingFeatureFilter";
+import API from "../routes.conf";
+import ControlStreamFilter from "../controlstream/ControlStreamFilter";
+import EventFilter from "../event/EventFilter";
+import SystemHistoryFilter from "../history/SystemHistoryFilter";
+import ConSysApiFetchSystemParser from "../../parsers/consysapi/collection/ConSysApiFetchSystem.parser";
+import ConSysApiDataStreamParser from "../../parsers/consysapi/collection/ConSysApiDataStream.parser";
+import ConSysApiFetchSamplingFeatureParser from "../../parsers/consysapi/collection/ConSysApiFetchSamplingFeature.parser";
+import ConSysApiFetchEventParser from "../../parsers/consysapi/collection/ConSysApiFetchEvent.parser";
+import ConSysApiFetchControlStreamParser from "../../parsers/consysapi/collection/ConSysApiFetchControlStream.parser";
+
+class System extends ConnectedSystemsApi {
+ /**
+ * @param {Object} properties - the properties of the object
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(properties, networkProperties) {
+ super(networkProperties); // network properties
+ this.properties = properties;
+ this.conSysApiFetchSystemParser = new ConSysApiFetchSystemParser(networkProperties);
+ this.conSysApiDataStreamParser = new ConSysApiDataStreamParser(networkProperties);
+ this.conSysApiFetchSamplingFeatureParser = new ConSysApiFetchSamplingFeatureParser(networkProperties);
+ this.conSysApiFetchEventParser = new ConSysApiFetchEventParser(networkProperties);
+ this.conSysApiFetchControlStreamParser = new ConSysApiFetchControlStreamParser(networkProperties);
+ }
+
+ /**
+ * Get the latest specsheet of a system
+ * route: /systems/{sysid}/details
+ * @param {SystemFilter} [systemFilter=new SystemFilter()] - the system filter
+ * @return {Promise} - SensorlML Description
+ */
+ async getDetails(systemFilter = new SystemFilter()) {
+ const apiUrl = API.systems.details.replace('{sysid}',this.properties.id);
+ const queryString = systemFilter.toQueryString(['select', 'format']);
+ return this.fetchAsJson(apiUrl, queryString);
+ }
+
+ /**
+ * Search for subsystems
+ * route: /systems/{sysid}/subsystems
+ * @param {SystemFilter} [systemFilter= new SystemFilter()] - the system filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A collection of System
+ */
+ async searchSubSystems(systemFilter = new SystemFilter(), pageSize = 10) {
+ return new Collection(
+ this.baseUrl() + API.systems.subsystems.replace('{sysid}',this.properties.id),
+ systemFilter,
+ pageSize,
+ this.conSysApiFetchSystemParser
+ );
+ }
+
+ /**
+ * List or search output datastreams of the selected system. Individual datastreams can be retrieved by ID directly on the root "datastreams" collection.
+ * route: /systems/{sysid}/datastreams
+ * @param {DataStreamFilter} [dataStreamFilter=new DataStreamFilter()] - default DataStream filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A collection of DataStream
+ */
+ async searchDataStreams(dataStreamFilter = new DataStreamFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.systems.datastreams.replace('{sysid}',this.properties.id),
+ dataStreamFilter,
+ pageSize,
+ this.conSysApiDataStreamParser
+ );
+ }
+
+ /**
+ * List or search sampling features of a system. Individual features can be retrieved by ID directly on the root "samplingFeatures" collection
+ * route: /systems/{sysid}/samplingFeatures
+ * @param {SamplingFeatureFilter} [samplingFeatureFilter=new SamplingFeatureFilter()] - FOI filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A collection of SamplingFeature
+ */
+ async searchSamplingFeatures(samplingFeatureFilter = new SamplingFeatureFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.systems.samplingFeatures.replace('{sysid}',this.properties.id),
+ samplingFeatureFilter,
+ pageSize,
+ this.conSysApiFetchSamplingFeatureParser
+ );
+ }
+
+ /**
+ * Get a list of control interfaces of a system
+ * route: /systems/{sysid}/controlstreams
+ * @param {ControlStreamFilter} [controlStreamFilter=new ControlStreamFilter()] - the controlstream filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A collection of ControlStream
+ */
+ async searchControlStreams(controlStreamFilter = new ControlStreamFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.systems.controlstreams.replace('{sysid}',this.properties.id),
+ controlStreamFilter,
+ pageSize,
+ this.conSysApiFetchControlStreamParser
+ );
+ }
+
+ /**
+ * Get a specific control interface description by ID
+ * route: /systems/{sysid}/controlstreams/{dsid}
+ * @param {String} controlstreamId - The ID of the control stream
+ * @param {ControlStreamFilter} [controlStreamFilter= new ControlStreamFilter()] - the controlstream filter
+ * @return {ControlStream} - The corresponding ControlStream
+ */
+ async getControlStreamById(controlstreamId,controlStreamFilter = new ControlStreamFilter()) {
+ const apiUrl = API.systems.controlstream_by_id.replace('{sysid}',this.properties.id).replace('{csid}', controlstreamId);
+ const queryString = controlStreamFilter.toQueryString(['select', 'format']);
+ const jsonData = await this.fetchAsJson(apiUrl, queryString);
+ return this.conSysApiFetchControlStreamParser.parseData(jsonData);
+ }
+
+ /**
+ * List or search events related to a system (e.g. maintenance events, contact change, etc.)
+ * route: /systems/{sysid}/events
+ * @param {EventFilter} [eventFilter= new EventFilter()] - the event filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A collection of Event
+ */
+ async searchEvents(eventFilter = new EventFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.systems.events.replace('{sysid}',this.properties.id),
+ eventFilter,
+ pageSize,
+ this.conSysApiFetchEventParser
+ );
+ }
+
+ /**
+ * List or search for historical descriptions of a specific system (ordered by time of validity)
+ * route: /systems/{sysid}/history
+ * @param {SystemHistoryFilter} [systemHistoryFilter= new SystemHistoryFilter()] - the history filer
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A collection of System
+ */
+ async searchHistory(systemHistoryFilter = new SystemHistoryFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.systems.history.replace('{sysid}',this.properties.id),
+ systemHistoryFilter,
+ pageSize,
+ this.conSysApiFetchSystemParser
+ );
+ }
+
+ /**
+ * List or search members of a system group. Individual members can be retrieved by ID directly on the root "systems" collection
+ * route: /systems/{sysid}/members
+ * @param {SystemFilter} [systemFilter=new SystemFilter()] - the system filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A collection of System
+ */
+ async searchMembers(systemFilter = new SystemFilter(), pageSize= 10) {
+ return new Collection(
+ this.baseUrl() + API.systems.members.replace('{sysid}',this.properties.id),
+ systemFilter,
+ pageSize,
+ this.conSysApiFetchSystemParser
+ );
+ }
+}
+
+export default System;
diff --git a/source/core/consysapi/system/SystemFilter.js b/source/core/consysapi/system/SystemFilter.js
new file mode 100644
index 0000000000..7fbb25d724
--- /dev/null
+++ b/source/core/consysapi/system/SystemFilter.js
@@ -0,0 +1,48 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApiFilter from "../Filter";
+
+class SystemFilter extends ConnectedSystemsApiFilter {
+ /**
+ *
+ * @param {Object} properties - object properties
+ * @param {string[]} [properties.q=undefined] - Comma separated keywords used for full-text search
+ * @param {number[]} [properties.bbox=undefined] - BBOX to filter resources on their location
+ * @param {string} [properties.location=undefined] - WKT geometry and operator to filter resources on their location or geometry
+ * @param {string[]} [properties.parent=undefined] - Comma separated list of parent resource IDs to restrict the search to or "*" to include nested resources at any level
+ * @param {string[]} [properties.foi=undefined] - Comma separated list of feature of interest IDs to get observations for
+ * @param {string[]} [properties.select=undefined] - Comma separated list of properties to include or exclude from results (use "!" prefix to exclude)
+ * @param {string} [properties.format='application/json'] - Mime type designating the format to use to encode the response.
+ * @param {string} [properties.validTime=undefined] - validTime - ISO 8601 time range to filter resources on their validity time.
+ When this parameter is omitted, the implicit value is "now", except for "history" collections where the absence of this parameter means no filtering is applied.
+ */
+ constructor(properties) {
+ super({
+ q: undefined,
+ bbox: undefined,
+ location: undefined,
+ parent: undefined,
+ foi: undefined,
+ select: undefined,
+ format: 'application/json',
+ validTime: undefined,
+ ...properties // merge defined properties
+ });
+ //TODO: assertions
+ }
+}
+export default SystemFilter;
diff --git a/source/core/consysapi/system/Systems.js b/source/core/consysapi/system/Systems.js
new file mode 100644
index 0000000000..07a5b08935
--- /dev/null
+++ b/source/core/consysapi/system/Systems.js
@@ -0,0 +1,65 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConnectedSystemsApi from "../ConnectedSystemsApi";
+import Collection from "../Collection";
+import SystemFilter from "./SystemFilter";
+import API from "../routes.conf";
+import ConSysApiFetchSystemParser from "../../parsers/consysapi/collection/ConSysApiFetchSystem.parser";
+
+class Systems extends ConnectedSystemsApi {
+ /**
+ * @param {Object} [networkProperties={}]
+ * @param {String} networkProperties.endpointUrl - defines the Http(s) endpoint URL
+ * @param {Boolean} networkProperties.tls - defines is use Http or Https secure protocol for fetching data
+ * @param {String} [networkProperties.streamProtocol='ws'] - the Stream protocol to use: 'ws' pr 'mqtt'
+ * @param {Object} [networkProperties.mqttOpts={}] - the Mqtt options if stream protocol is 'mqtt'
+ * @param {String} networkProperties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} networkProperties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ */
+ constructor(networkProperties) {
+ super(networkProperties);
+ this.conSysApiFetchSystemParser = new ConSysApiFetchSystemParser(networkProperties);
+ }
+
+ /**
+ * List or search all observing systems available through this API. By default, only top level systems are listed
+ * (i.e. subsystems are ommitted) unless the "parent" query parameter is set
+ * route: /systems
+ * @param {SystemFilter} [systemFilter= new SystemFilter()] - the system filter
+ * @param {Number} [pageSize=10] - default page size
+ * @return {Promise>} - A collection of System
+ */
+ async searchSystems(systemFilter = new SystemFilter(), pageSize = 10) {
+ return new Collection(this.baseUrl() + API.systems.search, systemFilter, pageSize, this.conSysApiFetchSystemParser);
+ }
+
+ /**
+ * Get a specific system resource by ID. Note that this will return the description of the system valid at the
+ * current time. To get the description valid for a past (or future) time, use the "history" sub-collection.
+ * route: /systems/{sysid}
+ * @param {String} systemId - the ID of the System resource
+ * @param {SystemFilter} [systemFilter=new SystemFilter()] - the system filter
+ * @return {System} - The corresponding System
+ */
+ async getSystemById(systemId,systemFilter = new SystemFilter()) {
+ const apiUrl = API.systems.by_id.replace('{sysid}',systemId);
+ const queryString = systemFilter.toQueryString(['select','format']);
+ const jsonData = await this.fetchAsJson(apiUrl, queryString);
+ return this.conSysApiFetchSystemParser.parseData(jsonData);
+ }
+}
+export default Systems;
diff --git a/source/core/datasource/consysapi/ConSysApi.datasource.js b/source/core/datasource/consysapi/ConSysApi.datasource.js
new file mode 100755
index 0000000000..afceb03cd0
--- /dev/null
+++ b/source/core/datasource/consysapi/ConSysApi.datasource.js
@@ -0,0 +1,91 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+
+import TimeSeriesDatasource from "../TimeSeries.datasource";
+import {Mode} from "../Mode";
+import ConSysApiDatasourceUpdater from "./ConSysApi.datasource.updater";
+
+class ConSysApi extends TimeSeriesDatasource {
+ /**
+ * @param {String} name - the datasource name
+ * @param {Object} properties - the datasource properties
+ * @param {String} properties.protocol - defines the protocol of the datasource. @see {@link DataConnector}, 'http', 'ws', 'mqtt', 'file', 'topic'
+ * @param {String} properties.endpointUrl the endpoint url, this property is ignored in case of using 'mqtt' protocol, the properties.mqttOpts.endpointUrl will be used instead
+ * @param {String} properties.resource the resource, /procedures, /fois, /observations, /tasks, /datastreams/4778/obs
+ * @param {Boolean} properties.tls - defines if use secure TLS connection
+ * @param {Boolean} properties.connectorOpts - connector specific Opts
+ * @param {Object} [properties.mqttOpts={}] - the Mqtt options if protocol is 'mqtt'
+ * @param {String} properties.mqttOpts.prefix - the Mqtt prefix value
+ * @param {String} properties.mqttOpts.endpointUrl - the Mqtt specific endpointUrl
+ * @param {Number} [properties.responseFormat=application/om+json] the response format (e.g application/om+json)
+ * @param {String[]} [properties.parentId=undefined] the parent id
+ * @param {String[]} [properties.keywords=undefined] the keyword ids
+ * @param {String[]} [properties.includedProps=undefined] the included properties
+ * @param {String[]} [properties.excludedProps=undefined] the excluded properties
+ * @param {string} [properties.roi=undefined] - WKT geometry and operator to filter resources on their location or geometry
+ * @param {String[]} [properties.featureOfInterest=undefined] Comma separated list of feature of interest IDs to get observations for.
+ * @param {String[]} [properties.observedProperty=undefined] Comma separated list of observed property URIs to get observations for.
+ * @param {String[]} [properties.prefetchBatchSize=250] Number of elements to prefetch at a time
+ * @param {String[]} [properties.prefetchBatchDuration=5000] Duration before prefetching the next batch. N.b the next batch will be prefetched at 80% of this duration
+ */
+ constructor(name, properties) {
+ super(name, {
+ reconnectTimeout: 1000 * 5, // default if not defined into properties
+ reconnectRetry: 10,
+ startTime: 'now',
+ endTime: '2055-01-01T00:00:00Z',
+ tls: false,
+ responseFormat: 'application/swe+json',
+ protocol: 'http',
+ type: 'ConSysApiStream',
+ mode: Mode.REAL_TIME,
+ prefetchBatchSize: 250,
+ prefetchBatchDuration: 5000,
+ connectorOpts: {},
+ ...properties,
+ });
+ }
+
+ async createTimeUpdater() {
+ if(!this.timeUpdater) {
+ this.timeUpdater = new ConSysApiDatasourceUpdater(this.properties);
+ let first = true;
+ this.timeUpdater.onTimeChanged = (min, max) => {
+ if (first) {
+ this.setMinTime(min);
+ first = false;
+ }
+ this.setMaxTime(max);
+ if (this.getDataSynchronizer()) {
+ this.getDataSynchronizer().minMaxChanged(first);
+ }
+ }
+ this.timeUpdater.onError = (err) => reject();
+
+ return this.timeUpdater.start();
+ } // TO CHECK: if timeUpdater has been created multiple times. Start() should not return anything
+ }
+
+ destroyTimeUpdater() {
+ if(this.timeUpdater) {
+ this.timeUpdater.destroy();
+ }
+ this.timeUpdater = undefined;
+ }
+}
+
+export default ConSysApi;
diff --git a/source/core/datasource/consysapi/ConSysApi.datasource.updater.js b/source/core/datasource/consysapi/ConSysApi.datasource.updater.js
new file mode 100644
index 0000000000..83da7968da
--- /dev/null
+++ b/source/core/datasource/consysapi/ConSysApi.datasource.updater.js
@@ -0,0 +1,55 @@
+class ConSysApiDatasourceUpdater {
+ constructor(properties) {
+ this.properties = properties;
+ this.datastreamInterval = undefined;
+ }
+
+ async fetchTime(url) {
+ return fetch(url)
+ .then(response => {
+ if (!response.ok) {
+ // create error object and reject if not a 2xx response code
+ let err = new Error("HTTP status code: " + response.status)
+ err.response = response
+ err.status = response.status
+ this.onError(err);
+ throw err
+ }
+ return response
+ })
+ .then(response => response.json())
+ .then(response => {
+ // update datastream times
+ if(response && response.items.length > 0 && response.items[0].phenomenonTime
+ && response.items[0].phenomenonTime.length > 1) {
+ const minTime = response.items[0].phenomenonTime[0];
+ const maxTime = response.items[0].phenomenonTime[1];
+ this.onTimeChanged(minTime, maxTime);
+ }
+ });
+ }
+ async start() {
+ const regex = new RegExp('\\/(.*\\/)(.*)\\/observations'); // /datastreams/abc13/observations
+ if(regex.test(this.properties.resource)) {
+ // is observation streaming
+ const match = regex.exec(this.properties.resource);
+ const datastreamId = match[2];
+ const url = `http${this.properties.tls? 's' : ''}://${this.properties.endpointUrl}/datastreams?id=${datastreamId}&select=id,phenomenonTime&f=application%2Fjson`;
+ return this.fetchTime(url).then(() => {
+ this.datastreamInterval = setInterval(() => {
+ this.fetchTime(url);
+ }, 5000);
+ })
+ } else {
+ throw Error(`Cannot parse dataStream id from resource ${this.properties.resource}`);
+ }
+ }
+ onTimeChanged(min, max){}
+
+ onError(err){}
+ destroy() {
+ clearInterval(this.datastreamInterval);
+ }
+}
+
+export default ConSysApiDatasourceUpdater;
diff --git a/source/core/datasource/consysapi/context/ConSysApi.context.js b/source/core/datasource/consysapi/context/ConSysApi.context.js
new file mode 100644
index 0000000000..d31d599c0a
--- /dev/null
+++ b/source/core/datasource/consysapi/context/ConSysApi.context.js
@@ -0,0 +1,88 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import {isDefined} from "../../../utils/Utils";
+import ObservationFilter from "../../../consysapi/observation/ObservationFilter";
+import DataSourceContext from "../../common/context/DataSource.context";
+import ControlStreamFilter from "../../../consysapi/controlstream/ControlStreamFilter";
+
+class ConSysApiContext extends DataSourceContext {
+ createControlStreamFilter(properties) {
+ const props = {};
+ if(isDefined(properties.keywords)) {
+ props.q = properties.keywords;
+ }
+ if(isDefined(properties.actuableProperty)) {
+ props.actuableProperty = properties.actuableProperty;
+ }
+ if(isDefined(properties.statusCode)) {
+ props.statusCode = properties.statusCode;
+ }
+ if(isDefined(properties.responseFormat)) {
+ props.format = properties.responseFormat;
+ }
+ if(isDefined(properties.issueTime)) {
+ props.issueTime = properties.issueTime;
+ }
+ if(isDefined(properties.executionTime)) {
+ props.executionTime = properties.executionTime;
+ }
+ if(isDefined(properties.reportTime)) {
+ props.reportTime = properties.reportTime;
+ }
+
+ return new ControlStreamFilter(props);
+ }
+
+ createObservationFilter(properties) {
+ const props = {};
+ if(isDefined(properties.roi)) {
+ props.location = props.roi;
+ }
+ if(isDefined(properties.responseFormat)) {
+ props.format = properties.responseFormat;
+ }
+ if(isDefined(properties.replaySpeed)) {
+ props.replaySpeed = properties.replaySpeed;
+ }
+ if(isDefined(properties.startTime)) {
+ props.phenomenonTime = properties.startTime + '/' + properties.endTime;
+ }
+ if(isDefined(properties.resultTime)) {
+ props.resultTime = properties.resultTime;
+ }
+ if(isDefined(properties.resultTime)) {
+ props.resultTime = properties.resultTime;
+ }
+ if(isDefined(properties.featureOfInterest)) {
+ props.featureOfInterest = properties.featureOfInterest;
+ }
+ if(isDefined(properties.excludedProps)) {
+ props.select = properties.excludedProps.map(e => '!' + e);
+ }
+ if(isDefined(properties.includedProps)) {
+ if(!isDefined(props.select)) {
+ props.select = [];
+ }
+ props.select.concat(properties.includedProps);
+ }
+
+ return new ObservationFilter(props);
+ }
+}
+
+
+export default ConSysApiContext;
diff --git a/source/core/datasource/consysapi/context/ConSysApi.realtime.context.js b/source/core/datasource/consysapi/context/ConSysApi.realtime.context.js
new file mode 100644
index 0000000000..21593337f6
--- /dev/null
+++ b/source/core/datasource/consysapi/context/ConSysApi.realtime.context.js
@@ -0,0 +1,91 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConSysApiContext from "./ConSysApi.context";
+import DataStream from "../../../consysapi/datastream/DataStream";
+import {isDefined} from "../../../utils/Utils";
+import ControlStream from "../../../consysapi/controlstream/ControlStream";
+
+class ConSysApiRealTimeContext extends ConSysApiContext {
+ init(properties) {
+ this.properties = properties;
+
+ const networkProperties = {
+ ...properties,
+ streamProtocol: properties.protocol
+ };
+ let filter;
+ let regex = new RegExp('\\/systems\\/(.*)\\/controlstreams\\/(.*)\\/status');
+
+ this.streamObject = undefined;
+
+ // check control status
+ if(regex.test(properties.resource)) {
+ filter = this.createControlStreamFilter(properties);
+ // is observation streaming
+ const match = regex.exec(properties.resource);
+
+ this.streamObject = new ControlStream({
+ id: match[2],
+ 'system@id': match[1]
+ }, networkProperties);
+ this.streamFunction = function() {
+ this.streamObject.streamStatus(filter, (messages) => this.onStreamMessage(messages, filter.props.format));
+ }
+ } else {
+ // check for datastream observations
+ regex = new RegExp('\\/(.*\\/)(.*)\\/observations'); // /datastreams/abc13/observations
+ if(regex.test(properties.resource)) {
+ filter = this.createObservationFilter(properties);
+ // is observation streaming
+ const match = regex.exec(properties.resource);
+ this.streamObject = new DataStream({
+ id: match[2]
+ }, networkProperties);
+ this.streamFunction = function() {
+ this.streamObject.streamObservations(filter, (messages) => this.onStreamMessage(messages, filter.props.format));
+ }
+ }
+ }
+ this.streamObject.stream().onChangeStatus = this.onChangeStatus.bind(this);
+ }
+ onStreamMessage(messages, format) {
+ // in case of om+json ,we have to add the timestamp which is not included for each record but at the root level
+ let results = messages;
+ let version = this.properties.version;
+ for(let message of messages) {
+ message.version = version;
+ }
+ this.handleData(results, format);
+ }
+
+ connect() {
+ this.streamFunction();
+ }
+
+ async disconnect() {
+ if(isDefined(this.streamObject)) {
+ this.streamObject.stream().disconnect();
+ }
+ }
+
+ isConnected() {
+ return this.streamObject.stream().status;
+ }
+}
+
+
+export default ConSysApiRealTimeContext;
diff --git a/source/core/datasource/consysapi/context/ConSysApi.replay.context.js b/source/core/datasource/consysapi/context/ConSysApi.replay.context.js
new file mode 100644
index 0000000000..ad3c5e5122
--- /dev/null
+++ b/source/core/datasource/consysapi/context/ConSysApi.replay.context.js
@@ -0,0 +1,138 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import ConSysApiContext from "./ConSysApi.context";
+import DataStream from "../../../consysapi/datastream/DataStream";
+import {isDefined} from "../../../utils/Utils";
+import ControlStream from "../../../consysapi/controlstream/ControlStream";
+
+class ConSysApiReplayContext extends ConSysApiContext {
+ init(properties) {
+ this.collection = undefined;
+ this.relativeStartTimestamp = undefined;
+ this.properties = properties;
+ this.replayFunction = undefined;
+
+ const networkProperties = {
+ ...properties
+ };
+ let filter;
+ let regex = new RegExp('\\/systems\\/(.*)\\/controlstreams\\/(.*)\\/status');
+
+ // check controlstream status
+ if(regex.test(properties.resource)) {
+ filter = this.createControlStreamFilter(properties);
+ // is observation streaming
+ const match = regex.exec(properties.resource);
+
+ let control = new ControlStream({
+ id: match[2],
+ 'system@id': match[1]
+ }, networkProperties);
+ this.replayFunction = function(props, startTimestamp, endTimestamp) {
+ const controlFilter = this.createControlStreamFilter({
+ ...properties,
+ ...props,
+ startTime: new Date(startTimestamp).toISOString(),
+ endTime: new Date(endTimestamp).toISOString()
+ });
+ return control.searchStatus(controlFilter, 1);
+ }
+ } else {
+ // check for datastream observations
+ regex = new RegExp('\\/(.*\\/)(.*)\\/observations'); // /datastreams/abc13/observations
+ if(regex.test(properties.resource)) {
+ // is observation streaming
+ const match = regex.exec(properties.resource);
+ let dataStream = new DataStream({
+ id: match[2]
+ }, networkProperties);
+ this.dataStream = dataStream;
+ this.replayFunction = function(props, startTime, endTime) {
+ const obsFilter = this.createObservationFilter({
+ ...properties,
+ ...props,
+ replaySpeed: undefined,
+ startTime: startTime,
+ endTime: endTime
+ });
+ return dataStream.searchObservations(obsFilter, properties.prefetchBatchSize);
+ }
+ }
+ }
+ }
+
+ async disconnect() {
+ this.collection = undefined;
+ this.relativeStartTimestamp = undefined;
+ this.replayFunction = undefined;
+ }
+
+ async nextBatch(properties, masterTimestamp, status = {cancel:false}) {
+ let version = this.properties.version;
+ return new Promise(async (resolve, reject) => {
+ try {
+ let data;
+ let results = [];
+
+ const moveTimeCursor = async () => {
+ let relativeStartTime;
+ if(isDefined(this.relativeStartTimestamp)) {
+ relativeStartTime = new Date(this.relativeStartTimestamp + 1).toISOString();
+ } else {
+ //TOCHECK: ISO or timestamp
+ relativeStartTime = new Date(this.properties.startTime).toISOString();
+ }
+
+ console.warn(`fetching ${relativeStartTime} -> ` +
+ `${this.properties.endTime} for datasource ${this.properties.dataSourceId}`);
+ // if disconnected, replay function is reset
+ if(this.replayFunction) {
+ this.collection = await this.replayFunction(properties, relativeStartTime, this.properties.endTime);
+ }
+ }
+
+ const fetchNext = async () => {
+ data = await this.collection.nextPage();
+ if (status.cancel) {
+ reject('Status has been cancelled');
+ }
+ if (data.length > 0) {
+ results = data;
+ for(let d of results) {
+ d.version = version;
+ }
+ if(status.cancel) {
+ reject('Status has been cancelled');
+ } else {
+ // start startTime cursor
+ this.relativeStartTimestamp = results[results.length-1].timestamp;
+ resolve(data);
+ }
+ }
+ }
+
+ await moveTimeCursor();
+ await fetchNext();
+ } catch (ex) {
+ reject(ex);
+ }
+ });
+ }
+}
+
+
+export default ConSysApiReplayContext;
diff --git a/source/core/datasource/consysapi/handler/ConSysApi.handler.js b/source/core/datasource/consysapi/handler/ConSysApi.handler.js
new file mode 100644
index 0000000000..1b79d12ba4
--- /dev/null
+++ b/source/core/datasource/consysapi/handler/ConSysApi.handler.js
@@ -0,0 +1,32 @@
+/***************************** BEGIN LICENSE BLOCK ***************************
+
+ The contents of this file are subject to the Mozilla Public License, v. 2.0.
+ If a copy of the MPL was not distributed with this file, You can obtain one
+ at http://mozilla.org/MPL/2.0/.
+
+ Software distributed under the License is distributed on an "AS IS" basis,
+ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ for the specific language governing rights and limitations under the License.
+
+ Copyright (C) 2015-2022 Georobotix Inc. All Rights Reserved.
+
+ Author: Mathieu Dhainaut
+
+ ******************************* END LICENSE BLOCK ***************************/
+
+import TimeSeriesHandler from "../../common/handler/TimeSeries.handler";
+import ConSysApiRealtimeContext from "../context/ConSysApi.realtime.context";
+import ConSysApiReplayContext from "../context/ConSysApi.replay.context";
+import {Mode} from "../../Mode";
+
+class ConSysApiHandler extends TimeSeriesHandler {
+ createContext(properties) {
+ if(properties.mode === Mode.REPLAY || properties.mode === Mode.BATCH) {
+ return new ConSysApiReplayContext();
+ } else {
+ return new ConSysApiRealtimeContext();
+ }
+ }
+}
+
+export default ConSysApiHandler;
diff --git a/source/core/datasource/worker/DataSourceWorker.js b/source/core/datasource/worker/DataSourceWorker.js
index b4a102305d..dfe95c3a48 100644
--- a/source/core/datasource/worker/DataSourceWorker.js
+++ b/source/core/datasource/worker/DataSourceWorker.js
@@ -1,6 +1,7 @@
import SosGetResultHandler from "../sos/handler/SosGetResult.handler";
import SosGetFoisHandler from "../sos/handler/SosGetFois.handler";
import SweApiHandler from "../sweapi/handler/SweApi.handler";
+import ConSysApiHandler from "../consysapi/handler/ConSysApi.handler";
class DataSourceWorker {
constructor() {
@@ -116,6 +117,8 @@ class DataSourceWorker {
return new SosGetFoisHandler();
} else if (properties.type === 'SweApiStream') {
return new SweApiHandler();
+ } else if (properties.type === 'ConSysApiStream') {
+ return new ConSysApiHandler();
} else {
throw Error('Unsupported SOS service Error');
}
diff --git a/source/core/parsers/consysapi/collection/CollectionOmJsonParser.parser.js b/source/core/parsers/consysapi/collection/CollectionOmJsonParser.parser.js
new file mode 100644
index 0000000000..57a65c7706
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/CollectionOmJsonParser.parser.js
@@ -0,0 +1,24 @@
+import OmJsonParser from "../common/OmJsonParser.parser";
+
+class OmJsonCollectionParser extends OmJsonParser {
+ constructor(rootElement) {
+ super(rootElement);
+ }
+ getTimeField() {
+ return 'phenomenonTime';
+ }
+
+ parseDataBlock(arrayBuffer) {
+ let dataBlock = this.textDecoder.decode(arrayBuffer);
+ const jsonData = JSON.parse(dataBlock);
+ const result = [];
+
+ for(let d of jsonData.items) {
+ d['timestamp'] = new Date(d[this.getTimeField()]).getTime();
+ result.push(d);
+ }
+ return result;
+ }
+}
+
+export default OmJsonCollectionParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiCollectionObjectParser.js b/source/core/parsers/consysapi/collection/ConSysApiCollectionObjectParser.js
new file mode 100644
index 0000000000..36cfba7edf
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiCollectionObjectParser.js
@@ -0,0 +1,9 @@
+class ConSysApiCollectionObjectParser {
+ constructor(networkProperties) {
+ this.networkProperties = networkProperties;
+ }
+
+ parseData(data) {}
+}
+
+export default ConSysApiCollectionObjectParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiControlStreamStatus.parser.js b/source/core/parsers/consysapi/collection/ConSysApiControlStreamStatus.parser.js
new file mode 100644
index 0000000000..71c9701a4b
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiControlStreamStatus.parser.js
@@ -0,0 +1,20 @@
+import ConSysApiCollectionObjectParser from "./ConSysApiCollectionObjectParser";
+
+class ConSysApiControlStreamStatusParser extends ConSysApiCollectionObjectParser {
+ constructor(networkProperties) {
+ super(networkProperties);
+ this.textDecoder = new TextDecoder();
+ }
+
+ parseData(data, format) {
+ let res;
+ if(format === 'arraybuffer') {
+ res = this.textDecoder.decode(data);
+ } else {
+ res = JSON.parse(data);
+ }
+ return JSON.parse(res);
+ }
+}
+
+export default ConSysApiControlStreamStatusParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiDataStream.parser.js b/source/core/parsers/consysapi/collection/ConSysApiDataStream.parser.js
new file mode 100644
index 0000000000..8666a30c32
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiDataStream.parser.js
@@ -0,0 +1,16 @@
+import ConSysApiCollectionObjectParser from "./ConSysApiCollectionObjectParser";
+import DataStream from "../../../consysapi/datastream/DataStream";
+
+class ConSysApiDataStreamParser extends ConSysApiCollectionObjectParser {
+ parseData(data) {
+ return new DataStream(
+ data,
+ {
+ streamProtocol: 'ws', // default streaming
+ ...this.networkProperties
+ }
+ );
+ }
+}
+
+export default ConSysApiDataStreamParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiFetchCommand.parser.js b/source/core/parsers/consysapi/collection/ConSysApiFetchCommand.parser.js
new file mode 100644
index 0000000000..e10575dd8f
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiFetchCommand.parser.js
@@ -0,0 +1,21 @@
+import ConSysApiCollectionObjectParser from "./ConSysApiCollectionObjectParser";
+import Command from "../../../consysapi/command/Command";
+
+class ConSysApiFetchCommandParser extends ConSysApiCollectionObjectParser {
+ constructor(networkProperties, systemId) {
+ super(networkProperties);
+ this.systemId = systemId;
+ }
+
+ parseData(data) {
+ return new Command(
+ {
+ ...data,
+ systemId: this.systemId
+ },
+ this.networkProperties
+ );
+ }
+}
+
+export default ConSysApiFetchCommandParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiFetchControlStream.parser.js b/source/core/parsers/consysapi/collection/ConSysApiFetchControlStream.parser.js
new file mode 100644
index 0000000000..f9efa12fe6
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiFetchControlStream.parser.js
@@ -0,0 +1,16 @@
+import ConSysApiCollectionObjectParser from "./ConSysApiCollectionObjectParser";
+import ControlStream from "../../../consysapi/controlstream/ControlStream";
+
+class ConSysApiFetchControlStreamParser extends ConSysApiCollectionObjectParser {
+ parseData(data) {
+ return new ControlStream(
+ data,
+ {
+ streamProtocol: 'ws', // default streaming
+ ...this.networkProperties
+ }
+ );
+ }
+}
+
+export default ConSysApiFetchControlStreamParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiFetchEvent.parser.js b/source/core/parsers/consysapi/collection/ConSysApiFetchEvent.parser.js
new file mode 100644
index 0000000000..1d514b4150
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiFetchEvent.parser.js
@@ -0,0 +1,12 @@
+import ConSysApiCollectionObjectParser from "./ConSysApiCollectionObjectParser";
+
+class ConSysApiFetchEventParser extends ConSysApiCollectionObjectParser {
+ parseData(data) {
+ return new Event(
+ data,
+ this.networkProperties
+ );
+ }
+}
+
+export default ConSysApiFetchEventParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiFetchObservation.parser.js b/source/core/parsers/consysapi/collection/ConSysApiFetchObservation.parser.js
new file mode 100644
index 0000000000..3be6531cec
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiFetchObservation.parser.js
@@ -0,0 +1,13 @@
+import ConSysApiCollectionObjectParser from "./ConSysApiCollectionObjectParser";
+import Observation from "../../../consysapi/observation/Observation";
+
+class ConSysApiFetchObservationParser extends ConSysApiCollectionObjectParser {
+ parseData(data) {
+ return new Observation(
+ data,
+ this.networkProperties
+ );
+ }
+}
+
+export default ConSysApiFetchObservationParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiFetchSamplingFeature.parser.js b/source/core/parsers/consysapi/collection/ConSysApiFetchSamplingFeature.parser.js
new file mode 100644
index 0000000000..17bcc5b586
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiFetchSamplingFeature.parser.js
@@ -0,0 +1,18 @@
+import ConSysApiCollectionObjectParser from "./ConSysApiCollectionObjectParser";
+import SamplingFeature from "../../../consysapi/samplingfeature/SamplingFeature";
+
+class ConSysApiFetchSamplingFeatureParser extends ConSysApiCollectionObjectParser {
+ parseData(data) {
+ return new SamplingFeature(
+ {
+ ...data,
+ geometry: data.geometry || undefined,
+ bbox: data.bbox || undefined
+ },
+
+ this.networkProperties
+ );
+ }
+}
+
+export default ConSysApiFetchSamplingFeatureParser;
diff --git a/source/core/parsers/consysapi/collection/ConSysApiFetchSystem.parser.js b/source/core/parsers/consysapi/collection/ConSysApiFetchSystem.parser.js
new file mode 100644
index 0000000000..b627838ad9
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/ConSysApiFetchSystem.parser.js
@@ -0,0 +1,13 @@
+import ConSysApiCollectionObjectParser from "./ConSysApiCollectionObjectParser";
+import System from "../../../consysapi/system/System";
+
+class ConSysApiFetchSystemParser extends ConSysApiCollectionObjectParser {
+ parseData(data) {
+ return new System(
+ data,
+ this.networkProperties
+ );
+ }
+}
+
+export default ConSysApiFetchSystemParser;
diff --git a/source/core/parsers/consysapi/collection/SweCollectionDataParser.js b/source/core/parsers/consysapi/collection/SweCollectionDataParser.js
new file mode 100644
index 0000000000..cb1ebebb42
--- /dev/null
+++ b/source/core/parsers/consysapi/collection/SweCollectionDataParser.js
@@ -0,0 +1,37 @@
+class SweCollectionDataParser {
+
+ constructor(format = 'application/json') {
+ this.format = format;
+ }
+
+ parseData(data) {
+ if (this.format === 'application/om+json' || this.format === 'application/json') {
+ return this.parseOmJsonData(data);
+ } else if (this.format === 'application/swe+json') {
+ return this.parseSweJsonData(data);
+ } else if (this.format === 'application/swe+csv') {
+ return this.parseSweCsv(data);
+ } else if (this.format === 'application/swe+xml') {
+ return this.parseSweXml(data);
+ } else {
+ throw Error(`Unsupported collection format ${this.format}`);
+ }
+ }
+
+ parseOmJsonData(data) {
+ return (data instanceof ArrayBuffer) ? JSON.parse(String.fromCharCode.apply(null, new Uint8Array(data))).items : data.items;
+ }
+
+ parseSweJsonData(data) {
+ return (data instanceof ArrayBuffer) ? JSON.parse(String.fromCharCode.apply(null, new Uint8Array(data))) : data;
+ }
+
+ parseSweCsv(data) {
+ let content = (data instanceof ArrayBuffer) ? String.fromCharCode.apply(null, new Uint8Array(data)) : data;
+ return content.split('\n');
+ }
+ parseSweXml(data) {
+ return (data instanceof ArrayBuffer) ? String.fromCharCode.apply(null, new Uint8Array(data)) : data;
+ }
+}
+export default SweCollectionDataParser;
diff --git a/source/core/parsers/consysapi/common/OmJsonParser.parser.js b/source/core/parsers/consysapi/common/OmJsonParser.parser.js
new file mode 100644
index 0000000000..2f65224dbe
--- /dev/null
+++ b/source/core/parsers/consysapi/common/OmJsonParser.parser.js
@@ -0,0 +1,12 @@
+import JsonDataParser from "../../JsonDataParser";
+
+class OmJsonParser extends JsonDataParser {
+ constructor(rootElement) {
+ super(rootElement);
+ }
+ getTimeField() {
+ return 'phenomenonTime';
+ }
+}
+
+export default OmJsonParser;
diff --git a/source/core/parsers/consysapi/common/SweBinaryParser.parser.js b/source/core/parsers/consysapi/common/SweBinaryParser.parser.js
new file mode 100644
index 0000000000..d59f4b4d7c
--- /dev/null
+++ b/source/core/parsers/consysapi/common/SweBinaryParser.parser.js
@@ -0,0 +1,9 @@
+import BinaryDataParser from "../../BinaryDataParser";
+
+class SweBinaryParser extends BinaryDataParser {
+ constructor(rootElement, encoding) {
+ super(rootElement, encoding)
+ }
+}
+
+export default SweBinaryParser;
diff --git a/source/core/parsers/consysapi/common/SweCsvParser.parser.js b/source/core/parsers/consysapi/common/SweCsvParser.parser.js
new file mode 100644
index 0000000000..c4364054c1
--- /dev/null
+++ b/source/core/parsers/consysapi/common/SweCsvParser.parser.js
@@ -0,0 +1,9 @@
+import TextDataParser from "../../TextDataParser";
+
+class SweCsvParser extends TextDataParser {
+ constructor(rootElement, encoding) {
+ super(rootElement, encoding)
+ }
+}
+
+export default SweCsvParser;
diff --git a/source/core/parsers/consysapi/common/SweJsonParser.parser.js b/source/core/parsers/consysapi/common/SweJsonParser.parser.js
new file mode 100644
index 0000000000..12f818a96b
--- /dev/null
+++ b/source/core/parsers/consysapi/common/SweJsonParser.parser.js
@@ -0,0 +1,9 @@
+import JsonDataParser from "../../JsonDataParser";
+
+class SweJsonParser extends JsonDataParser {
+ constructor(rootElement) {
+ super(rootElement)
+ }
+}
+
+export default SweJsonParser;
diff --git a/source/core/parsers/consysapi/common/SweXmlParser.parser.js b/source/core/parsers/consysapi/common/SweXmlParser.parser.js
new file mode 100644
index 0000000000..705e5c3f37
--- /dev/null
+++ b/source/core/parsers/consysapi/common/SweXmlParser.parser.js
@@ -0,0 +1,9 @@
+import JsonDataParser from "../../../parsers/JsonDataParser";
+
+class SweXmlParser extends JsonDataParser {
+ constructor(rootElement) {
+ super(rootElement)
+ }
+}
+
+export default SweXmlParser;
diff --git a/source/core/parsers/consysapi/observations/ConSysApiResult.collection.controlstream.parser.js b/source/core/parsers/consysapi/observations/ConSysApiResult.collection.controlstream.parser.js
new file mode 100644
index 0000000000..46f30df86b
--- /dev/null
+++ b/source/core/parsers/consysapi/observations/ConSysApiResult.collection.controlstream.parser.js
@@ -0,0 +1,21 @@
+import ConSysApiResultControlStreamParser from "./ConSysApiResult.controlstream.parser";
+
+class ConSysApiResultCollectionControlStreamParser extends ConSysApiResultControlStreamParser {
+ constructor(dataObject) {
+ super(dataObject);
+ }
+
+ init(schema, format) {
+ if(format === 'application/swe+binary') {
+ //resultSchema
+ throw new Error(`Format not supported ${format}`);
+ } else if(format === 'application/swe+xml') {
+ //resultSchema
+ throw new Error(`Format not supported ${format}`);
+ } else {
+ super.init(schema, format);
+ }
+ }
+}
+
+export default ConSysApiResultCollectionControlStreamParser;
diff --git a/source/core/parsers/consysapi/observations/ConSysApiResult.collection.datastream.parser.js b/source/core/parsers/consysapi/observations/ConSysApiResult.collection.datastream.parser.js
new file mode 100644
index 0000000000..5016da7737
--- /dev/null
+++ b/source/core/parsers/consysapi/observations/ConSysApiResult.collection.datastream.parser.js
@@ -0,0 +1,22 @@
+import OmJsonCollectionParser from "../collection/CollectionOmJsonParser.parser";
+import ConSysApiResultDatastreamParser from "./ConSysApiResult.datastream.parser";
+
+class ConSysApiResultCollectionDatastreamParser extends ConSysApiResultDatastreamParser {
+ constructor(dataObject) {
+ super(dataObject);
+ }
+
+ init(schema, format) {
+ if(format === 'application/om+json') {
+ //resultSchema
+ this.parsers[format].parser = new OmJsonCollectionParser(schema.resultSchema);
+ } else if(format === 'application/swe+xml') {
+ //resultSchema
+ throw new Error(`Format not supported ${format}`);
+ } else {
+ super.init(schema, format);
+ }
+ }
+}
+
+export default ConSysApiResultCollectionDatastreamParser;
diff --git a/source/core/parsers/consysapi/observations/ConSysApiResult.controlstream.parser.js b/source/core/parsers/consysapi/observations/ConSysApiResult.controlstream.parser.js
new file mode 100644
index 0000000000..e47e7f3cc4
--- /dev/null
+++ b/source/core/parsers/consysapi/observations/ConSysApiResult.controlstream.parser.js
@@ -0,0 +1,34 @@
+import OmJsonParser from "../common/OmJsonParser.parser";
+import ConSysApiResultParser from "./ConSysApiResult.parser";
+import SweJsonParser from "../common/SweJsonParser.parser";
+import SweBinaryParser from "../common/SweBinaryParser.parser";
+import SweCsvParser from "../common/SweCsvParser.parser";
+
+class ConSysApiResultControlStreamParser extends ConSysApiResultParser {
+ constructor(dataObject) {
+ super(dataObject);
+ }
+
+ init(schema, format) {
+ if(format === 'application/om+json') {
+ //resultSchema
+ this.parsers[format].parser = new OmJsonParser(schema.commandSchema);
+ } else if(format === 'application/swe+json') {
+ //recordSchema
+ this.parsers[format].parser = new SweJsonParser(schema.commandSchema);
+ } /*else if(format === 'application/swe+xml') {
+ //recordSchema
+ this.parsers[format].parser = new SweXmlParser(schema.recordSchema);
+ }*/ else if(format === 'application/swe+binary') {
+ //recordSchema
+ this.parsers[format].parser = new SweBinaryParser(schema.commandSchema, schema.commandEncoding);
+ } else if(format === 'application/swe+csv') {
+ //recordSchema
+ this.parsers[format].parser = new SweCsvParser(schema.commandSchema, schema.commandEncoding);
+ } else {
+ throw Error(`Not supported parser format: ${format}`);
+ }
+ }
+}
+
+export default ConSysApiResultControlStreamParser;
diff --git a/source/core/parsers/consysapi/observations/ConSysApiResult.datastream.parser.js b/source/core/parsers/consysapi/observations/ConSysApiResult.datastream.parser.js
new file mode 100644
index 0000000000..a3c905bdec
--- /dev/null
+++ b/source/core/parsers/consysapi/observations/ConSysApiResult.datastream.parser.js
@@ -0,0 +1,38 @@
+import OmJsonParser from "../common/OmJsonParser.parser";
+import ConSysApiResultParser from "./ConSysApiResult.parser";
+import SweJsonParser from "../common/SweJsonParser.parser";
+import SweBinaryParser from "../common/SweBinaryParser.parser";
+import SweCsvParser from "../common/SweCsvParser.parser";
+import {isDefined} from "../../../utils/Utils";
+
+class ConSysApiResultDatastreamParser extends ConSysApiResultParser {
+ constructor(dataObject) {
+ super(dataObject);
+ }
+
+ init(schema, format) {
+ if(format in this.parsers && isDefined(this.parsers[format].parser)) {
+ return this.parsers[format].parser;
+ }
+ if(format === 'application/om+json') {
+ //resultSchema
+ this.parsers[format].parser = new OmJsonParser(schema.resultSchema);
+ } else if(format === 'application/swe+json') {
+ //recordSchema
+ this.parsers[format].parser = new SweJsonParser(schema.recordSchema);
+ } /*else if(format === 'application/swe+xml') {
+ //recordSchema
+ this.parsers[format].parser = new SweXmlParser(schema.recordSchema);
+ }*/ else if(format === 'application/swe+binary') {
+ //recordSchema
+ this.parsers[format].parser = new SweBinaryParser(schema.recordSchema, schema.recordEncoding);
+ } else if(format === 'application/swe+csv') {
+ //recordSchema
+ this.parsers[format].parser = new SweCsvParser(schema.recordSchema, schema.recordEncoding);
+ } else {
+ throw Error(`Not supported parser format: ${format}`);
+ }
+ }
+}
+
+export default ConSysApiResultDatastreamParser;
diff --git a/source/core/parsers/consysapi/observations/ConSysApiResult.parser.js b/source/core/parsers/consysapi/observations/ConSysApiResult.parser.js
new file mode 100644
index 0000000000..a12c8e3122
--- /dev/null
+++ b/source/core/parsers/consysapi/observations/ConSysApiResult.parser.js
@@ -0,0 +1,69 @@
+import ConnectedSystemsApiFilter from "../../../consysapi/Filter";
+import {isDefined} from "../../../utils/Utils";
+
+class ConSysApiResultParser {
+ constructor(dataObject) {
+ this.dataObject = dataObject;
+ this.parsers = {
+ 'application/om+json' : {
+ schemaPromise: undefined,
+ parser: undefined
+ },
+ 'application/swe+json' : {
+ schemaPromise: undefined,
+ parser: undefined
+ },
+ 'application/swe+xml' : {
+ schemaPromise: undefined,
+ parser: undefined
+ },
+ 'application/swe+csv' : {
+ schemaPromise: undefined,
+ parser: undefined
+ },
+ 'application/swe+binary' : {
+ schemaPromise: undefined,
+ parser: undefined
+ }
+ }
+ }
+
+ async checkParser(format) {
+ if(!(format in this.parsers)) {
+ throw new Error(`Not support format ${format}`);
+ }
+
+ const parser = this.parsers[format];
+ if(!isDefined(parser.parser)) {
+ if(!isDefined(parser.schemaPromise)) {
+ this.parsers[format].schemaPromise = new Promise(async (resolve, reject) => {
+ try {
+ const jsonSchema = await this.dataObject.getSchema(new ConnectedSystemsApiFilter({
+ obsFormat: format
+ }));
+ this.init(jsonSchema, format);
+ resolve();
+ } catch (ex) {
+ console.error(ex);
+ reject(ex);
+ }
+ });
+ }
+ await parser.schemaPromise;
+ return this.parsers[format].parser;
+ } else {
+ return parser.parser;
+ }
+ }
+
+ init(schema, format) {
+ throw new Error('Unsupported Operation')
+ }
+
+ async parseDataBlock(arrayBuffer, format = 'application/om+json') {
+ const parser = await this.checkParser(format);
+ return parser.parseDataBlock(arrayBuffer);
+ }
+}
+
+export default ConSysApiResultParser;