# TimeController

The TimeController is a component allowing the visualization and temporal control of the Toolkit's DataSources. Thus it allows to go back to archive data at specific periods or to switch to real time.

API Reference

# Properties configuration

The control can be done either by passing a DataSource object or a DataSynchronizer object containing several DataSources.

The skipTimeStep parameter is used to define the period of time you want to go forward or backward. The value can be expressed in seconds or as a percentage.

The replaySpeedStep parameter is used to define the speed of acceleration or deceleration of the DataSource. It will act directly on the replaySpeed value of the DataSource object.

The debounce parameter is used to set the measured waiting time between two actions. For example, if we press forward several times, this value will allow to take into account either the first or both actions.

Example: if we click twice on forward at 300ms interval and the debounce value is 500ms, then the second `forward' will be ignored. On the other hand, if the debounce value was less than or equal to 300ms, the second action would also be executed.

The parseTime parameter allows you to define a function that will customize the time display next to the action buttons. This can be useful if we want to display the time in ISO UTC or local time for example, or if we want to display only hours:minutes or also seconds, months etc.

WARNING

For each forward, backward, replay speed and slide action of the slider, a reconnection is automatically performed and an event is launched with the name of the action that has just been performed as the value.

When switching to real time, the reconnection is also automatic. On the other hand, when switching from real time to replay, the last replay parameters are reloaded but the reconnection is not automatic. It is then necessary either to perform an action or to click on the play button.

# Example

<template>
  <div id="app">
    <div id="container">
    </div>
    <TimeController
        :dataSynchronizer="dataSynchronizer"
        @event='onControlEvent'
        :skipTimeStep="'60s'"
        :replaySpeedStep=0.1
        v-if="dataSynchronizer"
    ></TimeController>
  </div>
</template>
<script>
// @ is an alias to /src
import ChartJsView from 'osh-js/core/ui/view/chart/ChartJsView.js';
import CurveLayer from 'osh-js/core/ui/layer/CurveLayer.js';
import SosGetResult from 'osh-js/core/datasource/sos/SosGetResult.datasource.js';
import TimeController from 'osh-js/vue/components/TimeController.vue';
import {Mode} from 'osh-js/core/datasource/Mode';
import DataSynchronizer from 'osh-js/core/timesync/DataSynchronizer';
import {isDefined} from "osh-js/core/utils/Utils";

export default {
  components: {
    TimeController
  },
  data: function () {
    return {
      dataSynchronizer: null,
      view: null
    }
  },
  mounted() {

    let startTime = (new Date(Date.now() - 60 * 1000 * 60 * 1).toISOString());
    let endTime = (new Date(Date.now()).toISOString());

    let chartDataSource = new SosGetResult("weather", {
      endpointUrl: "sensiasoft.net/sensorhub/sos",
      offeringID: "urn:mysos:offering04",
      observedProperty: "http://sensorml.com/ont/swe/property/Weather",
      startTime: startTime,
      endTime: endTime,
      minTime: (new Date(Date.now() - 60 * 1000 * 60 * 1).toISOString()),
      maxTime: (new Date(Date.now()).toISOString()),
      mode: Mode.REPLAY,
      tls: true
    });

    console.log('chart dataSource: '+chartDataSource.id);
    const dataSynchronizer = new DataSynchronizer({
      replaySpeed: 1.5,
      startTime: startTime,
      endTime: endTime,
      dataSources: [chartDataSource],
      masterTimeRefreshRate: 250
    });

    function getRandomArbitrary(min, max) {
      return Math.random() * (max - min) + min;
    }

// #region snippet_curve_layer
    let windSpeedLayerCurve = new CurveLayer({
      dataSourceId: chartDataSource.id,
      getValues: (rec, timestamp) => {
        return {
          x: timestamp,
          y: rec.windSpeed
        }
      },
      lineColor: 'rgba(38,152,255,0.5)',
      getLineColor: (rec) => {
        const randomNumber = getRandomArbitrary(0,1);
        if(randomNumber > 0.5) {
          return 'rgba(255,0,0,0.5)';
        } else {
          return 'rgba(38,152,255,0.5)';
        }
      },
      fill: true,
      backgroundColor: 'rgba(169,212,255,0.5)',
      maxValues: 20,
      getBackgroundColor: (rec) => {
        const randomNumber = getRandomArbitrary(0,1);
        if(randomNumber > 0.5) {
          return 'rgba(255,0,0,0.5)';
        } else {
          return 'rgba(38,152,255,0.5)';
        }
      },
      name: 'Wind Speed (m/s)'
    });
// #endregion snippet_curve_layer

// show it in video view
    this.view = new ChartJsView({
      container: 'container',
      layers: [windSpeedLayerCurve],
      css: "chart-view",
      options: {
          scales: {
            y: {
              title: {
                display : true,
                text: "Wind Speed (m/s)s",
                padding: 20
              }
            },
          }
        },
      datasetOptions: {
        tension: 0.2 // for 'line'
      }
    });

    // start streaming
    dataSynchronizer.connect();

    this.dataSynchronizer = dataSynchronizer;
  },
  methods: {
    onControlEvent(eventName) {
      if(eventName === 'forward' || eventName === 'backward' || eventName === 'end'
          || eventName === 'replaySpeed'
          || (eventName === 'play')) {
        this.view.reset();
      }
    }
  }
};
</script>
<style>
body, html {
  overflow-x: hidden;
  margin: 0;
  padding: 0px;
  background: aliceblue;
  width: 100%;
  height: 100%;
}

#container {
  height: 80%;
  margin-bottom: 50px;
}
#app {
  width: inherit;
  height: inherit;
}
</style>