だれかの備忘録

主に自分用。

ThingSpeakで確実にデータを記録する方法

FreeライセンスのThingSpeakでは15秒よりも短い間隔でデータを送信しても記録されません。サーバーからのレスポンスにより記録されたかどうかを確認し、確実にデータを記録する方法を説明します。

Freeライセンスの制約

ThingSpeakはRaspberry Pi等で採ったセンサデータをHTTPのPOSTリクエストの送信のみで記録できますが、Freeライセンスだと制約があり、同じChannelにおいてデータ送信間隔は15秒以上空ける必要があります。15秒以内に送信しても記録されません。Fieldが別でも同じChannelならこの制約を受けます。Channelが別ならこの制約はありません。

データ送信(投げっ放し)

ThingSpeakにデータを記録する最小限のプログラムです。ここでは'1000'という値を送信して記録します。requestsというモジュールを使ってHTTPのPOSTリクエストを送ります。headersのXXXXX...はWrite API Keyで置き換えてください。

import requests
headers = {'X-THINGSPEAKAPIKEY': 'XXXXXXXXXXXXXXXX'}
data = {'field1': '1000'}
requests.post('https://api.thingspeak.com/update/', headers=headers, data=data)

POSTリクエストに対するレスポンスの内容は確認していないのでThingSpeak側で記録できたかどうか分かりません。これだと絶対に15秒以上空けるようにする必要があります。

サーバーからのレスポンス

ThingSpeakに連続でデータを送信してみたときにサーバーからどんなレスポンスが来るか確認します。

import requests
import time

headers = {'X-THINGSPEAKAPIKEY': 'XXXXXXXXXXXXXXXX'}
data = {'field1': '1000'}

t0 = time.time()

while True:
    response = requests.post('https://api.thingspeak.com/update/', headers=headers, data=data)
    print('{0:>5.1f}[sec]\t{1}'.format(time.time()-t0, response.text))

postの戻り値にはPOSTレスポンスの情報が返ってきて、ThingSpeakのEntry ID(記録されたデータの通し番号)がresponse.textに入ります。記録ができたなら1以上の値になりますが、記録されなかったら0になります。
実行するとpost毎に開始からの秒数とレスポンスをprintします。

   1.3[sec]	30
   2.3[sec]	0
   3.4[sec]	0
   4.4[sec]	0
   5.4[sec]	0
   6.4[sec]	0
   7.5[sec]	0
   8.6[sec]	0
   9.6[sec]	0
  10.7[sec]	0
  11.8[sec]	0
  12.9[sec]	0
  13.9[sec]	0
  14.9[sec]	0
  16.0[sec]	0
  17.2[sec]	31
  18.3[sec]	0
  19.4[sec]	0
  20.5[sec]	0
  21.6[sec]	0
  22.6[sec]	0
  23.7[sec]	0
  24.7[sec]	0
  25.8[sec]	0
  26.9[sec]	0
  27.9[sec]	0
  29.1[sec]	0
  30.1[sec]	0
  31.2[sec]	0
  32.4[sec]	32
  33.5[sec]	0
  34.5[sec]	0

最初の送信ではEntry IDが30として記録に成功していますが、その後15秒間は0が返ってきて記録できていないことが分かります。最初から15秒以上経過すると次はEntry ID 31として記録されています。15秒間隔で記録が成功し、Entry IDはインクリメントされていきます。

レスポンスを確認してリトライ

サーバーからの返信が1以上か、0かでエラーチェックします。エラーだったら正常になるまでPOSTを繰り返します。

import requests
import time

headers = {'X-THINGSPEAKAPIKEY': 'XXXXXXXXXXXXXXXX'}
data = {'field1': '1000'}

while True:
    response = requests.post('https://api.thingspeak.com/update/', headers=headers, data=data)
    if response.text != '0':
        break
    time.sleep(1)

前回の送信から15秒以内ならresponse.textが0になってwhileループに留まります。15秒以上経過していてresponse.textが1以上になるとbreakで抜けて終わります。

おわりに

そもそもネットワークの不調でサーバーに繋がらないこともあり得るし、15秒も待てないシステムもどうかと思ったりもしますが、念のためこんなエラーチェックを入れておくと安心です。