Link Search Menu Expand Document

RMS Telemetry Interface

May 15 2023 at 12:00 AM

  1. Introduction
  2. Aim
  3. Approach
    1. Device Functionality Overview
      1. Capability
      2. Protocol information
    2. Integrations plan
      1. Design specifications
  4. Usage
    1. Steps on how to deploy and configure the driver
    2. Device Configuration Example and walkthrough
    3. Available Commander Endpoints
    4. GUI Example
  5. External References
  6. Release Notes

Introduction

Remote Metering Solutions (RMS) supply best-practice end-to-end utility metering tech and recovery solutions and services that property owners, tenants, residents and consumers can trust.

RMS

Figure 1 - Remote Metering Solutions (RMS)

For more infomation on RMS, visit their website by clicking on this link https://www.remotemetering.net/.

Aim

Resource usage monitoring is one of many key features in the IoT industry. Remote Metering Solutions (RMS) provides sensors that do this type of data collection. This solution addresses:

  • Water usage monitoring
  • Electricity usage monitoring

Approach

Device Functionality Overview

RMS sensors are placed on water and electricity access points to measure the usage passing by. Below is a high level flow diagram indicating the data flow from hardware device all the way through to this driver.

RMS

Figure 2 - High Level Flow Diagram

Capability

The energy meters can provide us with the following types of readings:

  • Forward Active Energy
  • Reactive Energy
  • Reverse Active Energy
  • Together with the above, it also gives the direction e.g. forward/backward

While the water meters can provide the following types of readings:

  • Liters used
  • The direction of usage e.g. forward/backward

Protocol information

The RMS backend has a REST API from where data is pulled/queried and thus only uses the HTTP protocol. Below is the sequence in which meter readings can be pulled from the RMS backend.

OrderDescriptionURLComments
1Auth Requesthttps://meters.rmsconnect.net/api/loginPOST the user name and password to the url. Make sure that the “Content-Type”, ‘application/json’ is added to your requests header.
2Auth Response-Parse the response and extract the bearer token.
3Request Meter Listhttps://meters.rmsconnect.net/api/meters/listPOST a request containing the number of wanted meters as well the paging token named “after” which can either be blank i.e. “” or contain the paging pointer. Remember to use ‘Bearer Token’ as the Authorization with the token extracted in the auth response and make sure that the “Content-Type”, ‘application/json’ is added to your requests header.
4Parse Meter Response-Parse, extract and store the received list of meters. You will also receive a paging object, use this and repeat step 3 until there are no more meters received.
5Request Meter Readingshttps://meters.rmsconnect.net/api/meters/readings?id=123456POST a request containing an array of meter ids who’s readings you are interested in and include date range (start/end date) for the readings you require. Again, make sure that the “Content-Type”, ‘application/json’ is added to your requests header and that the Authorization is set to ‘Bearer Token’.
6Parse Meter Reading Response-Parse, extract and store the meter readings received.

