質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.37%

M5Stackを3Gでgoogoleスプレッドシートにデータをあげたい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,774

score 20

こんにちは。

M5Stack Grayと拡張モジュールの「M5Stack用 3G 拡張ボード」
(https://www.switch-science.com/catalog/4000/)
を利用してgoogoleスプレッドシートにデータをアップロードしたいと思っています。

右も左もわからず困惑しています。
以下、ネットで見つけたサンプルコードを参考に改編をしたいのですが、所々で分からない関数が出てきていてどういった
挙動をするコードなのか皆目見当がつきません。

■参考にさせていただいたサイト様
http://www.telomere0101.site/archives/post-1008.html

上記サイトではwi-fiを利用していますので、wi-fiに関するコードをそのまま3Gのコードに置き換えたらできるかなぁと
思いましたが全くうまくいきません。

以下が公開されているwifiのコードです

/*
  Program for logging temperature and humidity on Google Spreadsheet.


MIT License

Copyright (c) 2018 @telomere0101

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include <M5Stack.h>
#include "DHT12.h"
#include <WiFi.h>
#include <HTTPClient.h>

DHT12 dht12;          //Preset scale CELSIUS and ID 0x5c.

const char* ssid     = "SSID";   // your network SSID (name of wifi network)
const char* password = "Password";    // your network password

//setup start
void setup() {
  M5.begin();
  Wire.begin();
  //Initialize serial and wait for port to open:
  Serial.begin(115200);
  delay(100);


  Serial.print("Attempting to connect to SSID: ");
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  // attempt to connect to Wifi network:
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    // wait 1 second for re-trying
    delay(1000);
  }

  Serial.print("Connected to ");
  Serial.println(ssid);

}

//loop endless
void loop() {
  float temp, humid;
  temp = (float)dht12.readTemperature();
  humid = (float)dht12.readHumidity();

  //fill Screen black for clear screen
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextSize(6);
  //Read temperature with preset scale
  Serial.printf("Temp: %2.2f", temp);
  M5.Lcd.printf("Temp:\r\n %2.2f\r\n", temp);

  //Read humidity
  Serial.printf("Humid: %2.2f", humid);
  M5.Lcd.printf("Humid:\r\n %2.2f\r\n", humid);
  //make JSON
  char json[100];
  sprintf(json, "{\"temp\": %2.2f , \"humid\": %2.2f }", temp, humid);

  //HTTPClient code start
  HTTPClient http;

  Serial.print("[HTTP] begin...\n");
  // configure traged server and url
  http.begin("your_google_apps_script_published_url"); //HTTP

  Serial.print("[HTTP] POST...\n");
  // start connection and send HTTP header
  int httpCode = http.POST(json);

  // httpCode will be negative on error
  if (httpCode > 0) {
    // HTTP header has been send and Server response header has been handled
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);

    // file found at server
    if (httpCode == HTTP_CODE_OK) {
      String payload = http.getString();
      Serial.println(payload);
    }
  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }

  http.end();

  //delay 5 minutes
  delay(300000);
}

以下が3Gに置き換えようとしたコードです。

#define TINY_GSM_MODEM_UBLOX
#include <M5Stack.h>
#include <M5StackUpdater.h>
#include <TinyGsmClient.h>
#include <HTTPClient.h>

//TinyGsmClientSecure client;

const char* server = "script.google.com"; 
const char* key = "スクリプトキーを入力";  // google script key
float sensor_data1;
float sensor_data2;
float sensor_data3;


TinyGsm modem(Serial2); /* Serial2 is Modem of 3G Module */
TinyGsmClient ctx(modem);

void setup() {


//M5stackのSDから起動するためのファーム用のコードです
  if(digitalRead(BUTTON_A_PIN) == 0) {
  Serial.println("Will Load menu binary");
  updateFromFS(SD);
  ESP.restart();}

//LCDの初期化しているコードだと思っています  
  Serial.begin(115200);
  M5.begin();
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.println(F("M5Stack + 3G Module"));

//3Gで通信するSerial2の転送速度を115200に設定してるコードだと思っています
  M5.Lcd.print(F("modem.restart()"));
  Serial2.begin(115200, SERIAL_8N1, 16, 17);
  modem.restart();
  M5.Lcd.println(F("done"));

//モデムの情報を取得しLCDに表示しているコードだと思っています
  M5.Lcd.print(F("getModemInfo:"));
  String modemInfo = modem.getModemInfo();
  M5.Lcd.println(modemInfo);

//ここの「modem.waitForNetwork」が何をしているか不明です
  M5.Lcd.print(F("waitForNetwork()"));
  while (!modem.waitForNetwork()) M5.Lcd.print(".");
  M5.Lcd.println(F("Ok"));

//「gprsConnect」は3GのAPN情報などを設定していると思っています
  M5.Lcd.print(F("gprsConnect(soracom.io)"));
  modem.gprsConnect("soracom.io", "sora", "sora");
  M5.Lcd.println(F("done"));

//「modem.isNetworkConnected」はPDPに接続できているか確認するということが分かったのですが、
// PDPをまだ理解できていないです
  M5.Lcd.print(F("isNetworkConnected()"));
  while (!modem.isNetworkConnected()) M5.Lcd.print(".");
  M5.Lcd.println(F("Ok"));

//取得したIPアドレスを表示していると思われます
  M5.Lcd.print(F("My IP addr: "));
  IPAddress ipaddr = modem.localIP();
  M5.Lcd.print(ipaddr);
  delay(2000);
}

void loop() {
//こちらの変数はテストのためにそれぞれtempを10、humidを20として固定しています
  float temp, humid;
  temp = 10;
  humid = 20;
  //fill Screen black for clear screen
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextSize(6);
  //Read temperature with preset scale
  Serial.printf("Temp: %2.2f", temp);
  M5.Lcd.printf("Temp:\r\n %2.2f\r\n", temp);

  //Read humidity
  Serial.printf("Humid: %2.2f", humid);
  M5.Lcd.printf("Humid:\r\n %2.2f\r\n", humid);
  //make JSON
  char json[100];
  sprintf(json, "{\"temp\": %2.2f , \"humid\": %2.2f }", temp, humid);

  //HTTPClient code start
  HTTPClient http;

//ここより下のコードが理解できていません

  Serial.print("[HTTP] begin...\n");
  // configure traged server and url
  http.begin("https://script.google.com/macros/s/スクリプトキーを入力/exec"); //HTTP

  Serial.print("[HTTP] POST...\n");
  // start connection and send HTTP header
  int httpCode = http.POST(json);

  // httpCode will be negative on error
  if (httpCode > 0) {
    // HTTP header has been send and Server response header has been handled
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);

    // file found at server
    if (httpCode == HTTP_CODE_OK) {
      String payload = http.getString();
      Serial.println(payload);
    }
  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }

  http.end();

  //delay 5 minutes
  delay(3000);
}

