Nature Remo E の消費電力情報を Amazon Timestream へLambdaでサーバレスに連携させてみた

Nature Remo E lite で取得したスマートメーターの電力消費データを、AWSの時系列データベースAmazon Timestreamにサーバレスに連携させてみました。
2021.01.17

AWSチームのすずきです。

Nature Remo E Lite が取得したスマートメーターの消費電力情報を、 時系列データベース Amazon Timestream に登録する Lambda関数 を試す機会がありましたので、 紹介させて頂きます。

Nature Remo Cloud API

スマートメータの消費電力情報の取得は、Nature Remo Cloud APIを利用しました。

API利用に必要なトークンは以下を参考に用意しました。

電力情報

公式ドキュメントスマートメーターの値から電力データを算出するより、以下の2項目を記録対象としました。

  • measured_instantaneous : 積算電力量計測値(正方向)
  • normal_direction_cumulative_electric_energy : 瞬時電力計測値

API結果サンプル

$ TOKEN='0000'
$ curl -X GET "https://api.nature.global/1/appliances" -H "accept: application/json" -k --header "Authorization: Bearer ${TOKEN}" | jq '.[]|select (.smart_meter)'
{
  "id": "00000000-0000-0000-0000-000000000000",
  "device": {
    "name": "Remo E lite",
    "id": "00000000-0000-0000-0000-000000000001",
    "created_at": "2020-00-00T00:00:00Z",
    "updated_at": "2020-00-00T00:00:00Z",
    "mac_address": "00:00:00:00:00:00",
    "bt_mac_address": "00:00:00:00:00:00",
    "serial_number": "00000000000000",
    "firmware_version": "Remo-E-lite/1.1.14",
    "temperature_offset": 0,
    "humidity_offset": 0
  },
  "model": {
    "id": "00000000-0000-0000-0000-000000000002",
    "manufacturer": "",
    "name": "Smart Meter",
    "image": "ico_smartmeter"
  },
  "type": "EL_SMART_METER",
  "nickname": "スマートメーター",
  "image": "ico_smartmeter",
  "settings": null,
  "aircon": null,
  "signals": [],
  "smart_meter": {
    "echonetlite_properties": [
      {
        "name": "coefficient",
        "epc": 211,
        "val": "1",
        "updated_at": "2021-01-17T09:14:53Z"
      },
      {
        "name": "cumulative_electric_energy_effective_digits",
        "epc": 215,
        "val": "6",
        "updated_at": "2021-01-17T09:14:53Z"
      },
      {
        "name": "normal_direction_cumulative_electric_energy",
        "epc": 224,
        "val": "102095",
        "updated_at": "2021-01-17T09:14:53Z"
      },
      {
        "name": "cumulative_electric_energy_unit",
        "epc": 225,
        "val": "2",
        "updated_at": "2021-01-17T09:14:53Z"
      },
      {
        "name": "reverse_direction_cumulative_electric_energy",
        "epc": 227,
        "val": "72",
        "updated_at": "2021-01-17T09:14:53Z"
      },
      {
        "name": "measured_instantaneous",
        "epc": 231,
        "val": "808",
        "updated_at": "2021-01-17T09:14:53Z"
      }
    ]
  }
}

Amazon Timestream

リージョン

2021年1月現在、Amazon Timestreamは東京リージョンを未サポートのため、オレゴンリージョン(us-west-2)を利用しました。

Database

「Standard Database」、暗号化は「デフォルトキー」で作成しました。

テーブル

作成したデータベースにテーブルを追加しました。

メモリストアに1日(24時間)、マグネティックストアに2年間データ保持する指定としました。

Lambda設定

リージョン

Amazon Timestream と同じ、オレゴンリージョン(us-west-2)に設置しました。

IAM

Lambdaの実行と、Timestream利用に必要なIAM権限、マネージドポリシーで付与しました。

  • arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
  • arn:aws:iam::aws:policy/AmazonTimestreamFullAccess

