LocationData

Real Time Crowd Management

Getting started with RTCM

RTCM, or Real Time Crowd Management, allows the user to define zones of interest to measure the number of people in a certain area within Belgium. This works by looking at the amount of mobile devices connected to specific cell towers/antennas in the given area. A separation between international and national numbers is available in our API.

After you define your zone(s), you can create a stream to get notified every x minutes about a specific zone. A stream expires after the specified time.

Example code

The RTCM Bin viewer is available on the Enabling github as a demonstration/example of how to consume/visualize the data that is provided by this API.

Zones

A zone can be created by providing a name and the wkt of your choice. One way to generate this wkt can be found below. Please note that the RTCM API only accepts POLYGON and POINT objects. In cases where you provide a POINT object, you'll need to specify the radius as well.

Once your create request is made, our API will divide your wkt in so-called 'bins'. These bins are rectangular bounding boxes within the Lambert azimuthal equal-area projection EPSG:3035 that are calculated according to the area of the wkt you requested. The mobile device count is calculated per bin and will be available in your stream(s).

The RTCM API also includes a feature that allows you to request this bin information for your wkt, without the actual creation of a zone. This way you can test and adapt your wkt to get the best result. For more information, please check the API docs.

More information about the bins themselves and the system used in the IDs is provided is available below

Streams

After you create your zone(s), it's time to set up a stream for one of the zones. Several things must be specified to set up your stream:

  • The zone you created before.
  • The interval of the updates being sent.
  • The endpoint type and address where you want to receive these updates. You can stream to HTTP (and HTTPS) or stream to a CloudEngine script, to leverage its scripting and data transformation capabilities, as well as leverage the variety of oubound endpoints (for easy integration with Microsoft Azure, MQTT, sFTP etc).
  • The duration of your stream.

Important note about HTTP streams

When streaming to a HTTP endpoint, upon creation of the stream our systems will first issue an OPTIONS call to your web server. The reason for this call is to ensure your HTTP endpoint is properly configured to accept our POST requests with the data. OPTIONS for API usage is defined via the "Allow" header as defined under RFC7231, and NOT via CORS headers. As a reminder and according to w3c specifications, OPTIONS calls must be processed without authentication.

As mentioned earlier, a zone is divided in bins (cells) and will be available in your stream(s). Response payload example:

[
  {
    "binId": "250mE392400N309775",
    "national": 314,
    "international": 21
  },
  {
    "binId": "250mE392375N309750",
    "national": 236,
    "international": 16
  },
  {
    "binId": "250mE392400N309575",
    "national": 103,
    "international": 2
  },
  {
    "binId": "250mE392450N309700",
    "national": 277,
    "international": 21
  },
  ...
]

Disclaimer: The data used has an accuracy at cell level

Well Known Text (WKT)

A wkt (well-known text), is a way to represent vector geometry objects. The RTCM API accepts two types of wkt: POLYGON and POINT. Please make sure that the wkt is provided in the Lambert azimuthal equal-area projection EPSG:3035.

Generating WKT's

Follow the steps below to generate a wkt for an area of interest.

  1. Download QGIS for your OS.
  2. Open QGIS.
  3. Navigate to Plugins > Manage.
  4. Install following plugins: Get WKT and OpenLayersPlugin (for 3.0+ you might have to enable experimental plugins to be able to install this).
  5. Add OpenStreetMap to the Layers Panel following these steps:

Web -> OpenLayers Plugin -> OpenStreetMap -> OpenStreetMap The OpenStreetMap layer will be shown in the Layer Panel. Layer panel

  1. Click EPSG:3857 (bottom right) and search for EPSG:3035, select it and click Apply + OK. Project properties

  2. Add a temporary layer by navigating to: Layer > Create Layer > New Temporary Scratch Layer…

