# DataSynchronizer

The DataSynchronizer is an object allowing the synchronization of multiple DataSources.

When several DataSources connect to the server, the data come on different channels.

They come in temporal order within the same Stream but f you want to display data from several DataSources at a time t, then you need to set up a synchronization mechanism.

Let's take the example of a GPS sensor, and a video where the GPS sensor sends data at a rate of 1 data/second, and the video sends data at a rate of 30 frames/second.

So if we want to synchronize them, we have to take into account each video frame (where each frame has a timestamp that can locate it precisely in time) and a GPS data.

A mechanism will therefore have to take all these data streams as INPUT, ordering them in temporal order and sending them back to the Views so that they can be displayed.

This is the role of the DataSynchronizer, taking several DataSources as Input and send back the new stream containing all data ordered in temporal order.

# Properties configuration

There are properties owned by the DataSynchronizer Object.

API Reference

The timerResolution allows you to define the refresh rate of the synchronization algorithm.

The algorithm uses a function to check the state of its buffer to know if a data is candidate to be sent to the views. This function is timed by a time interval that can be changed during the construction of the DataSynchronizer object using the timerResolution property.

*Note For further details about how the algorithm works, see Advanced section

# Channels

The DataSynchronizer will receive the data through BroadcastChannel(s) (opens new window) and send back the result through the same channel(s).

It also returns a time synchronization data defined by TIME_SYNCHRONIZER_TOPIC + <id_of_synchronizer>.

The TIME_SYNCHRONIZER_TOPIC constant is defined from the constant package 'osh-js/core/Constants'

# Example

This example defines multiple DataSources object to synchronize:

// create data source for Android phone GPS
import SweJson from 'osh-js/core/datasource/SosGetResultJson.js';
import SosGetResultVideo from 'osh-js/core/datasource/SosGetResultVideo';
import DataSynchronizer from 'osh-js/core/timesync/DataSynchronizer';
import {TIME_SYNCHRONIZER_TOPIC} from 'osh-js/core/Constants';

const START_TIME = '2015-12-19T21:04:29.231Z';
const END_TIME = '2015-12-19T21:09:19.675Z';
const REPLAY_SPEED = 4.0;
const BUFFERING_TIME = 500;
const TIMEOUT = 1000;

const videoDataSource = new SosGetResultVideo("drone-Video", {
  protocol: 'ws',
  service: 'SOS',
  endpointUrl: 'sensiasoft.net:8181/sensorhub/sos',
  offeringID: 'urn:mysos:solo:video2',
  observedProperty: 'http://sensorml.com/ont/swe/property/VideoFrame',
  startTime: START_TIME,
  endTime: END_TIME,
  replaySpeed: REPLAY_SPEED,
  bufferingTime: BUFFERING_TIME,
  timeOut: TIMEOUT
});
const platformLocationDataSource = new SweJson('android-GPS', {
  protocol: 'ws',
  service: 'SOS',
  endpointUrl: 'sensiasoft.net:8181/sensorhub/sos',
  offeringID: 'urn:mysos:solo:nav2',
  observedProperty: 'http://www.opengis.net/def/property/OGC/0/PlatformLocation',
  startTime: START_TIME,
  endTime: END_TIME,
  replaySpeed: REPLAY_SPEED,
  bufferingTime: BUFFERING_TIME,
  timeOut: TIMEOUT
});
const platformOrientationDataSource = new SweJson('android-Heading', {
  protocol: 'ws',
  service: 'SOS',
  endpointUrl: 'sensiasoft.net:8181/sensorhub/sos',
  offeringID: 'urn:mysos:solo:nav2',
  observedProperty: 'http://www.opengis.net/def/property/OGC/0/PlatformOrientation',
  startTime: START_TIME,
  endTime: END_TIME,
  replaySpeed: REPLAY_SPEED,
  bufferingTime: BUFFERING_TIME,
  timeOut: TIMEOUT
});

const dataSynchronizer = new DataSynchronizer({
  replaySpeed: REPLAY_SPEED,
  timerResolution: 5,
  dataSources: [videoDataSource, platformLocationDataSource, platformOrientationDataSource]
})

// connects each DataSource
dataSynchronizer.connect();

// Data are received through Broadcast channel in a separate thread.
// When you create a View object, it automatically subscribes to the corresponding datasource channel(s).
// If you don't have view, or don't need, you can directly subscribe to the channel

const videoBroadcastChannel     = new BroadcastChannel(DATASOURCE_DATA_TOPIC + videoDataSource.id);
const gpsBroadcastChannel       = new BroadcastChannel(DATASOURCE_DATA_TOPIC + platformLocationDataSource.id);
const orientBroadcastChannel    = new BroadcastChannel(DATASOURCE_DATA_TOPIC + platformOrientationDataSource.id);
const syncTimeBroadcastChannel  = new BroadcastChannel(TIME_SYNCHRONIZER_TOPIC + dataSynchronizer.id);

gpsBroadcastChannel.onmessage = (message) => {
  if(message.data.type === 'data') {
    displayLocation(message.data.values);
  }
}

orientBroadcastChannel.onmessage = (message) => {
  if(message.data.type === 'data') {
   displayOrientation(message.data.values);
  }
}

videoBroadcastChannel.onmessage = (message) => {
  if(message.data.type === 'data') {
    displayVideo(message.data.values);
  }
}

syncTimeBroadcastChannel.onmessage = (message) => {
    displayError(message.data.timestamp);
}

// start streaming
dataSynchronizer.connect();