Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

cot-lib

Package Overview
Dependencies
Maintainers
1
Versions
42
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cot-lib

Easily consume the City of Things platform data

  • 1.0.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
2
decreased by-33.33%
Maintainers
1
Weekly downloads
 
Created
Source

The City of Things client library will help you to connect to the City of Things backend. It uses the Web Linking RFC 5988 and interprets the Link header for you. This way you can let the library follow the next/prev/last pages for you.

Installation

npm install cot-client --save

Usage

[TODO] including via Typescript of Javascript

You start by creating a CotClient object.

Creating a CotClient

A CotClient object allows you to request the basic API functions. It needs a reference to the base url of the API.

import { CotClient } from 'cot-lib';
let cotClient = new CotClient('http://my-cot-backend.eu');

Creating a SourcesClient

A SourcesClient object allows you to pre-define all the sourceIds you want to request data from simultaneously. It needs a reference to the base url of the API, but you can get it from a CotClient object too.

import { SourcesClient } from 'cot-lib';
let sourcesClient = new SourcesClient('http://my-cot-backend.eu', 'sourceId1', 'sourceId2', 'sourceId3');

or

import { CotClient, SourcesClient } from 'cot-lib';
let cotClient = new CotClient('http://my-cot-backend.eu');
let sourcesClient = cotClient.createSourcesClient('sourceId1', 'sourceId2', 'sourceId3');

Creating a LocationsClient

A LocationsClient object allows you to pre-define all the geohashes you want to request data from simultaneously. Because of the sheer amount of data, you are required to already filter on the Type you are interested in. It needs a reference to the base url of the API, but you can get it from a CotClient object too.

import { LocationsClient } from 'cot-lib';
let locationsClient = new LocationsClient('http://my-cot-backend.eu');

or

import { CotClient, LocationsClient } from 'cot-lib';
let cotClient = new CotClient('http://my-cot-backend.eu', 'typeId', 'u15kk', 'u15kh', 'u15ke');
let locationsClient = cotClient.createLocationsClient('typeId', 'u15kk', 'u15kh', 'u15ke');

About Observables

This API makes heavy use of ReactiveX Observables. They are a very modern way to do asynchronous communication. When calling subscribe(...) on an Observable, the Observable is activated and starts its work. It will asynchronously notify its different handlers. The first handler - typically called next - can be notified multiple times, everytime there is new data available, the second one handles errors and the last one is called when the Observable stream has completed its work.

Simple use of Observables

The simplest way to use them is as follows. Given a method getMyData() that returns an Observable<MyData> type. This is how you handle it:

Typescript

client.getMyData().subscribe(
    nextData => { 
        // handle nextData as its coming in, this handler will be called on every update with new data
    },
    error => {
        // do something when an error occurs
    },
    () => {
        // this handler will be called when the data streaming is complete and there is no more incoming data
    }
);

Javascript

client.getMyData().subscribe(
    function(nextData) { 
        // handle nextData as its coming in, this handler will be called on every update with new data
    },
    function(error) {
        // do something when an error occurs
    },
    function() {
        // this handler will be called when the data streaming is complete and there is no more incoming data
    }
);

There are many more things you can do with Observables, for a more comprehensive guide we refer to the ReactiveX introduction website and the RxJs github page with its excellent Readme.

What about Promises?

An Observable allows you to call the toPromise() method on it, after which it can be handled as a normal Promise with a then(...) method. Be aware though that to first argument callback of the then(...) method will only be called with the very last next update of the observable. So this will not always behave as you would expect.

However we remediated this with two Util methods collectOne(...) and collectMultiple(...) that are further explained in the API section. They allow for usage that is more in line with the Promises workflow.

Types

The API uses a couple of Types that it returns.

Type

A Type object describes sources of the same type. It has an id to uniquely identify it. It has a finalizationDelay that determines the delay until the data is considered unchanged and indefinitely cacheable, it has a preferredGranularity that determines the default size of returned TemperalPage brackets for Sources of this Type. At last is has a schema that defines the structure and meaning of the fields in the Source data.

{
    "id": "bpost.car",
    "finalizationDelay": 0,
    "preferredGranularity": "HOURLY",
    "schema": {
      "co2": "IntNumber (The co2 level.)"
    }
}
  

Source

A Source represents a sensor, actuator or data producer of some sort. It has an id to uniquely identify it. It has a name which is a human readable label for this Source. At last it has a typeRefs field which contains a set of typeId strings that define the Types this Source belongs to.

{
    "id": "Car1",
    "name": "Bpost Mockup Car 1",
    "typeRefs": [
      "bpost.car"
    ]
}

TemporalPage

A TemporalPage object is a bucket (like a page in a pageing mechanism, but spread by time instead of amount). This object contains the parsed Link header values, so they can easily be accessed.

{
    "data": {TemporalPageData},
    "link": {TemporalPageLink}
}

TemporalPageData

A TemporalPageData object is just the data part of a TemporalPage. It is used when the TemporalPageLink field is no longer relevant in the returned data of a TemporalPage object. (e.g. when requesting data of an interval of multiple pages). (note that next, prev and last fields are optional and not always present).