Make sure to select the desired geometry type (only POLYGON and POINT are allowed by EnCo) and select EPSG:3035 as the project. New temporary scratch layer

  1. Make sure the created layer from step 7 is selected in the Layers Panel.
  2. Make sure Toggle Editing is selected and then click Add Feature. Add feature
  3. The following step is different depending on the geometry type chosen in step 7.
  • Point: just left-click on the map on the area you are interested in. A dot will be shown on the map.
  • Polygon: left click on the map to add corners to your polygon. When you're done, just right click (anywhere is fine) and the polygon will be created.
  1. Click on the icon Select Features by area or single click and click on the created point or polygon from step 10. Your selected area should be colored in yellow. Select feature

  2. Click the wkt icon and your POLYGON or POINT wkt will be shown. This wkt can be used for the RTCM API. Point example Polygon example

Bins

The bins are based on an EEA reference grid within the Lambert azimuthal equal-area projection EPSG:3035.

Each bin is a square with a size ranging from 100 meters, up to 100km. The size is automatically chosen depending on the surface area of you wkt, with as ultimate goal that the total number of bins should not exceed 1,000 by much. The table below gives an overview of the relation between the area covered by the request (only the overlap with our coverage area is taken in to account) and the resulting bin size:

Lower area limit Upper area limit Bin size
0 10km2 100m
10km2 62.5 250m
62.5km2 250km2 500m
250km2 262.5km2 750m
262.5km2 1000km2 1km
1000km2 6250km2 2.5km
6250km2 25000km2 5km
25000km2 7.5km

A bin is identified with an ID from which you can also derive the area itself. Let's look at "100mE39412N30758" for example.

  • The first part is the size, in this case the bin size is 100m.
  • Next we find the longitude in EPSG:3035. Note that insignificant zeroes are omitted, so the actual longitude is, 39412 times 100m East = 3941200.
  • And finally the latitude in EPSG:3035 also without the insignificant zeroes. So the actual latitude is 30758 times 100m North = 3075800.

If we take into account that the coordinates in EPSG:3035 are specified in meters, we can even reconstruct the wkt for this bin, it is in fact:

POLYGON((3941200 3075800,3941300 3075800,3941300 3075900,3941200 3075900,3941200 3075800))

When the bin size is 250m, only one 0 can be omitted, so for example "250mE392375N309750" means:

  • Size 250m
  • Longitude = 392375 times 10m East = 3923750
  • Latitude 309750 times 10m North = 3097500.

And in this case we can derive that the wkt should be:

POLYGON((3923750 3097500,3924000 3097500,3924000 3097750,3923750 3097750,3923750 3097500))

Note: You can use the QuickWKT plugin in QGIS described above to visualize these areas. Once it is installed select QuickWKT from the plugin menu and paste your WKT in the dialog (make sure that you are using EPSG:3035 before using the plugin)

RTCM API

The RTCM (Real Time Crowd Management) API allows you to manage your zones and streams.

Base url: https://api.enco.io/rtcm/1.0.0

Header Value Required
Authorization Bearer <access token> Yes
Accept application/json Yes
Content-type application/json Yes

The access_token should be retrieved via the authentication API. See the Authentication page

/zones GET
/zones POST
/zones/info POST
/zones/{name} GET
/zones/{name}    DELETE

/streams GET
/streams POST
/streams/{id} GET
/streams/{id} DELETE

/logs GET

/zones GET

Returns a list of zones defined for your account.

Response payload

[
  {
    "name": {string},
    "wkt": {string},
    "surface": {number},
    "granularity": {integer},
    "bins": [
      {
        "cellcode": {string},
        "wkt": {string}
      }
    ]
  }
]

/zones POST

Define a new zone. Zones are defined using a WKT string, it is required that this WKT string is either a Polygon or a Point. When defining a zone with a point, please use the radius property to set a radius around this point.

Request payload

{
  "name*": {string},
  "wkt*": {string},
  "radius": {integer}
}

ESPG:3035 More information can be found here.

Response payload

{
  "name": {string},
  "wkt": {string},
  "surface": {number},
  "granularity": {integer},
  "bins": [
    {
      "cellcode": {string},
      "wkt": {string}
    }
  ]
}

/zones/info POST

