HOME
  Security
   Software
    Hardware
  
FPGA
  CPU
   Android
    Raspberry Pi
  
nLite
  Xcode
   etc.
    ALL
  
LINK
BACK
 

2023/02/10

ESP32のプログラムを ESP8266に移植する方法、Arduinoでも微妙に互換性が無い所が有ります ESP32のプログラムを ESP8266に移植する方法、Arduinoでも微妙に互換性が無い所が有ります

(ESP32の https SSLや GPIO割込み等を ESP8266に移植する方法)

Tags: [電子工作]




● ESP32のプログラムを ESP8266に移植する方法、Arduinoでも微妙に互換性が無い所が有ります

 ESP32の https SSLや GPIO割込み等を ESP8266に移植する方法。

● ESP8266で Slackに「勤怠管理」メッセージをワンボタン操作で投稿する方法

 Slackの勤怠チャンネルに勤怠メッセージを投稿する物を ESP32で作りましたが、ESP32ではオーバースペックなのと、使用していない OLED付きの ESP8266のモジュールが有るのでそれを使う様にしました。


2023/01/30
ESP32で Slackに「勤怠管理」メッセージをワンボタン操作で投稿する方法
ESP32で Slackに「勤怠管理」メッセージをワンボタン操作で投稿する方法

  Slackの勤怠チャンネルに毎日毎日毎日毎日 手動で投稿するのが馬鹿らしいので ESP32で作った

 Arduinoなので何も考えずに ESP8266で動くと思いましたが、ESP32と ESP8266で微妙に異なる部分が有り移植には若干てこずりました。

 ESP32から始めた私にとって ESP8266はトラップが多い感じです。
 (ESP8266から始めた場合は逆に感じたと思うが)

ESP32の場合ESP8266の場合
#include <HTTPClient.h>#include <ESP8266HTTPClient.h>
httpsの SSL通信の場合は下記が必要
#include <WiFiClientSecureBearSSL.h>
#include <WiFi.h>#include <ESP8266WiFi.h>
#include "NTPClient.h"#include "NTPClient.h"
#include <WiFiUdp.h>
ARDUINO_ISR_ATTRICACHE_RAM_ATTR

・ESP8266で Slackに「勤怠管理」メッセージをワンボタン操作で投稿する方法
ESP8266で Slackに「勤怠管理」メッセージをワンボタン操作で投稿する方法



ESP8266で Slackにメッセージをワンボタンで投稿する方法



● error: 'WiFiUDP' does not name a type; did you mean 'WiFi'?

 WiFiUDPの定義が無いので WiFiUdp.hを明示的に includeする。

error: 'WiFiUDP' does not name a type; did you mean 'WiFi'?

WiFiUDP udp;
// Japan timeOffset 9 hours, updateInterval 12 hours
NTPClient ntp(udp, "ntp.nict.jp", 9 * 60 * 60, 12 * 60 * 60 * 1000);

●Solution
 Add
#include <WiFiUdp.h>


● error: call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)

 HTTPClient::beginの記述が古いと怒られるので begin(WiFiClient, url)に書き換える。

 WiFiClient wifiClient; を記述するだけで良い(インスタンス化は不用)。

error: call to 'HTTPClient::begin' declared with attribute error: obsolete API, use ::begin(WiFiClient, url)

  httpClient.begin("http://hogehoge.hoge/");

●Solution
  WiFiClient wifiClient;
  httpClient.begin(wifiClient, "http://hogehoge.hoge/");

 ちなみに HTTPCLIENT_1_1_COMPATIBLEを定義する方法は 2023年現在は使えないっぽい。
Issues HTTPCLIENT_1_1_COMPATIBLE

#define HTTPCLIENT_1_1_COMPATIBLE
 を
platform.local.txt
 に追加する。

platform.txt


● https error code -5 connection lost

 httpsの SSL通信の場合は素の WiFiClientでは駄目。
 httpsの SSL通信の場合は WiFiClientSecureを使う必要がある。

 更に SSL証明書の設定が必要で、setInsecure()で無効化するか、真面目に SHA-1の SSL certificate Fingerprintを設定する。

 下記の公式のサンプルプログラムが無かったら解決は不可能でした。
BasicHttpsClient.ino