Here are sample JSON packed for the above explained transactions:

  • Send auth request
{
  "username": "********",
  "password": "******"
}
  • Receive an auth response
{
  "id": "1******-e**-4****-***1-1*******",
  "username": "*********",
  "email": "*******",
  "name": "IoT nxt",
  "firstName": "IoT",
  "lastName": "nxt",
  "token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJheU11MWVSQ0wyRERfM0ltakVFWk5ZMmxNOWZSLU5pSmZqUlhQeGU3aTdnIn0.eyJleHAiOjE2NjkyODU2NzEsImlhdCI6MTY2OTI3ODQ3MSwianRpIjoiZWZlYjRkNDctMmNiMy00OTc0LTk3MGUtMGZmMGY4YjYxNzdjIiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50LnJtc2Nvbm5lY3QubmV0L2F1dGgvcmVhbG1zL3JtcyIsImF1ZCI6WyJhY2NvdW50cy1ycyIsInBheW1lbnRzLWFwaSIsIndhbGxldHMtcnMiLCJ3YWxsZXQtYXBpIiwicGF5bWVudC1nYXRld2F5LWFkbWluLXVpIiwicGF5bWVudHMtcmVjb24tYXBpIiwiY2FzaC1wYXltZW50cy1hcGkiLCJwYXltZW50LWdhdGV3YXktYXBpIiwiaXNzdWUtdHJhY2tlci11aSIsImFjY291bnQiXSwic3ViIjoiMjYzMDEyMWQtZTk1Yy00MzBhLWE3NGUtNTY1YjNkMGYxMWE1IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoibWV0ZXItc2VydmljZS1sb2dpbiIsInNlc3Npb25fc3RhdGUiOiIyZTA5MzYwOC04NjA4LTQ3M2UtYTg4OC1iZjQ5NTM5OTAzNDEiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtcm1zIiwib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7Imlzc3VlLXRyYWNrZXItdWkiOnsicm9sZXMiOlsiYWNjZXNzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBEZWZhdWx0IHByb2ZpbGUgZW1haWwiLCJzaWQiOiIyZTA5MzYwOC04NjA4LTQ3M2UtYTg4OC1iZjQ5NTM5OTAzNDEiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibmFtZSI6IklvVCBueHQiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhcGlAaW90bnh0LmNvbSIsImdpdmVuX25hbWUiOiJJb1QiLCJmYW1pbHlfbmFtZSI6Im54dCIsInVzZXJJZCI6IjFFNzhBQzRGLUVCMUQtNDBDNS1BRUMxLTFCMzYzNjIwRTUzNCIsImVtYWlsIjoiYXBpQGlvdG54dC5jb20ifQ.lwjfrlJXL9Jx3rbDfOvn056pcOmaIlaOp-G_VKrM9T6mmKtOD0gpTtTmthnZYLs1LfgFVjPI0bUT6FGhdRnuL3otnKfrOCMAKMxJZ2k_3HbHD8UsfmhugajvIipV1C0bEHslIDtm8JB2gzAD8uF_4POPvylqfyol2hdsTzx7SDYLECRb-jZnVcBGVOwPDy3CMQ1--eG5IgLD6LTBGh8mZeymjIBA3Hvg-BbH2uEtcFAGlxm_QhzGuLVDuAgGE5SSy30UK50cD7R6hSh-IOVB4d6z37Qr0QOtG0lZM5SNKmw6hdw3eExapim5i_AKq_0mk6Qnm6S3Ju9oPFxq1YfGlQ",
  "tokenExpiresAt": "2022-11-24T10:27:51.000Z",
  "refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI3M2U0MWU3MC0yMTRhLTQ4Y2UtYWRjMC00NDljMDk3MmQzYjMifQ.eyJleHAiOjE2NjkzNjQ4NzEsImlhdCI6MTY2OTI3ODQ3MSwianRpIjoiYmVjNjBkYTMtNzMzMS00ZjVmLWI0OGQtNTgzMDFhZjNkNGMxIiwiaXNzIjoiaHR0cHM6Ly9hY2NvdW50LnJtc2Nvbm5lY3QubmV0L2F1dGgvcmVhbG1zL3JtcyIsImF1ZCI6Imh0dHBzOi8vYWNjb3VudC5ybXNjb25uZWN0Lm5ldC9hdXRoL3JlYWxtcy9ybXMiLCJzdWIiOiIyNjMwMTIxZC1lOTVjLTQzMGEtYTc0ZS01NjViM2QwZjExYTUiLCJ0eXAiOiJSZWZyZXNoIiwiYXpwIjoibWV0ZXItc2VydmljZS1sb2dpbiIsInNlc3Npb25fc3RhdGUiOiIyZTA5MzYwOC04NjA4LTQ3M2UtYTg4OC1iZjQ5NTM5OTAzNDEiLCJzY29wZSI6Im9wZW5pZCBEZWZhdWx0IHByb2ZpbGUgZW1haWwiLCJzaWQiOiIyZTA5MzYwOC04NjA4LTQ3M2UtYTg4OC1iZjQ5NTM5OTAzNDEifQ.Wd3cvS0_tzOhyYc2ItFyuoFWkpJjS0EV0hvsR5xznhg",
  "refreshTokenExpiresAt": "2022-11-25T08:27:51.000Z"
}
  • Send a meter list request
{
    "first": 5,
    "after":""
}
  • Receive a meter list response
{
  "data": [
    {
      "id": "d*********-*9***-b***-9*******",
      "serial": "E******3",
      "__createdDate": "2018-07-16T08:29:29.589Z",
      "__lastModifiedDate": "2018-07-16T08:29:29.589Z",
      "__version": 0
    },
    {
      "id": "******4-2**c-4***-a************",
      "serial": "8**********",
      "__createdDate": "2020-04-21T13:38:49.577Z",
      "__lastModifiedDate": "2020-04-21T13:38:49.577Z",
      "__version": 0
    },
    {
      "id": "d********-0***-4***-b***-4******",
      "serial": "**********8",
      "__createdDate": "2020-03-04T12:58:28.761Z",
      "__lastModifiedDate": "2020-03-04T12:58:28.761Z",
      "__version": 0
    },
    {
      "id": "0******c-***b-***f-***5-**********f",
      "serial": "N*********",
      "__createdDate": "2021-07-02T20:07:52.924Z",
      "__lastModifiedDate": "2021-07-02T20:07:52.924Z",
      "__version": 0
    },
    {
      "id": "2********-e***-***d-**1a-*****20",
      "serial": "C-******",
      "__createdDate": "2019-05-03T05:48:35.820Z",
      "__lastModifiedDate": "2019-05-03T05:48:35.820Z",
      "__version": 0
    }
  ],
  "paging": {
    "hasNextPage": false,
    "hasPreviousPage": false,
    "cursor": {
      "before": "OGY5MzBiNmMtMmEzOC00YjYxLWFhYmUtZWM1Njg5ZTg5OGE0",
      "after": "ODNhOTAxZmItNDI3OC00NDllLWI3ZTktZmNlN2YzNjNhYTk3"
    }
  }
}
  • Send a meter reading request
{
  "ids": ["d*****-*-4*-b***-9******0*","*d********-***c-4***-a***-303********", "d******-0***-4***-****-*********", "********c-****b-****f-****-*********cf", "*********e-***a-****d-***a-********0"],
  "startDate": "2022-11-21",
  "endDate": "2022-11-22"
}
  • Receive a meter reading response
{
  "data": [
    {
      "id": "******-****c*-*****f*-****b-9*****3*2**b*",
      "serial": "*******",
      "readings": [
        {
          "measure": "forwardActiveEnergy",
          "unit": "Wh",
          "direction": "forward",
          "value": 57083651,
          "date": "2022-11-21T22:00:00.000Z"
        },
        {
          "measure": "reactiveEnergy",
          "unit": "VARh",
          "direction": "forward",
          "value": 27737128,
          "date": "2022-11-21T22:30:00.000Z"
        }
      ]
    },
    {
      "id": "******-***c-***a-a***-3*******e",
      "serial": "8S*******5",
      "readings": [
        {
          "measure": "litres",
          "unit": "l",
          "direction": "forward",
          "value": 581694,
          "date": "2022-11-21T22:00:00.000Z"
        }
      ]
    },
    {
      "id": "******00-****-***-b**9-4f********1",
      "serial": "8*E******",
      "readings": [
        {
          "measure": "litres",
          "unit": "l",
          "direction": "forward",
          "value": 3353328.72,
          "date": "2022-11-21T22:00:00.000Z"
        }
      ]
    },
    {
      "id": "***e****-****-***f-***5-3**********",
      "serial": "NE******6",
      "readings": [
        {
          "measure": "forwardActiveEnergy",
          "unit": "Wh",
          "direction": "forward",
          "value": 1********,
          "date": "2022-11-21T22:00:00.000Z"
        }
      ]
    },
    {
      "id": "2*****-****a-4***-***a-f*****0",
      "serial": "C-********",
      "readings": []
    }
  ]
}

Integrations plan

Design specifications

This driver transacts with the RMS REST API. The driver will periodically request meter readings from the RMS backend (See protocol walkthrough above).

Here is a run down of the drivers device configuration:

Device configuration options

{
  "Devices": {
    "Device1": {
      "Enabled": true,
      "Debug": true,
      "DeviceType": "***",
      "ActionDelay": 30000,
      "RegisterAsGateway": true,
      "BaseHostUrl": "https://meters.********.net",
      "LoginRoute": "/***/*****",
      "MeterRoute": "/***/******/****",
      "MeterReadingsRoute": "/***/******/readings?id=123456",
      "LoginUsername": "***********",
      "LoginPassword": "*******",
      "MeterListBatchSize": 30,
      "ProcessBoundedCapacity": 100,
      "ProcessMaxDegreeOfParallelism": 50,
      "HistoricHourOffset": -6
    }
  }
}

Device configuration definitions

PropertyDescriptionTypeDefaults 
 Device1The device name for this device. This has to be specified.string-
 EnabledGets or sets whether this device is enabled.boolfalse????
 DebugGets or sets whether debug information is written to console/log file for this specific device.boolfalse???
 DeviceTypeGets or sets the type of this device. To use the rms device, this has to be ‘RmsDevice’.string-
 ActionDelayTime delay, in milliseconds, between each execution. Set this to 0 to use the default setting in Task Scheduler Options, which is normally 300000.int0, which would result in it being 300000
 RegisterAsGatewayIdentifying if incoming device data needs to be registered under a gateway entity, or device entity..booltrue
 BaseHostUrlThe base host Url from where data must be fetched.string-
 LoginRouteThe API login route.string-
 MeterRouteThe API meter route.string-
 MeterReadingsRouteThe API meter readings route.string-
 LoginUsernameThe username to login and authorize access.string-
 LoginPasswordThe password to login and authorize access.string-
 MeterListBatchSizeThe maximum number of meters to fetch per read iteration.int30
 ProcessBoundedCapacitySpecifying a bounded capacity for the actionblock size, handling meter reading calls.int500
 ProcessMaxDegreeOfParallelismMax amount of meter reading calls allowed to run in parallel.int50
 HistoricHourOffsetThe number of historic hours each fetch iteration must include for meter readings.int-4

