0
0

おんどとり WebStorage APIのデータ活用 (3)

Last updated at Posted at 2024-09-10

1. はじめに

こんにちは!今回はおんどとり WebStorage APIを使ったデータ取得方法の第3弾です。前回の記事(下記リンク)で紹介したAPI取得の応用バージョンをお届けします。

前回の記事はこちら

前回はRTR503Bのみを想定していましたが、今回は新たに2つの機種を追加して動作確認を行いました。(おそらく他の機種でも動作すると思います。)

  • RTR503B(温度・湿度)
  • TR501B(温度のみ)
  • RTR-576(温度・湿度・CO2)

ちなみに、今回は温度・湿度のデータのみを使用し、CO2の値は無視します。

2. レスポンスデータ(JSON)の確認

機種ごとに応答データが少し異なるので、それぞれについて説明します。

  • RTR503B
    温度がch1、湿度がch2に格納されています。
"channel":[
    {
        "name":"ch1",
        "num":1,
        "unit":"C"
    },{
        "name":"ch2",
        "num":2,
        "unit":"%"
    }],
"data":[
    {
        "unixtime": 1234560000,
        "data-id":101,
        "ch1":23.5,
        "ch2":65
    },
    {
        "unixtime": 1234560030,
        "data-id":102,
        "ch1":25.5,
        "ch2":68
    },
    ... ,
    {
        "unixtime": 1235040000,
        "data-id":16100,
        "ch1":21.5,
        "ch2":60
    }
]
  • TR501B
    温度のみで、ch1に温度が格納されています。
"channel": [
    {
        "name": "ch1",
        "num": "1",
        "unit": "C"
    }
],
"data": [
    {
        "ch1": "26.2",
        "data-id": "63702",
        "unixtime": "1725438716"
    },
    {
        "ch1": "26.2",
        "data-id": "63703",
        "unixtime": "1725438776"
    }, 
    .... ,
    {
        "ch1": "26.2",
        "data-id": "63704",
        "unixtime": "1725438836"
    }
]
  • RTR-576
    温度がch2、湿度がch3に格納されています。CO2は無視します。
"channel": [
    {
        "name": "ch1",
        "num": "1",
        "unit": "ppm"
    },
    {
        "name": "ch2",
        "num": "2",
        "unit": "C"
    },
    {
        "name": "ch3",
        "num": "3",
        "unit": "%"
    }
],
"data": [
    {
        "ch1": 839,
        ch2: 27.6,
         ch3: 64,
         data-id: 1,
         unixtime: 1725500843
     },
     .... ,
     {
         ch1: 885,
         ch2: 27.5,
         ch3: 58,
         data-id: 2,
         unixtime: 1725501443
     }
 ]

3. Pythonコードの修正

前回作成したコードを以下の方針で修正しました。

  • レスポンスデータから温度と湿度のみを抽出してデータフレームに保存
  • 温度・湿度以外のデータは無視
  • 温度または湿度のどちらか一方しかない場合は、その片方だけをデータフレームに保存し、もう一方は空欄に
  • 温度・湿度どちらもない場合はデータフレームに保存しない

修正したコードはこちらです。

import requests
import pandas as pd
from datetime import datetime, timedelta
import os
from dotenv import load_dotenv

# データフレームの表示で改行を防ぐために、出力幅を広げる
pd.set_option('display.width', 1000)

# おんどとり関連の環境変数をセット
load_dotenv(dotenv_path='./ondotori.env')

# 環境変数から情報を取得
API_KEY = os.getenv('API_KEY')
LOGIN_ID = os.getenv('LOGIN_ID')
LOGIN_PASS = os.getenv('LOGIN_PASS')
REMOTE_SERIAL = os.getenv('REMOTE_SERIAL')
BASE_SERIAL = os.getenv('BASE_SERIAL')

# データを取得してデータフレーム形式へ変換

# 現在の時刻と24時間前の時刻をUNIXタイムスタンプで取得
now = datetime.now()
unixtime_to = int(now.timestamp())
unixtime_from = int((now - timedelta(days=1)).timestamp())

# APIエンドポイントとヘッダー
url = 'https://api.webstorage.jp/v1/devices/data-rtr500'
headers = {
    'Content-Type': 'application/json',
    'X-HTTP-Method-Override': 'GET'
}

# リクエストボディ
payload = {
    'api-key': API_KEY,
    'login-id': LOGIN_ID,
    'login-pass': LOGIN_PASS,
    'remote-serial': REMOTE_SERIAL,
    'base-serial': BASE_SERIAL,
    'unixtime-from': unixtime_from,
    'unixtime-to': unixtime_to,
    'type': 'json'
}

# APIリクエスト
response = requests.post(url, headers=headers, json=payload)

# レスポンスのステータスコードを確認
if response.status_code != 200:
    raise Exception(f'API request failed with status code {response.status_code}: {response.json().get("error", {}).get("message")}')

# JSONデータを取得
data = response.json()

# チャンネル情報を取得し、変換マッピングを作成
channel_map = {ch['name']: 'temperature' if ch['unit'] == 'C' else 'humidity' if ch['unit'] == '%' else None for ch in data['channel']}
channel_map = {k: v for k, v in channel_map.items() if v is not None}

# データフレームを作成
df = pd.DataFrame(data['data'])

# チャンネル名を変換
df = df.rename(columns={name: channel_map[name] for name in channel_map})

# 必要な列を追加
df['remote_serial'] = data.get('remote-serial')
df['base_serial'] = data.get('base-serial')
df['time'] = pd.to_datetime(df['unixtime'].astype(int), unit='s')
df['id'] = df.apply(lambda row: f"{row['remote_serial']}-{row['base_serial']}-{row['data-id']}-{row['time']}", axis=1)

# temperatureとhumidityのどちらか一方のみのデータの場合、欠損値を設定
if 'temperature' not in df.columns:
    df['temperature'] = None
if 'humidity' not in df.columns:
    df['humidity'] = None

# 不要な列を削除
df = df[['remote_serial', 'base_serial', 'data-id', 'time', 'temperature', 'humidity', 'id']]

# データフレームを表示
print(df)

今回は以上です!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0