実現したいこと
学校の卒業研究でNodeMCU社のESP8266でGASに接続して、GASからのレスポンスで条件判断し、ESPを動かしたいです。
発生している問題・分からないこと
GASとESPのプログラムはできているのですが、シリアルモニタでHTTPに接続する際に-1とでてしまい接続が失敗してしまいます。どうすればよいでしょうか。
エラーメッセージ
error
1Error sending data: -1
該当のソースコード
C++
1#include <ESP8266WiFi.h> 2#include <ESP8266HTTPClient.h> 3#include <WiFiClientSecure.h> 4 5const char* ssid = "ssid"; 6const char* password = "password"; 7 8const char* GAS_URL = 9"GAS_URL"; 10 11#define SOIL_PIN A0 12 13void setup() { 14 Serial.begin(115200); 15 delay(1000); 16 17 Serial.println("Connecting to WiFi..."); 18 WiFi.begin(ssid, password); 19 20 while (WiFi.status() != WL_CONNECTED) { 21 delay(500); 22 Serial.print(".");dd 23 } 24 25 Serial.println("\nWiFi connected!"); 26} 27 28void loop() { 29 30 int soilRaw = analogRead(SOIL_PIN); 31 32 int soilPercent = map(soilRaw, 1023, 0, 0, 100); 33 soilPercent = constrain(soilPercent, 0, 100); 34 35 Serial.printf( 36 "Soil raw: %d | Soil moisture: %d%%\n", 37 soilRaw, 38 soilPercent 39 ); 40 41 WiFiClientSecure client; 42 client.setInsecure(); 43 44 HTTPClient http; 45 46 String url = String(GAS_URL) 47 + "?soil_raw=" + String(soilRaw) 48 + "&soil_percent=" + String(soilPercent); 49 50 Serial.println(url); 51 52 53 http.begin(client, url); 54 http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS); 55 56 int httpCode = http.GET(); 57 58 Serial.print("HTTP code: "); 59 Serial.println(httpCode); 60 61 if (httpCode > 0) { 62 Serial.println(http.getString()); 63 } else { 64 Serial.println(http.errorToString(httpCode)); 65 } 66 67 http.end(); 68 69 delay(10000); 70} 71
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
サーバーに負荷がかからないように待機時間を変えてみたりやってみたのですが意味なかったです、
補足
1回目の通信で HTTP code: 200がでて、GASからもしっかりレスポンスを受け取れるのですが、2回目の通信以降、Error sending data: -1がでてしまいそこから失敗してしまいます。
ESP8266HTTPClient.hを見ると、-1 は 「HTTPC_ERROR_CONNECTION_FAILED」のようです。意味合いとしてはGASのホスト(HTTPサーバー)への「接続失敗」のようですね。TCP/IPやSSL/TSLレベルでの接続が出来てないと予想されますが、広い意味合いのエラーであるため原因はわからず、回答することは難しいのですが、次の点を確認(調査)してみるとなにか分かるかもしれません。
1. WiFiには正常に接続できているかどうか → WiFi.localIP()の結果を表示して確認
2. GAS_URL に対するDNS名前解決(正引き)ができているかどうか
デバッグメッセージを表示することで、もっと詳細なエラーの状況がわかるかもしれません。ご参考:https://arduino-esp8266.readthedocs.io/en/latest/Troubleshooting/debugging.html
>const char* ssid = "ssid";
>const char* password = "password";
>const char* GAS_URL = "GAS_URL";
このような定数の書き方(?)は、解説本・サイト等のサンプルコードで『これらはそれぞれの環境に合わせて書き換えてね』という暗黙の意味でよく使われて、つまり何かをまんまコピペしたように見えますが。
質問者さんの環境において SSID やパスワードや URL はこれで合っているのでしょうか。
1,スマホのモバイルWIFIをデザリングしてGASに接続しているのですが、Wifiには接続できていて、プライベートIPアドレスもちゃんと表示されました。
2,1回目の通信で HTTP code: 200がでて、GASからもしっかりレスポンスを受け取れるのですが、2回目の通信以降、Error sending data: -1がでてしまいそこから失敗してしまいます。でも1回目の通信ができているので多分DNS名前解決はできていると思います。
デバックが出る設定も試したところ、
BSSL:_run_until: Timeout
BSSL:_wait_for_handshake: failed
がでてきました。
>const char* ssid = "ssid";
>const char* password = "password";
>const char* GAS_URL = "GAS_URL";
のとこは適宜変えています。なので多分間違っていることはないとおもいます
>~のとこは適宜変えています。
なるほど、失礼しました。
>2,1回目の通信で HTTP code: 200がでて、GASからもしっかりレスポンスを受け取れるのですが、2回目の通信以降 (ry
その様なことは最初から質問に書いて頂けるとありがたいです。
全く動かないのと一度は動くのでは、原因究明の想定(何が起きているか)は全然違いますので。(Umeeeh さんのコメントの半分や私のコメントは無くて済んだはずです。)
あてずっぽうですが、loop() の最後に client.stop() を入れるとどうですか? GithubにWifiClientのサンプルコードが合ったのでこちらもご参考までにお知らせします。 https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiClient/WiFiClient.ino
>その様なことは最初から質問に書いて頂けるとありがたいです。
すいません。捕捉に追加いたしました。
>あてずっぽうですが、loop() の最後に client.stop() を入れるとどうですか?
BSSL:_connectSSL: start connection
BSSL:_run_until: Timeout
BSSL:_wait_for_handshake: failed
BSSL:Couldn't connect. Error = 'Unknown error code.'
HTTPステータスコード: -1
やはり失敗してしまうみたいです。これはコードが悪いのでしょうか?>それともスマホの回線が悪いのでしょうか
Timeoutということは、処理や通信の時間がかかりすぎているということですので、環境に合わせてコードを最適化する必要はあるかもしれませんね・・・。
ドキュメントを読んだ範囲では、次のような対策があるようです。
1. CPUの動作周波数を80Mhz(デフォルト)から160Mhzにアップすることが推奨されてます。以下のドキュメントに書かれています。私の方では、現物がないので、やり方はわからないのですが、IDEから変更できないでしょうか?
ご参考:https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/bearssl-client-secure-class.html
2. タイムアウト時間をデフォルトの5秒から、もっと長い時間にするといいかもしれません。
void HTTPClient::setTimeout(uint16_t timeout)
例)client.setTimeout(15000); // 5秒→15秒に変更
ご参考:https://deepwiki.com/esp8266/Arduino/3.4-http-client#42-connection-options
>環境に合わせてコードを最適化する必要はある
CPUも160MHzにし、タイムアウトの時間を延ばしてみたところ、ほとんど先ほどと同じエラーで失敗してしまうのですが、何回も通信してみたところ、BSSL:CERTが送られ、
BSSL:Connected!
HTTPステータスコード: -5
という文とともにGASとの通信が成功するパターンがでてきました!
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11328985336
https://teratail.com/help#posted-otherservice を見て、然るべく処置してください。
で。あまりちゃんと考えていませんが、ローカルネットワーク上のPC上にPythonかなにかでHTTPSのサーバを建てて、そこに繋いでみるとかどうでしょう。サーバ側のログも取れるので、なにかのヒントにならないかしら。
既に試してるよって言われるかもしれませんが、試したことに書いてないので
まずは、エラーメッセージ通りに、BSSL(WiFiClientSecure)がタイムアウト、handshake失敗とでてるのなら、WiFiClientSecureのハンドシェイクのタイムアウトを設定(setHandshakeTimeout)してみてはどうですか?
エラーコードは次のように定義されてました。
#define HTTPC_ERROR_CONNECTION_LOST (-5)
また、BSSL:CERT → BSSL:connected! というログは、TSLの接続(Handshake)が完了したことを意味するっぽいです。
可能なら、実行結果を編集せずそのまま、貼り付けてもらえませんか? 今のやり取りでは、断片的に情報が開示されているような印象を受けています。もしそうなら、重要な情報が伝わってない可能性があることを危惧しています。
また、Loopの1回目、2回目の違いも分かるように記載してもらえると嬉しいです。長くなっても構いませんが、長い場合は質問に追記していただいたほうが多くの方にとって読みやすくなると思います。
加えて、表に出せない情報が含まれる場合は、当該箇所を「*******」のようにマスクした状態で記載してもらえればと思います。情報の開示が多いほど、他の方からの回答がつきやすくなる可能性もあるので、よろしくお願いします。(対応が無理 or 難しい場合は大丈夫ですので、私のこのコメントはスルーください~)
補足①:
公式ドキュメントを読みましたが、SSLの場合は、CPU、メモリ、などのチューニングが重要なようです。具体的には、Sessionの活用(CPU対策)、MFLNの活用(メモリ対策)です。ご参考: https://github.com/esp8266/Arduino/blob/master/doc/esp8266wifi/bearssl-client-secure-class.rst
補足②
スマホのテザリングをご使用だと思いますが、切り分ける意味でも、テザリング以外のWiFiに接続して動作の違いを確認できると、環境の問題を切り分けられると思います。ご家庭や、学校のWiFiに接続出来ないか、ご検討してください。
あなたの回答
tips
プレビュー