Arduino筆記(40):ESP8266傳送DHT-11溫濕度到 Gmail信箱

有了 ESP8266-01的溫濕度模組,可以查詢溫濕度的方法有好幾種,其中一種是透過網頁檢視目前溫濕度,這個作法有點被動,需要知道溫度時,再以瀏覽器連線查詢。上一篇實作將溫濕度的偵測值,每兩分鐘就送給 Line 通知用戶,這種方式比較主動。除了 Line 以外,還可以將當時的溫濕度值送到 Email信箱,以下就來看看如何實作將感測值寄到我的 Gmail 信箱。相關ESP8266-01溫濕度模組線路的連接方式,請參考:Arduino筆記(33):透過 ESP8266 無線網路讀取DHT-11的溫濕度

要寄送郵件,有兩個必要條件:
(1) 要有發送的郵件主機 (SMTP) 帳號密碼
要從ESP8266模塊發送電子郵件,您需要遵循SMTP協議。如果沒有其他可以寄信的郵箱,可以申請免費的 SMTP 寄信服務,例如:Sendpulse 、SMTP2GO或其他的 SMTP 服務 。

(2) 傳送的帳號密碼需要以 Base64 加密
由於程式內要送出帳號跟密碼,需要以 Base64 的格式傳送,我們透過 Base64Encode 這個網站將 帳號跟密碼轉換成 Base64 的碼,寫在程式內。以下是 Base64Encode的首頁。可以分別輸入登入 SMTP 的帳號跟密碼,取得兩組編成 Base64的加密字串。例如帳號名稱是[myaccount] 編譯後的結果為 [bXlhY2NvdW50]。

我個人使用中華電信的信箱已經很長一段時間,以下的實作就用中華電信的郵件主機,寄送 DHT-11的溫濕度感測值到我的 Gmail 信箱,完整程式如下:


[程式]

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <DHT.h>

#define DHTTYPE DHT11
#define DHTPIN  2

// 設定網路基地台SSID跟密碼
char ssid[] = "MyHome";
char password[] = "12345678";

char server[] = "xxx.hinet.net";   // The SMTP Server 
String tempe = "";      // 顯示溫度的字串
String humid = "";      // 顯示濕度的字串

DHT dht(DHTPIN, DHTTYPE, 11);   
 
float humidity, temp_f;   // 從 DHT-11 讀取的值

// will store last temp was read
unsigned long previousMillis = 0;  
// interval at which to read sensor 
const long interval = 2000;     

WiFiClient espClient;

