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秒も待てないシステムもどうかと思ったりもしますが、念のためこんなエラーチェックを入れておくと安心です。