cloudvision-connector
    TypeScript icon, indicating that this package has built-in type declarations

    4.12.0 • Public • Published

    CloudVision Connector

    The CloudVision Connector is a simple JavaScript module using WebSockets that enables you to transmit data over an open connection with the CloudVision API server. The CloudVision Connector supports subscribing to data, which lets clients receive streaming updates as data changes in real-time.

    Installation

    with yarn:

    yarn add cloudvision-connector

    or npm:

    npm install --save cloudvision-connector

    Usage

    Getting Started

    Quick introduction into to how to connect to the API server

    Getting Datasets

    const parseDatasets = (err, datasets) => {...};
    // Add a callback
    connector.getDatasets(parseDatasets);
    
    // datasets returned in `parseDatasets` is a list of dataset ids
    datasets = [
      'JPE15076475',
      'JPE12111270',
      'app-turbine',
      'HSH14525062',
      'CloudTracer',
    ];

    You can also get datasets use getWithOptions (see details below). This is done by calling getWithOptions with Connector.DEVICES_DATASET_ID as the first parameter.

    const parseDevices = (err, datasets) => {...};
    const query = Connector.DEVICES_DATASET_ID;
    
    connector.getWithOptions(query, handleResponse);

    Getting Data

    The CloudVision Connector allows you to query notifications for multiple paths on a dataset, as well as multiple paths within multiple datasets.

    getWithOptions(query, callback, options)

    Returns all notifications that match the given query and options.

    • query: an object in the shape of a query (see "Query")
    • callback: a function that is called when notifications are received (see "Notifications Callback")
    • options: an object in the shape of query options (see "Options")
    • Returns: the token (unique identifier) of the request.
    Example
    const query = [{
      dataset: {
        type: 'app',
        name: 'analytics'
      },
      paths: [{
        path_elements: ['events','activeEvents'],
      }],
    }, {
      dataset: {
        type: 'app',
        name: 'analytics'
      },
      paths: [{
        path_elements: ['tags','stats'],
      }, {
        path_elements: ['BugAlerts','bugs'],
      }],
    }];
    const handleResponse = (err, res, status) => {...};
    const options = {
      start: 1504113817725,
      end: 1504113917725,
    };
    
    // open the stream
    const token = connector.getWithOptions(query, handleResponse), options;

    Subscribing to Data

    In addition to getting data, you can use the same query to subscribe to any updates to the data as it changes.

    getAndSubscribe(query, callback, options)

    Returns all notifications that match the given query and options, in addition to subscribing to updates. This will return notifications as new updates to the data requested come in.

    • query: an object in the shape of a query (see "Query")
    • callback: a function that is called when notifications are received (see "Notifications Callback")
    • options: an object in the shape of query options (see "Options")
    • Returns: a the subscription identifier. This is an object constaining the token and the callback
    Example
    const query = [{
      dataset: {
        type: 'app',
        name: 'analytics'
      },
      paths: [{
        path_elements: ['events','activeEvents'],
      }],
    }, {
      dataset: {
        type: 'app',
        name: 'analytics'
      },
      paths: [{
        path_elements: ['tags','stats'],
      }, {
        path_elements: ['BugAlerts','bugs'],
      }],
    }];
    const handleResponse = (err, res, status) => {...};
    
    // open the stream
    const subscribptionsIdentifier = connector.subscribe(query, handleResponse);

    Notifications Callback

    This is the callback, which is called when notifications are received.

    const handler = (err, res, status, token) => {...}

    Arguments:

    • err: either a string or null. If null then there is no error. If it is a string, then an error occurred.

    • res: an object with the properties dataset and notifications. e.g.

      res = {
        dataset: "someDevice",
        notifications: {
          "['path', 'to', 'some', 'data']":    [...],
          "['path', 'to', 'another', 'data']": [...],
          ...
        }
      }

    Each [...] above is an array of notifications which each have a timestamp, path, collection of updates, and deletes (see "Data Model" section for more information).

    • status: An object with the status code and a message. See the "Notification Statuses" section for more details.
    • token: The token id that was created for the request.

    Notification Statuses

    A status object has an optional message key containing a string describing the status, in addition to a code key with the code number.

    Possible status codes: |Code|JS Constant|Description| |1001|EOF_CODE|Signals that this is the last notification for the request| |3001|ACTIVE_CODE|Signals that the stream (subscription), has been established|

    Options

    There are a number of options you can supply to the query which limit it's scope. Options are passed as an object, where the key is the name of the option and the value is the value for that option.

    The options are start, end and versions. There are different combinations of options that are valid, each of them is listed below.

    Range query (returns one or more data points):

    • start: the epoch timestamp in (milliseconds) of the first data point.
    • end: the epoch timestamp in (milliseconds) of the last data point.

    Point in time query (returns exactly one data point):

    • end: the epoch timestamp in (milliseconds) of the data point.

    Limit query (returns versions + 1 number of data points):

    • end: the epoch timestamp in (milliseconds) of the last data point.
    • versions: the number of versions of data (in the past) to request in addition to the data point for end.

    Query

    A query is an array of objects with a dataset key and paths key.

    The value of each dataset is an object with a type (the type of the dataset, which can be device or app) and name (the identifier for the dataset e.g. 'JPE13262133') key.

    The value of the paths key is an array of objects with a path_elements (an array of the component parts of a path) key and an optional keys key. The value of keys is an object that defines the shape of how you want the data to be returned. Think of it like a map that points to certain fields in CloudVision api.

    query = [{
      dataset: {
        type: <dataset type>,
        name: <dataset>,
      },
      paths: [{
        path_elements: <path 1>,
      }, {
        path_elements: <path 2>,
        keys: {
          [any_custom_key]: {
            key: <key 1>,
          }
        }
      }],
    }];
    Example
    const handleResponse = (err, res) => {...};
    const query = [{
      dataset: {
        type: 'app'.
        name: 'analytics',
      },
      paths: [{
        path_elements: ['events', 'activeEvents'],
      }, {
        path_elements: ['Logs', 'var', 'log', 'messages'],
        keys: {
          logMessage: {
            key: 'text',
          }
         }
      }],
    }];
    const options = {
      start: 1504113817725,
      end: 1504113917725,
    };
    
    connector.getWithOptions(query, null, options, handleResponse);

    Getting Data

    More in depth information on how to query different data.

    Connecting to the Server

    You can connect to the CloudVision API server with any kind of WebSocket. This connector uses the regular browser WebSocket, but it also allows you to pass in your own custom implementation of a standard WebSocket.

    You can also connect via secure WebSockets (wss), which uses the same SSL certificate as https does.

    If you are using wss, you will need to get the authentication cookie from the CVP auth service.

    const authUrl = 'https://example.cloudvision.api-server/cvpservice/login/authenticate.do';
    const userId = 'user';
    const password = 'my-password';
    
    function loggedIn() {
      console.log('You are logged in');
    }
    
    function authFailure(message) {
      console.log('Auth Failure:', message);
    }
    
    window
      .fetch(authUrl, {
        method: 'POST',
        credentials: 'include',
        body: JSON.stringify({ userId, password }),
      })
      .then((response) => {
        // Handle JSON response
        return response.json();
      })
      .then((jsonResp) => {
        if (jsonResp.sessionId) {
          // We got a session id, so we are now logged in
          loggedIn();
        } else if (jsonResp.errorMessage) {
          // Handle authentication failure
          authFailure(jsonResp.errorMessage);
        }
      })
      .catch
      // Error handling for failed request
      ();

    Once you have completed this request successfully, you will have the authentication cookie which will be sent along with the request to open the WebSocket.

    // Import module
    import Connector from 'cloudvision-connector';
    
    // Create the connection
    const connector = new Connector();
    
    // Start the connection
    connector.run('ws://example.cloudvision.api-server/api/v3/wrpc/');
    
    // Start the connection with a custom WebSocket
    class CustomWS extends WebSocket {
     ...
    };
    
    const connectorWithCustomWS = new Connector(CustomWS);
    connectorWithCustomWS.runWithWs('ws://example.cloudvision.api-server/api/v3/wrpc/');
    
    // Start a secure authenticated connection. NOTE: the `wss` vs `ws`
    connector.run('wss://example.cloudvision.api-server/api/v3/wrpc/');

    Listening to the Connection Status

    The Connector.connection function adds a status-accepting callback to a Connector and returns an unbinding function that may be used to remove the callback. The status passed to the callback is either Connector.CONNECTED, or Connector.DISCONNECTED. Additionally, the WebSocket event (see WebSocket documentation) is passed as the second argument.

    • Connector.CONNECTED is emitted once the WebSocket connection has been established and the client is authenticated. At this point requests can be sent and the server will start sending responses.

    • Connector.DISCONNECTED is emitted when the WebSocket is hung up.

    Example
    function statusCallback(status, wsEvent) {
      switch (status) {
        case Connector.CONNECTED:
          // react to connected event
          break;
        case Connector.DISCONNECTED:
          // react to disconnected event
          break;
      }
    }
    
    // Add callback
    const unbindStatus = connector.connection(statusCallback);
    ...
    // Remove callback when done
    unbindStatus();

    Multiple callbacks may be added to a given Connector via Connector.connection:

    // This is es6 arrow function notation (shortcut for function() {} )
    const callback1 = (status) => {...}
    const callback2 = (status) => {...}
    const unbind1 = connector.connection(callback1)
    const unbind2 = connector.connection(callback2)

    Callbacks will be called in the order in which they were added.

    Data Endcoding

    Data returned from the CloudVision APi is both JSON and NEAT (more strict MessagePack) encoded. Additionally NEAT encoded values are base64 encoded for transport. The notification body is JSON encoded, while key and value attributes of the notification are NEAT encoded. The parser inside the cloudvision-connector library takes care of decoding and encoding notifications for you. Note that when notifications are decoded they are decoded into an object keyed key the notification key. Since keys can be non strings, the key is the base64 NEAT encoded value. The value of this object contains both the decoded key and value.

    What is NEAT?

    NEAT is MessagePack with some alterations listed below:

    • All strings are binary encoded

    • Maps and Object keys are encoded in order of binary value of the key. This means { a: 'b', c: 'd' } and { c: 'd', a: 'b' } are encoded as the same NEAT value.

    • Support for pointer values via the Pointer extention type

    • Support for wildcard values via the Wildcard extention type

    Try it out

    To try out the CloudVision Connector in your browser, simply run

    npm install

    at the root

    and then

    npm run build:try

    in the packages/cloudvision-connector directory

    Then open index.html in your browser. In the developer console CloudVision Connector will be available as window.CloudVisionConnector.

    Examples

    Create the connector: conn = new window.CloudVisionConnector() Connect to an API server: conn.run('ws://example.cloudvision.api-server/api/v3/wrpc/') Run a query: conn.getWithOptions(window.CloudVisionConnector.DEVICES_DATASET_ID , (err, res) => console.log(err, res))

    Contributing

    Contributing pull requests are welcomed for this repository. Please note that all contributions require 100% code test cases and 100% code coverage, otherwise the pull request will be rejected.

    License

    The CloudVision Connector is MIT licensed.

    Install

    npm i cloudvision-connector

    DownloadsWeekly Downloads

    45

    Version

    4.12.0

    License

    MIT

    Unpacked Size

    276 kB

    Total Files

    33

    Last publish

    Collaborators

    • rufman