Get information about a new zone without defining it. Use this method to try out how big a zone will be and in how much bins it will be divided.

Request payload

{
  "name*": {string},
  "wkt*": {string},
  "radius": {integer}
}

ESPG:3035 More information can be found here.

Response payload

{
  "name": {string},
  "wkt": {string},
  "surface": {number},
  "granularity": {integer},
  "bins": [
    {
      "cellcode": {string},
      "wkt": {string}
    }
  ]
}

/zones/{name} GET

Get information about a zone with given name.

Response payload

{
  "name": {string},
  "wkt": {string},
  "surface": {number},
  "granularity": {integer},
  "bins": [
    {
      "cellcode": {string},
      "wkt": {string}
    }
  ]
}

/zones/{name} DELETE

Delete a zone with given name.

/streams GET

Get a list of streams defined for your account.

Response payload

[
  {
    "id": {string},
    "zoneName": {string},
    "endpoint": {
      "type": {string} ["HTTP"],
      "address": {string},
      "authorization": {
        "type": {string} ["NONE", "BASIC"],
        "username": {string},
        "password": {string}
      }
    },
    "state": {string} ["ACTIVE", "PENDING", "STOPPED"],
    "interval": {integer} [1, 5],
    "duration": {integer} [1, 3, 6, 12],
    "timeStart": {string:datetime},
    "timeEnd": {string:datetime}
  }
]

/streams POST

Sets up a new stream.

Request payload

{
  "zoneName*": {string},
  "endpoint*": {
    "type*": {string} ["HTTP"],
    "address*": {string},
    "authorization": {
      "type*": {string} ["NONE", "BASIC"],
      "username": {string},
      "password": {string}
    }
  },
  "interval*": {integer} [1, 5],
  "duration*": {integer} [1, 3, 6, 12],
}

Response payload

{
  "id": {string},
  "zoneName": {string},
  "endpoint": {
    "type": {string} ["HTTP"],
    "address": {string},
    "authorization": {
      "type": {string} ["NONE", "BASIC"],
      "username": {string},
      "password": {string}
    }
  },
  "state": {string} ["ACTIVE", "PENDING", "STOPPED"],
  "interval": {integer} [1, 5],
  "duration": {integer} [1, 3, 6, 12],
  "timeStart": {string:datetime},
  "timeEnd": {string:datetime}
}

/streams/{id} GET

Fetch the stream definition with given id.

Response payload

{
  "id": {string},
  "zoneName": {string},
  "endpoint": {
    "type": {string} ["HTTP"],
    "address": {string},
    "authorization": {
      "type": {string} ["NONE", "BASIC"],
      "username": {string},
      "password": {string}
    }
  },
  "state": {string} ["ACTIVE", "PENDING", "STOPPED"],
  "interval": {integer} [1, 5],
  "duration": {integer} [1, 3, 6, 12],
  "timeStart": {string:datetime},
  "timeEnd": {string:datetime}
}

/streams/{id} DELETE

Stops and deletes a stream with given id.

/logs GET

Returns logs for the RTCM API

Parameter Description Type Required
type The type of logs to be retrieved. "stream-error" string
year The year to search in integer yes
month The month to search in integer yes
function Function to execute on the logs. "interval": retrieves all results in the specified interval. "groupByDay": retrieves an overview of the month specified string yes
startTime mandatory with "interval" function datetime no
endTime mandatory with "interval" function datetime no
page Used for paging. You can specify "first", "next", "previous" or "last" page. string no
pageref Used for paging. Identifies where to start the next or previous page. string no
limit Limits the amount of results to be returned integer no

Response payload

[
  {
    "timestamp" : {string:datetime},
    "rtcmMessage" : {string},
    "rtcmStreamId": {integer}
  }
]

API authentication

API Solutions uses OAuth2 to protect API resources. The OAuth2 specification has become the predominant standard for securing RESTful APIs and identity delegation.

In order to gain access to the resources exposed by your API assets, you will need to pass along a valid OAuth2 bearer access token. Here is how you can generate such a token.