Usage

Steps on how to deploy and configure the driver

The link below demonstrates the steps to follow when a user deploys and configures a V-Raptor driver:

Deployment Manager Application

Device Configuration Example and walkthrough

Here is an example config, with a walkthrough below it.

{
  "Devices": {
    "Device1": {
      "Enabled": true,
      "Debug": true,
      "ActionDelay": 30000,
      "DeviceType": "******",
      "RegisterAsGateway": true,
      "BaseHostUrl": "https://meters.**********.net",
      "LoginRoute": "/***/*****",
      "MeterRoute": "/***/******/****",
      "MeterReadingsRoute": "/***/******/readings?id=123456",
      "LoginUsername": "**********",
      "LoginPassword": "******",
      "MeterListBatchSize": 30,
      "ProcessBoundedCapacity": 100,
      "ProcessMaxDegreeOfParallelism": 50,
      "HistoricHourOffset": -6
    }
  }
}
  • Lets start by creating a new device called ‘Device1’.
  • We want this device to be enabled, so we make set ‘enabled’ to true.
  • We want to see the device logging, so we set ‘Debug’ to true. Note - logging still needs to be turned on via the config ‘Logging.json’.
  • We want this device to metch meter readings every 5min, so we set the ActionDelay to 30000ms. -We want to make sure that we have the Rms device running, so we specify the ‘DeviceType’ as ‘RmsDevice’.
  • We want this driver to register each meter as its own gateway, so we set RegisterAsGateway to ‘true’ meaning we will be expecting a routing key in commander like this <meter.Serial>.<meterReading.Measure>:<Options.DeviceType>|<Options.DeviceType>.
  • We specify a base url of the backend service where we will be getting data from. We thus set BaseHostUrl as https://meters.rmsconnect.net.
  • We specify the LoginRoute ‘/api/login’ meaning we will be requesting authentication from https://meters.rmsconnect.net/api/login.
  • We specify the MeterRoute ‘/api/meters/list’ meaning we will be requesting lists of meter ids from https://meters.rmsconnect.net/api/meters/list.
  • We specify the MeterReadingsRoute ‘/api/meters/readings?id=123456’ meaning we will be requesting meter readings from [https://meters.rmsconnect.net/api/meters/readings?id=123456] (https://meters.rmsconnect.net/api/meters/readings?id=123456).
  • We specify the LoginUsername of the user associated with the RMS backend service.
  • We specify the LoginPasswordof the user associated with the RMS backend service.
  • We specify how many meters we would like to receive per each request by providing MeterListBatchSize a value of ‘30’, meaning we want to request 30 meters at a time from the RMS backend service.
  • We want to limit the amount of items that we queue for processing, so we set ‘ProcessBoundedCapacity’ to 100.
  • We want multiple packets to be processed in parallel, so we set ‘ProcessMaxDegreeOfParallelism’ to 50, meaning we can have up to 50 batches of 30meters all being processed simultaneously.
  • Some meters only send in their readings every 1 hour, so we want to make sure that we query a few readings from the past, for this, we specify the HistoricHourOffset to ‘-6’, meaning that we roll back the “from time” in our query by 6 hours. E.g. if a query for meter readings runs at 18:00, we will request all meter readings from 12:00 up to 18:00.

Available Commander Endpoints

The routing key for these sensors is constructed as follows:

deviceInfo.GatewayId = Options.RegisterAsGateway ? meter.Serial : Options.GatewayId;
deviceInfo.GroupName = meterReading.Measure.ToUpper();
deviceInfo.DeviceType = Options.DeviceType;
deviceInfo.DeviceName = Options.RegisterAsGateway ? DeviceName : meter.Serial;

Meaning you can choose between one of the two configurations for the routing key GatewayID.GroupName:DeviceType|DeviceName

Options.RegisterAsGatewayRouting key construction: GatewayID.GroupName:|DeviceName
True<meter.Serial>.<meterReading.Measure>:<Options.DeviceType>|<Options.DeviceType>
False<Options.GatewayId>.<meterReading.Measure>:<Options.DeviceType>|<meter.Serial>

And the available properties are constructed as follows:

CreateProperty("string", nameof(meterReadingData.Id))
CreateProperty("string", nameof(meterReadingData.Serial))
CreateProperty( "string", nameof(meterReading.Measure))
CreateProperty( "string", nameof(meterReading.Unit))
CreateProperty( "string", nameof(meterReading.Direction))
CreateProperty("double", nameof(meterReading.Value))
CreateProperty("DateTime", nameof(meterReading.Date))

Meaning these are the 7 properties to be sent:

CountProperty NameData typeComment
1Idstring
2Serialstring
3Measurestring
4Unitstring
5Directionstring
6Valuedouble
7DateDateTime

GUI Example

Still waiting for a digital twin to be setup to show the mapping.

External References

For more infomation on RMS, visit their website by clicking on this https://www.remotemetering.net/.

Release Notes

VersionDescriptionRelease Date
4.0.43.10Initial version of the driver2023-03-13