環境変数

以下をLambdaの環境変数として利用しました。

  • Token (Cloud API用)
  • DatabaseName (作成したTimestreamのデータベース)
  • TableName (作成したTimeStreamのテーブル)

ランタイム

Python3.8を利用しました。

Boto3

2021年1月時点、Python3.8ランタイム同梱のSDK(Boto3)を利用しました。

  • boto3 vertion is 1.15.16
import boto3
def lambda_handler(event, context):
    print('boto3 vertion is {0}'.format(boto3.__version__))

コード

標準ライブラリのurllibを利用する実装としました。

import datetime
import json
import os
import urllib.request
import boto3

def get_api_appliances():
    
    #CloudAPI実行
    r = urllib.request.Request('https://api.nature.global/1/appliances')
    r.add_header('Authorization', 'Bearer ' + os.environ['Token'])
    with urllib.request.urlopen(r) as a:
        b = a.read()

    #smart_meter情報のみ抽出
    z = {}
    for c in json.loads(b):
        if 'smart_meter' in c:
            if 'echonetlite_properties' in c['smart_meter']:
                z = c['smart_meter']
                #デバイス情報付与
                z['id'] = c['id']
                z['device'] = c['device']
    return z

def create_records(b):

    dimensions = [
        {'Name': 'id', 'Value': b['id']},
        {'Name': 'device_name', 'Value': b['device']['name']}
    ]

    #積算電力計算用の係数取得
    coefficient = 1
    cumulative_electric_energy_unit = 1
    for c in b['echonetlite_properties']:
        if c['name'] == 'coefficient':
            coefficient = int(c['val'])
        if c['name'] == 'cumulative_electric_energy_unit':
            cumulative_electric_energy_unit = int(c['val'])

    x = []
    for c in b['echonetlite_properties']:
        #瞬間電力計測値
        if c['name'] == 'measured_instantaneous':
            z = {}
            z['Dimensions'] = dimensions
            z['MeasureName'] = 'measured_instantaneous'
            z['MeasureValue'] = str(int(c['val']))
            z['MeasureValueType'] = 'BIGINT'
            z['Time'] = str(int(datetime.datetime.timestamp(datetime.datetime.fromisoformat(c['updated_at'].replace('Z', '+00:00'))))*1000)
            x.append(z)
        #積算電力量計測値(正方向)
        if c['name'] == 'normal_direction_cumulative_electric_energy':
            z = {}
            z['Dimensions'] = dimensions
            z['MeasureName'] = 'normal_direction_cumulative_electric_energy'
            z['MeasureValue'] = str(int(c['val']) * coefficient * cumulative_electric_energy_unit )
            z['MeasureValueType'] = 'BIGINT'
            z['Time'] = str(int(datetime.datetime.timestamp(datetime.datetime.fromisoformat(c['updated_at'].replace('Z', '+00:00'))))*1000)
            x.append(z)
    return x

def write_records(records):
    client = boto3.client('timestream-write')
    r = client.write_records(
        DatabaseName = os.environ['DatabaseName'],
        TableName = os.environ['TableName'],
        Records = records
    )

def lambda_handler(event, context):
    a = get_api_appliances()
    b = create_records(a)
    if len(b) > 0:
        c = write_records(b)

確認

Timestreamのクエリエディタを利用、直近15分間に登録されたレコード(10件)が確認できました。

瞬間電力計測値(measured_instantaneous)

積算電力量計測値(normal_direction_cumulative_electric_energy)

料金

Amazon Timestream 料金計算ツールの試算では、 1分ごとに2項目を登録した場合の月額利用費、0.15USDとなりました。

まとめ

Nature Remo E Lite で 取得した消費電力情報を Amazon Timestream にサーバレスに連携できる事を確認できました。

Amazon Timestream が提供する 平滑化、近似、補間などの時系列関数の利用や、Grafanaによる可視化なども追って評価して紹介させて頂きたいと思います。