ThingSpeak雲端平台修改了MQTT服務的設置方式,本文將說明取得MQTT密碼的步驟,以及在ESP8266控制板(如:NodeMCU或Wemos D1 mini)執行Arduino和MicroPython,透過MQTT協定上傳DHT11溫溼度資料到ThingSpeak的程式碼。
本文的硬體連線與「MQTT教學(九)」相同:

新增ThingSpeak的MQTT裝置
舊版的ThingSpeak “My Profile”頁面有個產生MQTT API密鑰的欄位,在新版網頁中移除了,改由底下步驟產生MQTT API密鑰。
1. 登入ThingSpeak網站後,點擊導覽列上的Devices→MQTT(裝置→MQTT)選單。

2. 在MQTT Devices(MQTT裝置)頁面,點擊Add a new device(新增一個裝置)鈕:

3. 在底下的畫面中,填入裝置名稱和描述、選擇要授權存取的通道,然後按下Add Channel(新增通道)鈕。

4. 畫面底下將顯示已授權的通道。點擊Add Device(新增裝置)鈕。

5. 畫面將顯示新增裝置的用戶端ID、使用者名稱和密碼,請複製這些密碼備用,也可以點擊左下的Download Credentials鈕儲存純文字格式的密鑰。

6. 按下Done(完成)鈕,畫面將顯示MQTT裝置的摘要。

上傳資料到ThingSpeak MQTT伺服器的MicroPython程式
沿用《超圖解Python物聯網實作入門》18-22頁的MicroPython程式碼,需要修改MQTT伺服器的網址、使用者名稱、密碼和用戶端ID。topic(主題)字串末尾,本來有附加「寫入API密鑰」,現在不需要了,修改後的完整程式碼如下:
import machine
import ubinascii
import time
import dht
from machine import Pin
from umqtt.simple import MQTTClient
config = {
'broker':'mqtt3.thingspeak.com', # 之前是:mqtt.thingspeak.com
'user': '上個步驟產生的使用者名稱',
'pwd': '上個步驟產生的密碼',
'id' : '上個步驟產生的用戶端ID',
'port':1883,
'topic' : b'channels/通道ID/publish' # 不用填「寫入API密鑰」
}
client = MQTTClient(client_id=config['id'],
server=config['broker'],
port=config['port'],
user=config['user'],
password=config['pwd'])
d = dht.DHT11(Pin(5)) # DHT11接GPIO5 (D1)
d.measure()
data = 'field1={}&field2={}'.format(
d.temperature(),
d.humidity())
client.connect()
client.publish(config['topic'], data.encode())
time.sleep(2)
client.disconnect()
在燒錄MicroPython的ESP8266執行上面的程式,它將上傳DHT11溫濕度到ThingSpeak平台。
上傳資料到ThingSpeak MQTT伺服器的Arduino程式
修改「MQTT教學(九)」貼文的Arduino程式,更新MQTT伺服器的網址、使用者名稱、密碼和用戶端ID。topic(主題)字串末尾,本來有附加「寫入API密鑰」,現在不需要了,修改後的完整程式碼如下:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <dht11.h>
#define DHT11PIN D1 // DHT11資料接腳
#define mqttPort 1883 // MQTT伺服器埠號
const char* ssid = "Wi-Fi網路名稱";
const char* password = "Wi-Fi網路密碼";
const char* mqttServer = "mqtt3.thingspeak.com"; // MQTT伺服器位址
const char* mqttUserName = "使用者名稱";
const char* mqttPwd = " MQTT密碼";
const char* clientID = "用戶端ID ";
const char* topic = "channels/通道ID/publish"; // 不用填「寫入API密鑰」
unsigned long prevMillis = 0; // 暫存經過時間(毫秒)
const long interval = 20000; // 上傳資料的間隔時間,20秒。
String msgStr = ""; // 暫存MQTT訊息字串
dht11 DHT11;
int temp; // 暫存溫度
int hum; // 暫存濕度
WiFiClient espClient;
PubSubClient client(espClient);
void setup_wifi() {
delay(10);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
}
void reconnect() {
while (!client.connected()) {
if (client.connect(clientID, mqttUserName, mqttPwd)) {
Serial.println("MQTT connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000); // 等5秒之後再重試
}
}
}
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqttServer, mqttPort);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// 等待20秒
if (millis() - prevMillis > interval) {
prevMillis = millis();
// 讀取DHT11的溫濕度資料
int chk = DHT11.read(DHT11PIN);
if (chk == 0) {
temp = DHT11.temperature;
hum = DHT11.humidity;
}
// 組合MQTT訊息;field1填入溫度、field2填入濕度
msgStr = msgStr + "field1=" + temp + "&field2=" + hum;
Serial.print("Publish message: ");
Serial.println(msgStr);
client.publish(topic, msgStr.c_str()); // 發布MQTT主題與訊息
msgStr = "";
}
}
編譯、上傳程式到ESP8266控制板,它將上傳DHT11溫濕度到ThingSpeak平台。

想知道怎麼透過MQTT上傳感測器E18-D80NK感測器資料到THINGSPEAK平台(也是使用ESP8266,NODE MCU V2)
1. 讀取感測器資料
2. 上傳ThingSpeak
3. 延遲一段時間
4. 重複1
老師 您好,
想詢問一下,當感測器 DHT11 Publish 到ThingSpeak ,如果到一定閥值例如30度,要透過ThingSpeak發布訊息給Client(ESP : subscribe),以這樣的架構能否用 ThingSpeak一些內建的功能,來達到此目的?
應該沒有這樣的設定,要由你的程式碼判斷執行。