https error code -5 connection lost

  WiFiClient wifiClient;
  httpClient.begin(wifiClient, "https://hogehoge.hoge/");
  int status_code = httpClient.POST((uint8_t *)buf, strlen(buf));
  if (status_code == 200)
  {
    Serial.print("OK");
  }
  else
  {
    Serial.printf("ERR %d", status_code);
    if (status_code <= 0)
    {
      Serial.printf("ERR %s", httpClient.errorToString(status_code).c_str());
    }
  }

●Solution
#include <WiFiClientSecureBearSSL.h>

  std::unique_ptr<BearSSL::WiFiClientSecure> wifiClient(new BearSSL::WiFiClientSecure);
  // ignore the SSL certificate
  wifiClient->setInsecure();

  // or SSL certificate SHA-1 Fingerprint
  // const uint8_t fingerprint[20] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33 };
  // client->setFingerprint(fingerprint);

  HTTPClient httpClient;
  httpClient.begin(*wifiClient, "https://hogehoge.hoge/");

● Chromeブラウザで https通信の SHA-1の SSL certificate Fingerprintを確認する方法

 Chromeブラウザの場合。
 ・F12を押して developerコンソールを開く
 ・「セキュリティ」タブを選択する
 ・「証明書を表示」をクリックする
 ・「SHA-1 指紋」の 20バイトの 16進数の文字列を確認する

・Chromeブラウザで https通信の SHA-1の SSL certificate Fingerprintを確認する方法
Chromeブラウザで https通信の SHA-1の SSL certificate Fingerprintを確認する方法


Chromeブラウザで https通信の SHA-1の SSL certificate Fingerprintを確認する方法




● error: expected initializer before 'isr'

 割り込みの関数定義、ESP8266は ICACHE_RAM_ATTRを使用する。

c_types.h

 ARDUINO_ISR_ATTRは esp32-hal.hで定義されている。
esp32-hal.h

error: expected initializer before 'isr'

void ARDUINO_ISR_ATTR isr() {
    hasButtonPushed = true;
}

●Solution
void ICACHE_RAM_ATTR isr() {
    hasButtonPushed = true;
}


● ESP8266版の Slack投稿プログラム

 ESP32のプログラムを ESP8266用に書き換えたのが下記。

// #define HTTPCLIENT_1_1_COMPATIBLE true は使えないっぽい

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

#include <WiFiClientSecureBearSSL.h>
#include <WiFiUdp.h>

#include "NTPClient.h"
#include <ArduinoJson.h>

#include <Arduino.h>
#include <SPI.h>
#include <Wire.h>

#define BOARD_SW                    0 /* Flash */
#define SW_ON                       LOW
#define SW_OFF                      HIGH

#define HAS_DISPLAY
#define I2C_SDA                     5 /* GPIO 5 (D1) */
#define I2C_SCL                     4 /* GPIO 4 (D2) */

#ifdef HAS_DISPLAY
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_F_HW_I2C *u8g2 = nullptr;
#endif

StaticJsonDocument<512> doc;

// WiFi Internet Router
const char* ssid     = "WiFi_ssid";
const char* password = "WiFi_password";

// Slack API
const char* slack_user_oauth_token = "xoxp-xxxx";
const char* slack_channel = "#general";

// 1675256424.526809
char saved_ts[20] = "";

WiFiUDP udp;
// Japan timeOffset 9 hours, updateInterval 12 hours
NTPClient ntp(udp, "ntp.nict.jp", 9 * 60 * 60, 12 * 60 * 60 * 1000);


volatile bool hasButtonPushed = false;

// ESP32 ARDUINO_ISR_ATTR
void ICACHE_RAM_ATTR isr() {
    hasButtonPushed = true;
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("initBoard");
  Wire.begin(I2C_SDA, I2C_SCL);

  delay(20);

#ifdef HAS_DISPLAY
    Wire.beginTransmission(0x3C);
    if (Wire.endTransmission() == 0) {
        Serial.println("Started OLED");
        u8g2 = new U8G2_SSD1306_128X64_NONAME_F_HW_I2C(U8G2_R0, U8X8_PIN_NONE);
        u8g2->begin();
        u8g2->clearBuffer();
        u8g2->setFlipMode(0);
        u8g2->setFontMode(1); // Transparent
        u8g2->setDrawColor(1);
        u8g2->setFontDirection(0);
        u8g2->firstPage();
        do {
            u8g2->setFont(u8g2_font_inb19_mr);
            u8g2->drawStr(0, 30, "Time");
            u8g2->drawHLine(2, 35, 47);
            u8g2->drawHLine(3, 36, 47);
            u8g2->drawVLine(45, 32, 12);
            u8g2->drawVLine(46, 33, 12);
            u8g2->setFont(u8g2_font_inb19_mf);
            u8g2->drawStr(58, 60, "Card");
        } while ( u8g2->nextPage() );
        u8g2->sendBuffer();
        u8g2->setFont(u8g2_font_fur11_tf);
        delay(100);
    }
#endif

#ifdef BOARD_SW
    pinMode(BOARD_SW, INPUT_PULLUP);
#endif

    // When the power is turned on, a delay is required.
    delay(1500);

    Serial.println("WiFi Begin");
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(1000);
    }
    Serial.print("WiFi Connected: ");
    Serial.println(WiFi.localIP());