Obtaining your OAuth2 Application Keys

Each project you create through the API Solutions Market will result in the creation of a unique pair of OAuth2 application keys. To retrieve your keys, proceed as follows:

  • First, log in and visit your dashboard on the portal. Click the "TOKEN" menu.
  • This will result in your application keys to be shown. These keys can be used to access API resources exposed by any API asset to which you subscribed, within the scope of the selected project.

OAuth 2 Keys

Your application keys are sensitive information; keep them private at all time!

Make sure to store your application keys in a safe way, avoiding them to leak or be stolen by an unintended audience. They are quite sensitive, in that anyone obtaining them will be able to gain access to your assets. In case your application keys would become compromised, contact us through support and we'll revoke them to block access, and provide you with a new pair. This is also the reason why all API traffic should pass through secured HTTP, and why we do not support plain HTTP.

Generating a fresh bearer access token

A bearer access token is a self-contained unique identifier through which you can gain access to API resources. Before elaborating on how you can obtain such type of token, please note that these tokens are valid for a limited time span of 1 hour (or less, if explicitly revoked).

You can obtain a new token by issuing the following request against the server https://api.enco.io :

/token POST

Issue a request to https://api.enco.io/token, adding the following headers and body:

Request

curl -X POST \
  'https://api.enco.io/token?grant_type=client_credentials&scope=openid&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&Accept=application/json' \
  -H 'Content-Type: application/x-www-form-urlencoded' 

Response payload

{ 
  "scope": "openid", 
  "token_type": "Bearer", 
  "expires_in": {number}, 
  "access_token": {string}
}

The field accesstoken in the response contains your token. The field expiresin will show you the remaining validity of your token, in seconds.

Single active access token
Within the context of a single application, you will only have a single active access token at any time. If you would request a new token using the above request message while the previously issued token has not yet expired, you will get back the previous token. To obtain a new one, revoke the old token; then generate a new one.

Code Samples
To help you getting started on implementing this authentication in your code, you can find some samples on our Github.

Revoking an access token

This procedure should be used when your token has been compromised (leaked, stolen, etc.), or if you want to generate another token, but your old token is still valid.

/revoke POST

Issue a request to https://api.enco.io/revoke, adding the following headers and payload:

Header Value Required
Content-type application/x-www-form-urlencoded Yes

Request payload

token=<old-access-token-to-be-revoked>&client_id=<app-consumer-key>&client_secret=<app-consumer-secret>

Creating permanent token

You can create permanent tokens from the "TOKEN" menu of your profile's dashboard. Just click on "Add a new token" to create a new permanent token. Several permanent tokens can be created for the same account.

Permanent token

Your permanent token is sensitive information; keep it private at all time!

Make sure to store your permanent tokens in a safe way, avoiding them to leak or be stolen by an unintended audience. They are quite sensitive, in that anyone obtaining them will be able to gain access to your assets. In case a permanent token would become compromised or not needed anymore, delete this token from your "TOKEN" dashbload by clicking on the red cross next to it.

All set to call your API!

Once a valid access token has been generated, it should be added to request messages. The token should be passed in an HTTP header named Authorization, which should be assigned the value of Bearer, followed by a single space, and immediately followed by the access token. Note the single space between ‘Bearer’ and the token.

curl -i -X GET -H "Accept:application/json" -H "Authorization: Bearer <active-access-token>" https://api.enco.io/lora4maker/0.0.1/device

Blog articles

Find all articles including tutorials and customer cases related to Real Time Crowd Management on our blog.

Terms & Conditions

Proximus RTCM API Terms and Conditions

Never miss a thing

Stay informed on offers, promotions and platform updates by e-mail. You can unsubscribe at any time.

Proximus logo

All rights reserved. © 2020 Proximus | Cookie policy

This site was created and is managed in accordance with Belgian law.

Proximus API Solutions - powered by ClearMedia NV. Merksemsesteenweg 148, B-2100 Deurne.

BE 0831.425.897