{
    "name": "Car1" or ["Car1", "Car2"],
    "columns": ["timestamp","co2","temperature"]
    "values": [
        [1483201200, 430, 297.15],
        [1483201202, 432, 297.13],
        [1483201212, 433, 300.01],
        [1483201301, 427, 301.14],
        [1483201302, 419, 298.06],
        [1483201331, 418, 299.48],
        [1483201340, 424, 299.82],
    ]
}

A TemporalPageLink object contains the parsed Link header values relevant for the City of Things client to request follow up requests. It parses the Link header according to the RFC 5988 specification.

{
    "self": "/sources/Car1/events/20161231/16?from=1483201200",
    "next": "/sources/Car1/events/20161231/17",
    "prev": "/sources/Car1/events/20161231/16?to=1483201200",
    "last": "/sources/Car1/events/20161231/20?to=1483215300",
}

CotClient API

CotClient(host: string): CotClient

Constructor, call as new CotClient('http://my-cot.backend.eu'). This will construct a new cotClient to work with.

cotClient.getTypes(): Observable<Type[]>

Returns an Observable containing an array with all available Type objects.

cotClient.getType(typeId: string): Observable<Type>

Returns an Observable containing Type information of the Type with the given typeId.

cotClient.getSourcesOf(typeId: string): Observable<Source[]>

Returns an Observable containing an array of Source objects belonging to the Type with the given typeId.

cotClient.getSources(): Observable<Source[]>

Returns an Observable containing an array of all Source objects currently available.

cotClient.getSource(sourceId: string): Observable<Source>

Returns an Observable containing the Source object with the given sourceId.

cotClient.getData(sourceId: string, from?: number, to?: number): Observable<TemporalPage>

Returns an Observable containing a TemporalPage object with data from a Source defined by a given sourceId. Results vary according to parameters:

  • No from and to parameters: latest data TemporalPage is returned.
  • If from and/or to specified: from TemporalPage is returned (last link will be present if to is also specified).

The arguments from and to are UNIX (UTC) timestamps.

cotClient.getDataInterval(sourceId: string, from: number, to: number): Observable<TemporalPageData>

Returns an Observable containing a TemporalPageData object with data from a Source defined by a given sourceId. The TemporalPageData contains the aggregated interval. This method automatically calls the necessary subsequent requests. On every response, the Observable calls its next handler with the newly received data. It is up to the developer to listen for this incoming data and update the already received data.

If you want to wait and only call a handler when all data has come in, use the Utils.collectOne(...) method on this Observable. More information on this method can be found at the end of this API section.

The arguments from and to are UNIX (UTC) timestamps.

cotClient.getDataIn(geohash: string, typeId: string, from?: number, to?: number): Observable<TemporalPage>

Returns an Observable containing a TemporalPage object with data from Sources belonging to a given typeId, within the given geohash. Results vary according to parameters:

  • No from and to parameters: latest data TemporalPage is returned.
  • If from and/or to specified: from TemporalPage is returned (last link will be present if to is also specified).

The arguments from and to are UNIX (UTC) timestamps.

cotClient.getDataIntervalIn(geohash string, typeId: string, from: number, to: number): Observable<TemporalPageData>

Returns an Observable containing a TemporalPageData object with data from Sources belonging to a given typeId, within the given geohash. The TemporalPageData contains the aggregated interval. This method automatically calls the necessary subsequent requests. On every response, the Observable calls its next handler with the newly received data.

It is up to the developer to listen for this incoming data and update the already received data!

If you want to wait and only call a handler when all data has come in, use the Utils.collectOne(...) method on this Observable. More information on this method can be found at the end of this API section.

The arguments from and to are UNIX (UTC) timestamps.

cotClient.createSourcesClient(...sourceIds: string[]): SourcesClient

A convenience method to create a new SourcesClient object, by reusing the host setting from the CotClient.

cotClient.createLocationsClient(...sourceIds: string[]): LocationsClient

A convenience method to create a new LocationsClient object, by reusing the host setting from the CotClient.

SourcesClient API

SourcesClient(host: string, ...sourceIds: string[]): SourcesClient

Constructor, call as new SourcesClient('http://my-cot.backend.eu', 'sourceId1','sourceId2', 'sourceId3'). This will construct a new sourcesClient to work with.

sourcesClient.getData(from?: number, to?: number): Observable<TemporalPage[]>

Returns an Observable containing an array of TemporalPage objects, each with data from a Source defined by the registered sourceIds of this sourceClient. Results vary according to parameters:

  • No from and to parameters: latest data TemporalPages are returned.
  • If from and/or to specified: from TemporalPages are returned (last link will be present if to is also specified).

The arguments from and to are UNIX (UTC) timestamps.

sourcesClient.getDataInterval(sourceId: string, from: number, to: number): Observable<TemporalPageData>

Returns an Observable containing a TemporalPageData object with data from all Source defined by the registered sourceIds of this sourcesClient. The TemporalPageData contains the aggregated interval. This method automatically calls the necessary subsequent requests. On every response, the Observable calls its next handler with the newly received data.

