RMS Telemetry Interface
May 15 2023 at 12:00 AM
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.
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.
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.
Order | Description | URL | Comments |
1 | Auth Request | https://meters.rmsconnect.net/api/login | POST the user name and password to the url. Make sure that the “Content-Type”, ‘application/json’ is added to your requests header. |
2 | Auth Response | - | Parse the response and extract the bearer token. |
3 | Request Meter List | https://meters.rmsconnect.net/api/meters/list | POST 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. |
4 | Parse 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. |
5 | Request Meter Readings | https://meters.rmsconnect.net/api/meters/readings?id=123456 | POST 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’. |
6 | Parse 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
Property | Description | Type | Defaults | |
---|---|---|---|---|
Device1 | The device name for this device. This has to be specified. | string | - | |
Enabled | Gets or sets whether this device is enabled. | bool | false???? | |
Debug | Gets or sets whether debug information is written to console/log file for this specific device. | bool | false??? | |
DeviceType | Gets or sets the type of this device. To use the rms device, this has to be ‘RmsDevice’. | string | - | |
ActionDelay | Time delay, in milliseconds, between each execution. Set this to 0 to use the default setting in Task Scheduler Options, which is normally 300000. | int | 0, which would result in it being 300000 | |
RegisterAsGateway | Identifying if incoming device data needs to be registered under a gateway entity, or device entity.. | bool | true | |
BaseHostUrl | The base host Url from where data must be fetched. | string | - | |
LoginRoute | The API login route. | string | - | |
MeterRoute | The API meter route. | string | - | |
MeterReadingsRoute | The API meter readings route. | string | - | |
LoginUsername | The username to login and authorize access. | string | - | |
LoginPassword | The password to login and authorize access. | string | - | |
MeterListBatchSize | The maximum number of meters to fetch per read iteration. | int | 30 | |
ProcessBoundedCapacity | Specifying a bounded capacity for the actionblock size, handling meter reading calls. | int | 500 | |
ProcessMaxDegreeOfParallelism | Max amount of meter reading calls allowed to run in parallel. | int | 50 | |
HistoricHourOffset | The 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.RegisterAsGateway | Routing 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:
Count | Property Name | Data type | Comment |
1 | Id | string | – |
2 | Serial | string | – |
3 | Measure | string | – |
4 | Unit | string | – |
5 | Direction | string | – |
6 | Value | double | – |
7 | Date | DateTime | – |
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
Version | Description | Release Date |
---|---|---|
4.0.43.10 | Initial version of the driver | 2023-03-13 |