#ifdef HAS_DISPLAY
        if (u8g2) {
            u8g2->sleepOff();
            u8g2->clearBuffer();
            u8g2->setContrast(1);
            u8g2->setFontMode(0); // Transparent
            u8g2->setDrawColor(1);
        }
#endif

    attachInterrupt(BOARD_SW, isr, FALLING);
}

void(* resetFunc) (void) = 0; //declare reset function @ address 0

unsigned long past_epochTime = 0UL;

void loop() {
  // put your main code here, to run repeatedly:

    if (WiFi.status() != WL_CONNECTED) {
      Serial.println("!= WL_CONNECTED");
      // WiFi.disconnect();
      // WiFi.reconnect();
      resetFunc(); // call reset
      return;
    }

    ntp.update();

    unsigned long epochTime = ntp.getEpochTime();
    if (past_epochTime == epochTime && !hasButtonPushed) {
      return;
    }

    past_epochTime = epochTime;

    String formattedTime = ntp.getFormattedTime(); // hh:mm:ss

    char message[256];
    boolean isSyussya;
    int hours = ntp.getHours();
    int seconds = ntp.getSeconds();
    if (hours < 12) {
      isSyussya = true;
      Serial.println("[午前]");
    } else {
      isSyussya = false;
      Serial.println("[午後]");
    }

    if ((hours >= 8 && hours <= 20) || seconds <= 4) {
      if (epochTime % 2L != 0L) {
        u8g2->sleepOn();
      } else {
        u8g2->sleepOff();
      }
    } else {
      u8g2->sleepOn();
    }

#ifdef HAS_DISPLAY
        if (u8g2) {
            do {
              u8g2->setFont(u8g2_font_inb19_mr);
              u8g2->drawStr(0, 30, formattedTime.c_str());
              // u8g2->setCursor(0, 16);
              // u8g2->println(formattedTime.c_str());
              u8g2->drawStr(0, 60, isSyussya ? "AM" : "PM");
              u8g2->drawStr(60, 60, hasButtonPushed ? "**" : "  ");
            } while ( u8g2->nextPage() );
        }
#endif

    if (!hasButtonPushed) {
      return;
    }

    u8g2->sleepOff();

    if (isSyussya) {
      char* ts = sendSlackMessage(slack_user_oauth_token, slack_channel, "始めるにゃん🐈", "");
    } else {
      char* ts = sendSlackMessage(slack_user_oauth_token, slack_channel, "終わるにゃん🐈", "");
    }

    if (false) {
      char buf[256];
      sprintf(buf, "今の時刻: %s", formattedTime.c_str());
      sendSlackMessage(slack_user_oauth_token, slack_channel, buf, "");
    }

    delay(5000);
    hasButtonPushed = false;
    return;
}