It is up to the developer to listen for this incoming data and update the already received data!

If you want to wait and only call a handler when all data has come in, use the Utils.collectMany(...) method on this Observable. More information on this method can be found at the end of this API section.

The arguments from and to are UNIX (UTC) timestamps.

LocationsClient API

LocationsClient(host: string, ...geohashes: string[]): SourcesClient

Constructor, call as new LocationsClient('http://my-cot.backend.eu', 'geohash1','geohash2', 'geohash3'). This will construct a new LocationsClient to work with.

locationsClient.getData(typeId: string, from?: number, to?: number): Observable<TemporalPage[]>

Returns an Observable containing an array of TemporalPage objects, each with data from a location defined by the registered geohashes of this locationsClient. Because of the sheer amount of data, a typeId must be given to limit the results to Sources from this Type. Results vary according to parameters:

  • No from and to parameters: latest data TemporalPages are returned.
  • If from and/or to specified: from TemporalPages are returned (last link will be present if to is also specified).

The arguments from and to are UNIX (UTC) timestamps.

locationsClient.getDataInterval(sourceId: string, from: number, to: number): Observable<TemporalPageData>

Returns an Observable containing a TemporalPageData object with data from all locations defined by the registered geohashes of this locationsClient. Because of the sheer amount of data, a typeId must be given to limit the results to Sources from this Type. The TemporalPageData contains the aggregated interval. This method automatically calls the necessary subsequent requests. On every response, the Observable calls its next handler with the newly received data.

It is up to the developer to listen for this incoming data and update the already received data!

If you want to wait and only call a handler when all data has come in, use the Utils.collectMany(...) method on this Observable. More information on this method can be found at the end of this API section.

The arguments from and to are UNIX (UTC) timestamps.

Utils API

The Utils class contains some static methods that can be helpful when working with the City of Things cilent library.

Utils.timestampOf(year: number, month: number, day?: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number): number

Returns the unix (UTC) timestamp for the given date parameters. The arguments are considered to be in UTC time.

ArgumentOptionalDescription
yearnoFour digit number
monthnoThe month in the year (1-12)
dayyesThe day of the month (1-31)
hoursyesThe hour of the day (0-23)
minutesyesThe minute of the day (0-59)
secondsyesThe seconds of the day (0-59)
millisecondsyesThe milliseconds of the day (0-999)

Utils.collectOne(observable: Observable<TemporalPageData>, callback: (data: TemporalPageData) => any, error?: (error: Error) => any*): void

This utility method will subscribe to an Observable<TemporalPageData> and collect the results that are sent through on each update of the next handler. Once it is complete, the callback handler will be called with the complete collected data as an argument. An optional error handler is called with the Error object, if one occurs.

Note: Use this in conjunction with CotClient getDataInterval methods.**

import { CotClient, Utils } from 'cot-lib';

testMethod() {
    let client = new CotClient('http://my-cot-endpoint.eu');
    let from = Utils.timestampOf(2017, 3, 1, 0, 0, 0, 0);
    let to = Utils.timestampOf(2017, 4, 1, 0, 0, 0, 0);
    let observable = client.getDataIntervalIn('u15kk', 'bpost.cars', from, to);

    Util.collectOne(observable, temporalPageData => {
      console.log(temporalPageData);
    });
  }

Utils.encodeAsGoehash(lat: number, lng: number, precision: number = 9): string

Encodes a latitude-longitude point as a geohash with the given precision.

ArgumentDescription
latLatitude of point
lngLongitude of point
precisionCharacter length of geohash (defaults to 9)

Utils.decodeFromGeohash(geohash: string): {"latitude": number, "longitude": number}

Decode a given geohash as a latitude-longitude point.

Utils.collectMany(observable: Observable<TemporalPageData>, callback: (data: TemporalPageData[]) => any, error?: (error: Error) => any*): void

This utility method will subscribe to an Observable<TemporalPageData> and collect the results that are sent through on each update of the next handler for each endpoint. It will send these updates as an array of TemporalPageData objects. Once it is complete, the callback handler will be called with the complete collected data as an argument, this is again an array of TemporalPageData objects, as many as there are registered sourceIds for a SourcesClient or geohashes for a LocationsClient. An optional error handler is called with the Error object, if one occurs.

Note: Use this in conjunction with SourcesClient and LocationsClient getDataInterval methods.**

import { SourcesClient, Utils } from 'cot-lib';

testMethod() {
    let sclient = new SourcesClient('http://my-cot-endpoint.eu', 'Car1', 'Car2', 'Car3', 'Car4');
    let from = Utils.timestampOf(2017, 3, 1, 0, 0, 0, 0);
    let to = Utils.timestampOf(2017, 4, 1, 0, 0, 0, 0);
    let observable = sclient.getDataInterval(from, to);

    Util.collectMany(observable, collectedDataArray => {
      collectedDataArray.forEach(temporalPageData => {
        console.log(temporalPageData);
      });
    });
  }

Keywords

FAQs

Package last updated on 07 Apr 2017

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc