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

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

ただいまの
回答率

90.37%

  • Arduino

    713questions

    Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

2種類のCA証明書を設定する方法について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 260

y_gijutsu

score 9

やりたいこと

IFTTTとCloud MQTTの両方に対応したプログラムを作成しています。

①IFTTTの動作は、ボタンが押されると、LINEにメッセージを送信
②Cloud MQTTの動作は、LINEからメッセージを受信すると、LEDを点灯させる。

というように、Arduino(ESP32)とLINEとの間で双方向通信を行いたいと考えています。

今できていること

①と②をそれぞれ単独で動作させることはできています。

今つまづいている所

①と②を統合したプログラムを掲載します。
このプログラムでコンパイルしたところ、次のエラーが発生しました。

エラー
'class PubSubClient' has no member named 'setCACert'

教えてほしい内容

①のプログラムを単独で動作させるときは、

WiFiClientSecure client;


②のプログラムを単体で動作させるときは、

WiFiClientSecure wifiClient;
PubSubClient client(wifiClient);


このように設定していますが、①と②の両方を統合する場合は、どのように記述すれば良いのかが分かりません。
CA証明書のコードは、"certificate.h"内に①と②それぞれの証明書を記述しています。

プログラムコード

#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include "config.h"
#include "certificate.h"
#include "ifttt_config.h"

// hostname of Maker of IFTTT Platform
const char*  HOSTNAME = "maker.ifttt.com";

WiFiClientSecure wifiClient;
PubSubClient client(wifiClient);

void setup() {
  Serial.begin(115200);
  delay(100);

  Serial.println();
  WiFi.mode(WIFI_STA);
  client.setCallback(callback);
  client.setServer(host, port);
}

void loop() {
  //Wifi接続
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("connecting to ");
    Serial.print(ssid);
    Serial.println("...");
    WiFi.begin(ssid, password);

    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
      //アクセスポイントへの接続に失敗したら5秒間待ってリトライ
      Serial.println("failed to connect");
      delay(5000);
      return;
    } else {
      Serial.print("WiFi connected: ");
      Serial.println(WiFi.localIP());
    }
    wifiClient.setCACert(ca_cert);
  }

  //IFTTT Event Trig
      if(digitalRead(GPIO_NUM_34) == 0){
        trigger_event1();
      }


  //CloudMQTTに接続
  if (!client.connected()) {
    client.connect(clientID, CloudMQTT_user, CloudMQTT_pass);

    if (client.connected()) {
      Serial.println("MQTT connected");

      // トピック名を指定してsubscribe
      client.subscribe(topic);
    } else {
      Serial.print("MQTT connection failed: ");
      Serial.println(client.state());
      delay(5000);
    }
  } else {
    // 既にサーバに接続されていれば通常処理を行う
    client.loop();
  }
}


//Cloud MQTT 受信メッセージをシリアルにプリント
void callback(char* topic, byte* payload, unsigned int length) {

  Serial.print("Message arrived in topic: ");
  Serial.println(topic);

  Serial.print("Message:");
  String message;

  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  Serial.println(message);
  if (message == "On") {
    digitalWrite(LED,HIGH);
    delay(100);
    digitalWrite(LED,LOW);
    delay(100);
  } 
  Serial.println();
  Serial.println("-----------------------");
}


//IFTTT Event
void trigger_event1() {
  client.setCACert(ROOT_CA_CERT);

  Serial.println("\nStarting connection to server...");
  if (!client.connect(HOSTNAME, 443)) {
    Serial.println("Server connection failed!");
  } else {
    Serial.println("Connected to server!");

    // Make a HTTP request:
    client.print("GET ");
    client.print("/trigger/");
    client.print(EVENT1);
    client.print("/with/key/");
    client.print(KEY);
    client.println(" HTTP/1.0");
    client.print("Host: ");
    client.println(HOSTNAME);
    client.println("Connection: close");
    client.println();

    while (client.connected()) {
      String line = client.readStringUntil('\n');
      if (line == "\r") {
        Serial.println("headers received");
        break;
      }
    }
    while (client.available()) {
      char c = client.read();
      Serial.write(c);
    }
    Serial.println();

    client.stop();
  }
}

①のコードは、

#include <WiFiClientSecure.h>
#include "esp_deep_sleep.h"
#include "wifi_config.h"
#include "ifttt_config.h"

// hostname of Maker of IFTTT Platform
const char*  HOSTNAME = "maker.ifttt.com";

WiFiClientSecure client;

void setup() {
  Serial.begin(115200);
  delay(100);

}

void loop() {
  //IFTTT Event Trig
      if(digitalRead(GPIO_NUM_34) == 0){
        trigger_event1();
      }
  }

// connect to the WiFi network of home
bool connect_to_wifi() {
  Serial.print("Attempting to connect to SSID: ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  // attempt to connect to Wifi network:
  int retry_count = 0;
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    // wait 1 second for re-trying
    delay(1000);
    retry_count++;
    if (retry_count > 30) {
      Serial.println("WiFi connection failed!");      
      return false;
    }
  }

  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  return true;
}

// trigger an event of Maker
void trigger_event1() {
  client.setCACert(ROOT_CA_CERT);

  Serial.println("\nStarting connection to server...");
  if (!client.connect(HOSTNAME, 443)) {
    Serial.println("Server connection failed!");
  } else {
    Serial.println("Connected to server!");

    // Make a HTTP request:
    client.print("GET ");
    client.print("/trigger/");
    client.print(EVENT1);
    client.print("/with/key/");
    client.print(KEY);
    client.println(" HTTP/1.0");
    client.print("Host: ");
    client.println(HOSTNAME);
    client.println("Connection: close");
    client.println();

    while (client.connected()) {
      String line = client.readStringUntil('\n');
      if (line == "\r") {
        Serial.println("headers received");
        break;
      }
    }
    while (client.available()) {
      char c = client.read();
      Serial.write(c);
    }
    Serial.println();

    client.stop();
  }
}

②のコードは、

#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <IRremote.h>
#include "config.h"
#include "certificate.h"


WiFiClientSecure wifiClient;
PubSubClient client(wifiClient);

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.println();
  WiFi.mode(WIFI_STA);
  client.setCallback(callback);
  client.setServer(host, port);
}

void loop() {
  //Wifi接続
  if (WiFi.status() != WL_CONNECTED) {
    Serial.print("connecting to ");
    Serial.print(ssid);
    Serial.println("...");
    WiFi.begin(ssid, password);

    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
      //アクセスポイントへの接続に失敗したら5秒間待ってリトライ
      Serial.println("failed to connect");
      delay(5000);
      return;
    } else {
      Serial.print("WiFi connected: ");
      Serial.println(WiFi.localIP());
    }

    wifiClient.setCACert(ca_cert);
  }

  //CloudMQTTに接続
  if (!client.connected()) {
    client.connect(clientID, CloudMQTT_user, CloudMQTT_pass);

    if (client.connected()) {
      Serial.println("MQTT connected");

      // トピック名を指定してsubscribe
      client.subscribe(topic);
    } else {
      Serial.print("MQTT connection failed: ");
      Serial.println(client.state());
      delay(5000);
    }
  } else {
    // 既にサーバに接続されていれば通常処理を行う
    client.loop();
  }
}

//Cloud MQTT 受信メッセージをシリアルにプリント
void callback(char* topic, byte* payload, unsigned int length) {

  Serial.print("Message arrived in topic: ");
  Serial.println(topic);

  Serial.print("Message:");
  String message;

  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  Serial.println(message);
  if (message == "On") {
    digitalWrite(LED,HIGH);
    delay(100);
    digitalWrite(LED,LOW);
    delay(100);
  } 
  Serial.println();
  Serial.println("-----------------------");
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • ikedas

    2019/03/20 20:07

    ①と②別々のときのそれぞれのプログラムも掲載してください。

    キャンセル

  • この投稿は削除されました

  • ikedas

    2019/03/20 20:35

    質問文に追記していただけませんか。この欄は隠れてしまうので他の人が気づかないかもしれません。

    キャンセル

回答 1

checkベストアンサー

+1

この辺のプログラムは経験がないので回答と言うにはちょっと気が引けるところではあるのですが、修正追記依頼でもなし...

クラスの内容はともかく、コードを字面だけで追ってみると、

①では

WiFiClientSecure client;
//略
void trigger_event1() {
  client.setCACert(ROOT_CA_CERT); //このclientはWiFiClientSecureのインスタンス

  Serial.println("\nStarting connection to server...");
  if (!client.connect(HOSTNAME, 443)) {
//以下略


合体版では

WiFiClientSecure wifiClient;
PubSubClient client(wifiClient);
//略
void trigger_event1() {
  client.setCACert(ROOT_CA_CERT); //このclientはPubSubClientのインスタンス

  Serial.println("\nStarting connection to server...");
  if (!client.connect(HOSTNAME, 443)) {
//以下略


となっています。この違いは意図してのことですか? PubSubClientがWiFiClientSecureを継承してるならこれでもいい...ということもありそうですが、一応PubSubClientがMQTT用のクラスらしいので、それにIFTTTの接続を任せるのはどうなんでしょう。

ついでに、WiFiClientSecureも同じインスタンスをMQTT用とIFTTT用と使い回しは大丈夫なのでしょうか。それぞれにインスタンスを生成する必要とかはないのですか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/03/26 09:33

    回答ありがとうございます。
    それぞれにインスタンスを生成する場合、ハードウェアも少し変える必要があるのでしょうか。
    私が考えている方法としては、ハードウェアで切替スイッチを用意して、
    スイッチの状態に応じて、IFTTT(送信)とMQTT(受信)を切り替えるというアイデアしか思いつかないのですが、他に方法がありますでしょうか。
    それぞれにインスタンスを生成する方法について、どのように記述すれば良いのかが分からないため、教えていただけると助かります。

    キャンセル

  • 2019/03/27 23:31

    なんで「ハードウェアを変える」が出てくるのかよくわからないけど。
    WiFiClientSecure iftttClient;
    とかを宣言して、
    trigger_event1()の中のclientを全部iftttClientに変える、あたりでコンパイルは通るんじゃないかな。
    てもとであなたのプログラムをコンパイルしてみようとしたけどいろいろ足りなくてダメだから、あまり手伝えません。

    キャンセル

  • 2019/04/09 13:59

    返信がだいぶ遅れてしまい、すみません。
    WiFiClientSecure iftttClient;
    を用意して、trigger_event1()の中のclientを全部iftttClientに変えたところ、コンパイルは通りました。
    が、なぜ通るようになったのかが理解できておりません。
    次の理解であっていますでしょうか。
    [元々、エラーになった原因]
    IFTTTのEvent内で"client"クラスを使用していたが、
    これは、
    PubSubClient client(wifiClient); で宣言しているとおり、
    PubSubClientクラス(MQTT接続)を使用しているので、IFTTTをMQTT接続で行おうとしていた。
    [変更後]
    WiFiClientSecure iftttClient; と宣言し、IFTTTのEvent内の"client"を"iftttClient"に変更することで、
    IFTTTは、WiFiClientSecure接続となるため、解決できる。

    キャンセル

  • 2019/04/09 23:50

    接続がどうのこうのじゃなくて、単にC++の文法の問題でしょう。

    単体のプログラムでは
    WiFiClientSecure client;
    のclientに対して
    client.setCACert(ROOT_CA_CERT);
    を呼んでいたのを、

    あなたが合体させたプログラムでは
    PubSubClient client(wifiClient);
    に対して
    client.setCACert(ROOT_CA_CERT);
    と呼ぼうとしているのですからおかしなことになっているわけで。

    キャンセル

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

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

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

  • Arduino

    713questions

    Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。