Smart Meters and Client Access Devices (CADs)

I recently bought a(nother) gadget - the Glow stick Wifi CAD. This device reads data from my gas & electric smart meters and uploads it to the cloud, where it is available through a restful API.

It did take a little while for the device to be correctly paired but this was all down to one of my previous energy suppliers not following the process for a customer who leaves, so my smart meters were still 'owned' by them. Once this had been corrected the data started to flow and I pondered whether or not I'd ever have to go digging around under the spider infested staircase to get the meter readings ever again...

The API was very easy to get to grips with in postman and they have publicly available Swagger docs. A sample gas meter reading is below:

{
    "status": "OK",
    "name": "Smart Meter, gas consumption",
    "resourceTypeId": "672b8071-44ff-4f23-bca2-f50c6a3ddd02",
    "resourceId": "85495519-0ad3-4743-a2b3-202f37c152ad",
    "data": [
        [
            1586476916,
            23071780
        ]
    ],
    "units": "Wh",
    "classifier": "gas.consumption"
}

The usage data is contained within the "data" - the first entry is the UNIX timestamp of when the reading was taken and the second is the reading itself, in watt-hours.

For the electric readings the energy data is fine as it is; I have to enter my meter reading in kWh and that's what the API returns. The gas data isn't so simple; my supplier asks me to supply volume (cubic metres) readings but the API returns energy readings in watt-hours. Thankfully there is a simple equation to convert from volume to energy (available at the bottom of most gas bills) and this is what I've added to the azure function so that I can get my readings in the units I need to submit to my supplier.

Unfortunately, whatever values are used to calculate the energy usage are not the ones written on my bill, meaning the calculation is approximately 20 cubic metres out (at the moment). I don't know where this calculation is being done (in the smart meter, by the DCC or by Hildebrand) but because I can't access the volume data directly, it means my readings aren't quite right at the moment. I'm hopeful that the drift isn't too bad and so I could reasonably apply a static correction to get a good enough meter reading.

Azure Functions

I wanted something simple enough to get started with, but also very low cost to run ongoing. I didn't really want to trust my ageing unraid NAS that's gathering dust under the stairs and neither did I want to pay to continuously run a docker container or have to automate a schedule across several different products.

After throwing away lots of very empty solutions/projects in Visual Studio I made a little headway with Azure Functions (v3. v2 is hopelessly broken on my dev machine for some reason). The premise is simple enough, low barrier to entry serverless code execution and best of all, they have a timer based trigger, though I did have to try and make sense of the NCRONTAB based expressions they use for describing the schedule: https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer?tabs=csharp#ncrontab-expressions

All of the code is available on my GitHub: https://github.com/yakcam/BrightMeterReader

I'll need to revisit the auth token/auth system at some point. At the moment I have to manually enter a new value in to the Azure Key Vault secret that I'm using every time it expires. I'm hopeful I'll be able to make use of their oauth endpoints to get a refresh & access token.

If you'd like to run the code locally, clone the repo and populate the local.settings.json file as below, inputting your own values for the empty ones:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "SlackWebhookUrl": "",
    "GasResourceId": "",
    "ElectricResourceId": "",
    "BrightAuthToken": ""
  }
}

If you wish to run it on Azure, the right click publish wizard should do an adequate job of guiding you through the steps required. I've used Azure Key Vault (and a system assigned identity) to securely store secrets and make them available to the function. Links for these are available at the end.

I'm hoping that it'll cost very little to run, maybe only a few pence per month but time will tell; I'll certainly be keeping a very close eye on my Azure spend over the next few days! I will do my best to come back and update this post over the coming weeks with a breakdown of what it has cost to run.

An example of the slack output produced when the function runs can be seen below:

Automated meter reading submission?

Whilst my energy supplier don't advertise the fact that they have an API, a quick look at the interactions in the developer console shows that there's potentially a restful API behind the scenes, which might be used to automate the submission process... Of course if the UK's smart meter roll-out had been better executed (I'm not sure how it could have been done any worse) then all of this would be unnecessary!

Links

Azure Functions getting started using Visual Studio: https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-your-first-function-visual-studio

Timer triggers for Azure Functions: https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-timer?tabs=csharp

Azure Functions and Azure Key Vault: https://azure.microsoft.com/en-us/blog/simplifying-security-for-serverless-and-web-apps-with-azure-functions-and-app-service/

Update - 18/04/2020 - Costs and Token Refresh

The meter reading function has been running once a day for about a week now and I can't actually see any additional costs on my bill! Looking at the free limits I don't think I'll be coming anywhere close to them.

I've added a SetToken function which is run once an hour. This checks the current token to see if it expires within the next 2 days and if it does, it will go and fetch new one and save it to Azure Key Vault.