char* sendSlackMessage(const char* token, const char* channel, const char* message, const char* thread_ts)
{
      static char ts[20];
      strcpy(ts, "");

      // Slack Messaging API
      // WiFiClient wifiClient;
      std::unique_ptr<BearSSL::WiFiClientSecure> wifiClient(new BearSSL::WiFiClientSecure);
      // ignore the SSL certificate
      wifiClient->setInsecure();

      // or SSL certificate SHA-1 Fingerprint
      // const uint8_t fingerprint[20] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33 };
      // client->setFingerprint(fingerprint);

      HTTPClient httpClient;
      // httpClient.begin("https://slack.com/api/chat.postMessage");
      httpClient.begin(*wifiClient, "https://slack.com/api/chat.postMessage");
      httpClient.addHeader("Content-Type", "application/x-www-form-urlencoded");

      char buf[256];

      sprintf(buf, ""
        "token=%s"
        "&channel=%s"
        "&text=%s"
        "&thread_ts=%s"
        "&reply_broadcast=%s",
        token,
        channel,
        message,
        thread_ts,
        strlen(thread_ts) > 0 ? "True" : "False"
      );

      Serial.print("thread_ts = ");
      Serial.println(thread_ts);
      Serial.println(buf);

      strcpy(ts, "");

      int status_code = httpClient.POST((uint8_t *)buf, strlen(buf));
      if (status_code == 200)
      {
        Serial.print("OK");

        String json = httpClient.getString();
        Serial.println(json);

        deserializeJson(doc, json);
        if (doc.containsKey("ts"))
        {
          strcpy(ts, doc["ts"]);
          Serial.println(ts);
        }
      }
      else
      {
        Serial.printf("ERR %d", status_code);
        if (status_code <= 0)
        {
          Serial.printf("ERR %s", httpClient.errorToString(status_code).c_str());
        }
      }
      httpClient.end();

      return ts;
}


Tags: [電子工作]

●関連するコンテンツ(この記事を読んだ人は、次の記事も読んでいます)

ESP32で東方の Bad Apple!!の動画を 128 x 64 dotの OLED SSD1306で再生する!
ESP32で東方の Bad Apple!!の動画を 128 x 64 dotの OLED SSD1306で再生する!

  ESP32で東方の Bad Apple!!の動画を再生する!実際にはパラパラ漫画です

LilyGO ESP32 LoRa SX1276を買ってみた、LPWAの急先鋒、LoRaWANも無料
LilyGO ESP32 LoRa SX1276を買ってみた、LPWAの急先鋒、LoRaWANも無料

  LilyGO ESP32 LoRa SX1276を買ってみた

LoRa通信を使用してポストに郵便物が投函されるとスマホの LINE宛に通知する IoTの作り方
LoRa通信を使用してポストに郵便物が投函されるとスマホの LINE宛に通知する IoTの作り方

  LoRaを使用した IoT郵便受け LoRa IoT Mailbox Sensor with LINE Messaging API

ESP32で Slackに「勤怠管理」メッセージをワンボタン操作で投稿する方法
ESP32で Slackに「勤怠管理」メッセージをワンボタン操作で投稿する方法

  Slackの勤怠チャンネルに毎日毎日毎日毎日 手動で投稿するのが馬鹿らしいので ESP32で作った

Espressif ESP32 Arduino互換でスケッチが使える WROOM32開発基板
Espressif ESP32 Arduino互換でスケッチが使える WROOM32開発基板

  Espressif ESP32 32ビット Arduino互換マイコンボードをお手軽に開発する方法

Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板
Espressif ESP8266 Arduino互換でスケッチが使える ESP-12Eモジュール基板

  Espressif ESP8266 ESP-12-E NodeMCU V1 ESP12 CP2102

ESP8266で Python言語 MicroPythonを動かす方法
ESP8266で Python言語 MicroPythonを動かす方法

  Windows 10の WSL環境で ESP8266で Python言語 MicroPythonを動かします

ESP32で Python言語 MicroPythonを動かす方法
ESP32で Python言語 MicroPythonを動かす方法

  Windows 10の WSL環境で ESP32で Python言語 MicroPythonを動かします

LilyGO TTGO T-display ESP32/ RP2040/ GD32 GD32VF103CBT6を買ってみた
LilyGO TTGO T-display ESP32/ RP2040/ GD32 GD32VF103CBT6を買ってみた

  LilyGO TTGO T-display ESP32/ RP2040/ GD32 GD32VF103CBT6を買ってみた

新型 Arduino UNO R4 Minimaのクローンを買った!!
新型 Arduino UNO R4 Minimaのクローンを買った!!

  Renesas RA4M1 Arduino UNO R4 Minima clone 无名科技Nologo Tech




[HOME] | [BACK]
リンクフリー(連絡不要、ただしトップページ以外は Web構成の変更で移動する場合があります)
Copyright (c) 2023 FREE WING,Y.Sakamoto
Powered by 猫屋敷工房 & HTML Generator

http://www.neko.ne.jp/~freewing/hardware/espressif_esp8266_convert_program_esp32/