void setup()
{
  Serial.begin(9600);
  delay(10);
  Serial.println("");
  Serial.println("");
  Serial.print("Connecting To: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  // 等待連線,並從 Console顯示 IP
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.println("WiFi Connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

 }

void loop()
{

    // 量測間等待至少 2 秒
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis >= interval) {
    // 將最後讀取感測值的時間紀錄下來 
    previousMillis = currentMillis;   

    // 讀取溫度大約 250 微秒!
    humidity = dht.readHumidity();   // 讀取濕度(百分比)
    temp_f = dht.readTemperature(true); // 讀取溫度(華氏)
    
//    humidity = 53.5;
//    temp_f = 102.4;
 
    // 檢查兩個值是否為空值
    if (isnan(humidity) || isnan(temp_f)) {
       Serial.println("Failed to read from DHT sensor!");
       return;
    }
  }

  // 除錯用
  String tempe="現在溫度:"+String((int)(temp_f-32)*5/9)+"℃";   
  String humid="濕度:"+String((int)humidity)+"%";

  Serial.println(tempe);
  Serial.println(humid);
  
  sendEmail(tempe,humid);


  // 每三分鐘會發出一封郵件
  delay(180000);
}

void sendEmail(String tempe, String humid)
{
  // 使用 25 Port 連線
  if (espClient.connect(server, 25) == 1) {
    Serial.println(F("connected"));
  } 
  else  {
    Serial.println(F("connection failed"));
    return;
  }
  
  if (!emailResp()) 
    return;
  // 使用EHLO命令問候 SMTP服務器。
  // 如果連接成功,會得到回應碼 250
  Serial.println(F("Sending EHLO"));
  espClient.println("EHLO www.example.com");
  if (!emailResp()) 
    return;

  // 使用AUTH LOGIN 指令登入授權用戶。
  // 如果連接成功,會得到回應碼 334
  Serial.println(F("Sending auth login"));
  espClient.println("AUTH LOGIN");
  if (!emailResp()) 
    return;

  // 發送郵件登入 SMTP 主機的帳號, 
  //需要用 BASE64編碼,需使用者自行修改
  Serial.println(F("Sending User"));
  espClient.println("ABCD123456"); // 
  if (!emailResp()) 
    return;

  // 發送郵件登入 SMTP 主機的密碼, 
  // 需要用 BASE64編碼,需使用者自行修改
  Serial.println(F("Sending Password"));
  espClient.println("ABCD123456");  
  if (!emailResp()) 
    return;

  // 寄件者郵箱名稱
  Serial.println(F("Sending From"));
  espClient.println(F("MAIL From: xxx@ms4.hinet.net"));
  if (!emailResp()) 
    return;
    
  // 收件者郵箱名稱
  Serial.println(F("Sending To"));
  espClient.println(F("RCPT To: xxx@gmail.com"));
  if (!emailResp()) 
    return;
    
  // 發送"DATA",然後發送電子郵件的內文
  Serial.println(F("Sending DATA"));
  espClient.println(F("DATA"));
  if (!emailResp()) 
    return;
    
  Serial.println(F("Sending email"));

  // 改成您的收件者郵箱名稱
  espClient.println(F("To: xxx@gmail.com"));

  // 改成您的送件者郵箱名稱
  espClient.println(F("From: xxx@ms4.hinet.net"));
  espClient.println(F("Subject: ESP8266 test e-mail\r\n"));
  espClient.println(F("This is a e-mail sent from ESP8266.\n"));
  espClient.println(tempe);
  espClient.println(humid);
 
  //
  espClient.println(F("."));
  if (!emailResp()) 
    return;

  //終止郵件並發送quit命令
  Serial.println(F("Sending QUIT"));
  espClient.println(F("QUIT"));
  
  if (!emailResp()) 
    return;

  espClient.stop();
  Serial.println(F("disconnected"));
}

byte emailResp() {
  byte responseCode;
  byte readByte;
  int loopCount = 0;

  while (!espClient.available()) 
  {
    delay(1);
    loopCount++;

    // 等待 20 秒,如果無法接收就停止
    if (loopCount > 20000) {
      espClient.stop();
      Serial.println(F("\r\nTimeout"));
      return 0;
    }
  }

  responseCode = espClient.peek();
  while (espClient.available()) {
    readByte = espClient.read();
    Serial.write(readByte);
  }

  if (responseCode >= '4') {
    //  efail();
    return 0;
  }
  return 1;
}

[執行結果]



[參考資料]

ELECTRONICS HUB:How to Send an Email using ESP8266 WiFi Module?

5 留言

  1. hi 你好
    有如此的應用我很有興趣 ,依你的程式碼 我可以發送email 到我的指定信箱可是不是每一封都成功,觀察中發現只有在 250 msr11 的時候才可以收到,想請教是那出了問題?

    回覆刪除
    回覆
    1. 您好, 這應該是跟mail Server有關,也就是mail server要有SMTP的權限,通常是要帳號密碼才能透過這個帳號寄送。我曾遇到一種狀況是:如果是非中華電信的線路商連線(當時是台灣大哥大線路),無法直接打開Outlook寄信,必須回到中華電信的網頁上才可以寄信。您再看一下是否是因為mail server SMTP權限的問題而無法正常寄信。

      刪除
  2. 非常感謝您的分享。 您提到的用於在線base64解碼和編碼的工具很棒。 但是,這是另一個工具,您可以將其用作替代工具。 該工具是
    url-decode.com/tool/base64-encode
    這也使您可以訪問其他數量的Web實用程序。

    回覆刪除
  3. 網誌管理員已經移除這則留言。

    回覆刪除

張貼留言

較新的 較舊