御覧の通り、まったく理解がすすんでいません。
どのリファレンスを参照すれば通信について理解できるのか、ヒントが見当たらず見当がつかない状態です。
jsonというものも、今回初めて知りましたが、googoleスプレッドシートにデータをアップロードするだけでいいのでそのあたりを理解できるようになるために参考になるキーワードやサイトなどあればご教授いただけませんでしょうか。
また、コードの各関数の意味を教えていただけたら幸いです。
ちなみに改編したコードはコンパイルエラーなどは出ませんでした。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

私自身、M5Stackは触り始めてまだ日が浅いですし、3Gモジュールを使ったことがあるわけではありませんが、3GモジュールでHTTP通信するための記述を追加する必要があると思います。

  HTTPClient http;


という行がありますが、ここでHTTP通信するためのクライアントを作成しています。しかし、おそらく、ですが、このクライアントはWiFi接続で確立したソケット(ネットワーク通信経路)しか対応していないと思いますので、そのまま3Gのユニットでは使えないのではないかと思います。

一方、3Gモデム用に

TinyGsmClient ctx(modem);

という行も定義してあるので、おそらくこちらを使って通信することになるのではないでしょうか。

いくつか関連しそうなページを漁っていると、このようなページを見つけました。
https://qiita.com/yukataoka/items/119c69fa944fc500f8b5

こちらでは、M5Stackと3Gモジュールを使って、センサで得た値をクラウド側に送っています。

このページにあるソースコードを眺めていると、

ctx.connect("beam.soracom.io", 8888);
ctx.println("POST /k/v1/record.json HTTP/1.1");
ctx.println("Host: beam.soracom.io");
char content_length_hdr[32];
sprintf(content_length_hdr, "Content-Length: %lu", strlen(payload));
ctx.println(content_length_hdr);


という行がありました。

ここが3Gモジュール経由でWebサーバにhttpアクセスをしている部分(の冒頭)になります。

なので、これを参考にhttpプロトコルに従った通信を行えるようにコードを移植すればいいのではないでしょうか。

ただ、
元のソースはhttp通信のためのプロトコルを意識することなくデータの取得ができるように関数が準備されていますが、3G用のライブラリには原始的な関数しかないようで、プロトコルに則った通信については、自分で処理する必要がありそうです。

そうなると、今度はHTTPプロトコルに関する理解も必要になるとおもいます(さほど難しくはありません)。

googleで「TinyGsmClient http アクセス」あたりで検索するとヒントが色々ありそうです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/11 17:26

    ご回答ありがとうございます。
    なるほど、httpについてこの機会に理解を深めようと思います!

    >いくつか関連しそうなページを漁っていると、このようなページを見つけました。
    https://qiita.com/yukataoka/items/119c69fa944fc500f8b5

    ご教示ありがとうございます。
    さっそく確認します!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る