# Arduino 網路測試 : 發送 Twitter
但是自從學會使用 ESP8266 讓 Arduino 上網之後, 這塊又貴又大 (比起 ESP8266) 的板子就連同 UNO 一起放在零件盒裡不見天日了. 能用 Wifi 上網幹嘛還要用需要拉網路線的乙太網呢?
今天在 Oreilly "Arduino Cookbook 錦囊妙計" 這本書的 15.12 節又看到傳送訊息到 Twitter 的介紹, 那今晚就用 ESP8266 來重作這個實驗吧!
在上面 2015/4/2 的 Twitter 實驗中, 我是依照 "Arduino 自造指南" 這本書的作法, 透過 arduino-tweet 這個第三方網站所提供的函式庫來傳送訊息給 Twitter. 不過那個函式庫是為乙太網寫的, 沒辦法用在 ESP8266. 在歐萊里出版的 "Arduino Cookbook 錦囊妙計" 這本書裡的 15.12 節有介紹利用 Thingspeak 的 ThingTweet API 來當中繼站傳送 Tweet 訊息到自己的推特.
首先登入 Thingspeak 帳戶, 切換到 Apps 頁籤即可看到 ThingTweet 入口 :
點 "ThingTweet" 後按 "Link Twitter Account" 按鈕 :
按 "授權應用程式" 鈕 :
這樣就表示已授權 Thingspeak 傳送訊息到我的推特了.
按 "Back to ThingTweet" 就可以看到 API Key 了, 這個要記錄下來, 程式中要用到 :
接下來就可以撰寫程式, 讓 Arduino 利用 ESP8266 的 Wifi 連線功能向 Thingspeak 發出連線要求, 傳送 Tweet 訊息, 由 ThingTweet API 代為轉發到我們的推特上. 首先必須與 Thingspeak (網址 api.thingspeak.com) 建立 TCP 連線, 其 AP 指令如下 :
AT+CIPSTART="TCP","api.thingspeak.com",80
然後告訴 ESP8266 接下來要傳送的資料長度 :
AT+CIPSEND=字元數
最後傳送資料 (HTTP 內容), Thingspeak 網站的範例使用 HTTP 的 POST 方法, 下面這篇文章則是使用 GET 方法, 參考 :
# Beginner's guide to ESP8266 and tweeting using ESP8266
GET /apps/thingtweet/1/statuses/update?api_key=ThingTweet識別碼&status=要傳送的推特訊息
完整的程式如下 :
#include <SoftwareSerial.h>
#define DEBUG true
SoftwareSerial esp8266(7,8); //(RX,TX)
String ThingTweet_API="B2B4JF5WEUXGCOUY";
int i=0; //counter
void setup() {
Serial.begin(9600);
esp8266.begin(9600);
sendData("AT+RST\r\n",2000,DEBUG); // reset ESP8266
sendData("AT+GMR\r\n",1000,DEBUG);
delay(3000); //wait for wifi connection to get local ip
sendData("AT+CIFSR\r\n",1000,DEBUG); //get ip address
}
void loop() {
Serial.println("Connecting Thingspeak ...");
sendData("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80\r\n",1000,DEBUG);
String data="GET /apps/thingtweet/1/statuses/update?api_key=" + ThingTweet_API +
"&status=Hello! " + i + " times.\r\n";
sendData("AT+CIPSEND=" + (String)data.length() + "\r\n",1000,DEBUG);
String res=sendData(data,3000,DEBUG);
res.replace("\r\n",""); //remove all line terminator
if (res.indexOf("Unlink") == -1) { //if no auto unlink
sendData("AT+CIPCLOSE\r\n",2000,DEBUG); //close session
}
delay(60000);
i++;
}
String sendData(String command, const int timeout, boolean debug) {
String res="";
esp8266.print(command);
long int time=millis();
while ((time + timeout) > millis()) {
while(esp8266.available()) {res.concat((char)esp8266.read());}
}
if (debug) {Serial.print(res);}
return res;
}
此程式中我使用了一個發送次數計數器來避免每次發文內容相同, 這是推特的限制之一, 即連續兩次推文不可雷同, 否則第二則推文不會發送成功. 另外推特還有一個限制, 就是一分鐘內只能發送一個推文, 因此我在 loop() 最底下用了 delay(60000) 讓程式到此停止一分鐘以滿足推特之限制. 此程式每分鐘會發出 "Hello! x times." 的推文到我的 Twitter 上. 另外, length() 傳回的是整數, 因此必須用 (String) 強制轉型.
程式上傳執行後, 我手機果然每分鐘收到推文了 :
串列埠監控視窗擷取訊息如下 :
AT+RST
OK
bB�鑭b禕S��"愃L�侒��餾�
[System Ready, Vendor:www.ai-think
192.168.43.40
OK
Connecting Thingspeak ...
AT+CIPSTART="TCP","api.thingspeak.com",80
OK
Linked
AT+CIPSEND=88
> GET /apps/thingtweet/1/statuses/update?api_key=B2B4JF5WEUXGCOUY
SEND OK
+IPD,1:1
OK
OK
Unlink
Connecting Thingspeak ...
AT+CIPSTART="TCP","api.thingspeak.com",80
OK
Linked
AT+CIPSEND=88
> GET /apps/thingtweet/1/statuses/update?api_key=B2B4JF5WEUXGCOUY
SEND OK
+IPD,1:1
OK
OK
Unlink
2016-07-27 補充 :
上面範例程式使用我自製的 IOT 模組, 已經事先切換到設定模式, 以手機設定好要連線之 AP 後, 再切回工作模式, 因 ESP8266 特性是除非寫入新的設定值, 否則它就保存最近一次的寫入值, 因此上面範例程式中不須使用 AT+CWJAP 指令去設定要連線之 AP.
如果要在程式中自行設定連線 AP 要怎麼做? 下列範例程式中我另外寫了一個 connectWifi() 函數, 只要傳入 ssid 與 pwd, 它會向 ESP8266 送出 AT+CWJAP 指令, 若回應中有 "OK", 就回傳 true, 否則 false.
#include <SoftwareSerial.h>
#define DEBUG true
SoftwareSerial esp8266(7,8); //(RX,TX)
String ssid="H30-L02-webbot";
String pwd="1234567890";
String ThingTweet_API="B2B4JF5WEUXGCOUY";
int i=0; //counter
void setup() {
Serial.begin(9600);
esp8266.begin(9600);
sendData("AT+RST\r\n",2000,DEBUG); // reset ESP8266
while (!connectWifi(ssid, pwd)) {
Serial.println("Connecting WiFi ... failed");
delay(2000);
}
sendData("AT+GMR\r\n",1000,DEBUG);
delay(3000); //wait for wifi connection to get local ip
sendData("AT+CIFSR\r\n",1000,DEBUG); //get ip address
}
void loop() {
Serial.println("Connecting Thingspeak ...");
sendData("AT+CIPSTART=\"TCP\",\"api.thingspeak.com\",80\r\n",1000,DEBUG);
String data="GET /apps/thingtweet/1/statuses/update?api_key=" + ThingTweet_API +
"&status=Hello! " + i + " times.\r\n";
sendData("AT+CIPSEND=" + (String)data.length() + "\r\n",1000,DEBUG);
String res=sendData(data,3000,DEBUG);
res.replace("\r\n",""); //remove all line terminator
if (res.indexOf("Unlink") == -1) { //if no auto unlink
sendData("AT+CIPCLOSE\r\n",2000,DEBUG); //close session
}
delay(60000);
i++;
}
boolean connectWifi(String ssid, String pwd) {
String res=sendData("AT+CWJAP=\"" + ssid + "\",\"" + pwd + "\"\r\n",8000,DEBUG);
res.replace("\r\n",""); //remove all line terminator
if (res.indexOf("OK") != -1) {return true;}
else {return false;}
}
String sendData(String command, const int timeout, boolean debug) {
String res="";
esp8266.print(command);
long int time=millis();
while ((time + timeout) > millis()) {
while(esp8266.available()) {res.concat((char)esp8266.read());}
}
if (debug) {Serial.print(res);}
return res;
}
在 setup() 中我們用 while 來檢查 connectWifi() 是否傳回 true, 是的話表示連線成功, 否則就一直印出連線失敗訊息, while 迴圈不會結束, 因此沒機會到 loop() 中執行 twitter 訊息之發布. 注意, 在 connectWifi() 函數中, AT+CWJAP 的等待時間若太短的話, 可能會一直無法連上基地台, 因為連線需要一些時間. 我之前用 6 秒, 發覺不是很穩定, 調成 8 秒後就沒問題了.
參考 :
# How to tweet from an Arduino using the wifi sheild
# 以 Arduino+ESP8266 物聯網模組重作 DHT11 溫溼度實驗
# How to tweet with your Arduino
# Twitter controlled Arduino Outputs - no PC - LCD Display + Sensor data to Twitter
# TweetControl: Control Anything with Twitter
6 則留言 :
酷~~
版主您好
我想使用以下方法讓推特自動發文
String data="GET /apps/thingtweet/1/statuses/update?api_key=" + ThingTweet_API;
data += "&status=濕度: " + (String)h +"%";
data += "% 溫度: " + (String)t + "*C.\r\n";
data += "\r\n";
如果只有濕度是可以的((String)h後面加上"%"就不行 其他字就可以)
DEBUG一直回傳無法正常發文的訊息 請問要如何在一篇推特文章中加入2個由ARDUINO取得的變數呢?
還有想問如何讓推特文章換行?
林兄您好, url 字串中 % 字元有特殊用途 (表示編碼), 要傳送 '%' 字元本身要改用 '%25', 而跳行則要改用 '%0d%0a'.
參考 : http://www.convertstring.com/zh_TW/EncodeDecode/UrlEncode 與 https://openhome.cc/Gossip/Encoding/URLEncoding.html :
"在URI的規範中定義了一些保留字元(Reserved character),像是「:」、「/」、「?」、「&」、「=」、「@」、「%」等字元,在URI中都有它的作用,如果你要在請求參數上表達URI中的保留字元,必須在%字元之後以十六進位數值表示方式,來表示該字元的八個位元數值。"
Tony Huang 感謝您的回覆,終於藉由編碼打出%和換行了
真的非常感謝您!!
可以跟你問一下 為甚麼 我加按鈕上去 變成無法傳送文字上去 是因為delay問題嗎>?
按鈕有機械彈跳現象需處理, 參考 :
http://yhhuang1966.blogspot.tw/2016/09/arduino_11.html
http://yhhuang1966.blogspot.tw/2016/09/arduino-interrupt.html
張貼留言