งานที่ 11
- รับลิงก์
- X
- อีเมล
- แอปอื่นๆ
NodeMCU ESP8266 ESP32 IoT 30 วัน 30 โปรเจค วันที่ 3 รายงานสภาพอากาศ พยากรณ์อากาศจาก Google
3 ปีที่ผ่านมา
โดย เจ้าของร้าน
วันนี้เราจะมาทำ เครื่องรายงานสภาพอากศ จาก Google Weather โดยใช้อุปกรณ์จากวันที่ 2 เลย การต่อสายยังเหมือนเดิม แค่ปรับโค้ดใหม่ โดยหลักการทำงานก็คล้ายๆกันกับของวันที่ 2 คือ ตัว ESP8266 หรือ NodeMCU ของเราจะเข้าไปเชื่อมต่อ Wifi ที่ตั้งค่าไว้ จากนั้นก็เข้าไปดึงข้อมูลของการค้นหาคำว่า weather+[ชื่อเมือง] จาก google ซึ่งถ้าเราได้ลอง search ดูเว็บของ google มันจะแสดงรายงานสภาพอากาศออกมาพร้อมกับการผลลัพท์การ search เราก็แค่เอาส่วนนั้นมาตัดอันที่ไม่จำเป็นออกไปและ เหลือไว้เฉพาะข้อความที่จะเอามาแสดงผล จากนั้นก็ส่งให้ LCD ของเรานั่นเอง
สำหรับใครที่หลงเข้ามาก็สามารถตามอ่านของวันที่สองได้ที่นี่ครับ
https://www.mosfex.com/article/2
อันดับแรกก็ต้องเตรียมอุปกรณ์กันก่อนเลย (เผื่อใครยังไม่มี)
1. NodeMCU https://www.mosfex.com/product/38/
2. LCD 16x2 I2C https://www.mosfex.com/product/18/
3. สายแพ เมีย-เมีย https://www.mosfex.com/product/60/

จากนั้นก็ต่อสายไฟตาม Diagram ระวังอย่าต่อกลับขั้วกันนะ

ต่อมาเข้าไป Download โค้ดที่
https://github.com/mosfex/ESP8266_Google_Weather/blob/master/esp8266_google_weather.ino
แล้วก็มาวางใส่ Arduino ของเรา

ต่อมาทำการแก้ไข wifi และชื่อเมืองที่จะแสดงสภาพอากาศ

ประเด็นสำคัญอยู่ตรงนี้ มาลองดูโค้ดที่สำคัญกันหน่อยดีกว่า
ตรงนี้นะมันเป็นการร้องขอข้อมูลไปที่ google โดยเนียนว่าเราเป็น Android (ตรง User-Agent)
ที่ต้องทำเป็น android เพราะว่ามันแสดงข้อความได้เหมาะสม ไม่มี javascript อะไรเลย ทำให้ดึงข้อความไปแสดงผลง่าย
และตรง /search?q=weather+")+city+"&hl=en มันคือการค้นหาข้อความ weather+bangkok จาก google นั่นแหละ แต่เราใส่ hl=en ไปด้วยเป็นการบังคับให้ google แสดงผลเป็นภาษาอังกฤษออกมาแทนที่จะเป็นภาษาไทย เพราะเราแสดงภาษาไทยบน LCD ไม่ได้
String url = String("/search?q=weather+")+city+"&hl=en";
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: Mozilla/5.0 (Android 4.4; Mobile; rv:18.0) Gecko/18.0 Firefox/18.0\r\n" +
"Accept: text/html\r\n"+
"Connection: close\r\n\r\n");
ไปต่อการที่การ parse ข้อความ
ด้านล่างนี้เป็นการ ดึึงข้อความมาทีล่ะ tag จนเจอ table class ts ซึงเป็นส่วนข้อมูลที่เก็บสภาพอากาศเอาไว้
String line = client.readStringUntil('>');
if(line.startsWith("
ต่อไป เราจะ parse เอาเฉพาะข้อความ เรื่อยๆ จนเจอ หมดในส่วนข้อความ โดยดึงมาที่ล่ะตัวๆ
ถ้ามันเปิด < หมายถึึงเป็น html ก็ไม่ต้องเอาเก็บไว้ ส่วนถ้ามันปิด > ก็แสดงว่า html หมดแล้ว ค่อยเอาข้อความมาเก็บ
การทำแบบนี้จะทำให้การ process ได้ไวการเอามาเก็บใน string แล้ว search หาด้วย ซึ่งอาจเสี่ยงต่อการที่แรมเต็มแล้ว esp8266 รีสตาร์ตตัวเอง (ตัวแตก)
ในบางส่วนจะมีการ check นิดหน่อย คือ ถ้าปิดเปิด tag เยอะมันจะมี spacebar เลยต้องทำ buffer ใส่ string คอย check ด้วยว่าท้ายข้อความมี spacebar อยู่ไหม เดี๋ยวข้อความที่เอาไปแสดงจะไม่สวย อิอิ
while(line.indexOf(" if(client.available()){
char d = client.read();
if(d == '<') opentag = true;
if(d == '>'){ opentag = false; }
if(opentag == false){
if(d == '>' && forcast[forcast.length()-1] != ' '){
forcast += " ";
}else if(d != '>' && d<= 127){
forcast += d;
}
}else{
line += d;
}
}
}
เมื่อได้ครบแล้ว function ก็จะ return ข้อความพร้อมเอาไปแสดงผล ซึ่งในส่วนการแสดงผลเราจะให้มัน scroll ตัวเองด้วย ทุกๆ loop 400ms (ลองปรับดูได้) (ลองใช้ autoscroll ใน library ดูแล้วไม่ work มาก) หลักการ scroll แค่ให้มัน substing ตัวแรกออกมาแล้วเอาไปต่อที่ตัวสุุดท้ายนั่นเอง
forcast = forcast.substring(1,forcast.length()) + forcast.substring(0,1);
และยังมีส่วนนับเวลา ถ้ามันเกิน 60 วินาทีเมื่อไหร่เราก็ไปดึึงข้อความจาก google มาแสดงผลใหม่
void loop() {
if((millis() - counter) > 60000){
forcast = get_forcast();
counter = millis();
}
lcd.setCursor(0,1);
forcast = forcast.substring(1,forcast.length()) + forcast.substring(0,1);
lcd.print(forcast.substring(0,16));
delay(400);
}
หมดล่ะโค้ด อัพโหลด ดูผลกันได้เลย


นี่ผลลัพท์ที่ได้

เสร็จเรียบร้อยแล้ว อย่าลืมไป Like ใน Fanpage mosfex กันด้วยนะ ^^

สำหรับใครที่หลงเข้ามาก็สามารถตามอ่านของวันที่สองได้ที่นี่ครับ
https://www.mosfex.com/article/2
อันดับแรกก็ต้องเตรียมอุปกรณ์กันก่อนเลย (เผื่อใครยังไม่มี)
1. NodeMCU https://www.mosfex.com/product/38/
2. LCD 16x2 I2C https://www.mosfex.com/product/18/
3. สายแพ เมีย-เมีย https://www.mosfex.com/product/60/

จากนั้นก็ต่อสายไฟตาม Diagram ระวังอย่าต่อกลับขั้วกันนะ

ต่อมาเข้าไป Download โค้ดที่
https://github.com/mosfex/ESP8266_Google_Weather/blob/master/esp8266_google_weather.ino
แล้วก็มาวางใส่ Arduino ของเรา

ต่อมาทำการแก้ไข wifi และชื่อเมืองที่จะแสดงสภาพอากาศ

ประเด็นสำคัญอยู่ตรงนี้ มาลองดูโค้ดที่สำคัญกันหน่อยดีกว่า
ตรงนี้นะมันเป็นการร้องขอข้อมูลไปที่ google โดยเนียนว่าเราเป็น Android (ตรง User-Agent)
ที่ต้องทำเป็น android เพราะว่ามันแสดงข้อความได้เหมาะสม ไม่มี javascript อะไรเลย ทำให้ดึงข้อความไปแสดงผลง่าย
และตรง /search?q=weather+")+city+"&hl=en มันคือการค้นหาข้อความ weather+bangkok จาก google นั่นแหละ แต่เราใส่ hl=en ไปด้วยเป็นการบังคับให้ google แสดงผลเป็นภาษาอังกฤษออกมาแทนที่จะเป็นภาษาไทย เพราะเราแสดงภาษาไทยบน LCD ไม่ได้
String url = String("/search?q=weather+")+city+"&hl=en";
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: Mozilla/5.0 (Android 4.4; Mobile; rv:18.0) Gecko/18.0 Firefox/18.0\r\n" +
"Accept: text/html\r\n"+
"Connection: close\r\n\r\n");
ไปต่อการที่การ parse ข้อความ
ด้านล่างนี้เป็นการ ดึึงข้อความมาทีล่ะ tag จนเจอ table class ts ซึงเป็นส่วนข้อมูลที่เก็บสภาพอากาศเอาไว้
String line = client.readStringUntil('>');
if(line.startsWith("
ต่อไป เราจะ parse เอาเฉพาะข้อความ เรื่อยๆ จนเจอ หมดในส่วนข้อความ โดยดึงมาที่ล่ะตัวๆ
ถ้ามันเปิด < หมายถึึงเป็น html ก็ไม่ต้องเอาเก็บไว้ ส่วนถ้ามันปิด > ก็แสดงว่า html หมดแล้ว ค่อยเอาข้อความมาเก็บ
การทำแบบนี้จะทำให้การ process ได้ไวการเอามาเก็บใน string แล้ว search หาด้วย ซึ่งอาจเสี่ยงต่อการที่แรมเต็มแล้ว esp8266 รีสตาร์ตตัวเอง (ตัวแตก)
ในบางส่วนจะมีการ check นิดหน่อย คือ ถ้าปิดเปิด tag เยอะมันจะมี spacebar เลยต้องทำ buffer ใส่ string คอย check ด้วยว่าท้ายข้อความมี spacebar อยู่ไหม เดี๋ยวข้อความที่เอาไปแสดงจะไม่สวย อิอิ
while(line.indexOf(" if(client.available()){
char d = client.read();
if(d == '<') opentag = true;
if(d == '>'){ opentag = false; }
if(opentag == false){
if(d == '>' && forcast[forcast.length()-1] != ' '){
forcast += " ";
}else if(d != '>' && d<= 127){
forcast += d;
}
}else{
line += d;
}
}
}
เมื่อได้ครบแล้ว function ก็จะ return ข้อความพร้อมเอาไปแสดงผล ซึ่งในส่วนการแสดงผลเราจะให้มัน scroll ตัวเองด้วย ทุกๆ loop 400ms (ลองปรับดูได้) (ลองใช้ autoscroll ใน library ดูแล้วไม่ work มาก) หลักการ scroll แค่ให้มัน substing ตัวแรกออกมาแล้วเอาไปต่อที่ตัวสุุดท้ายนั่นเอง
forcast = forcast.substring(1,forcast.length()) + forcast.substring(0,1);
และยังมีส่วนนับเวลา ถ้ามันเกิน 60 วินาทีเมื่อไหร่เราก็ไปดึึงข้อความจาก google มาแสดงผลใหม่
void loop() {
if((millis() - counter) > 60000){
forcast = get_forcast();
counter = millis();
}
lcd.setCursor(0,1);
forcast = forcast.substring(1,forcast.length()) + forcast.substring(0,1);
lcd.print(forcast.substring(0,16));
delay(400);
}
หมดล่ะโค้ด อัพโหลด ดูผลกันได้เลย


นี่ผลลัพท์ที่ได้

เสร็จเรียบร้อยแล้ว อย่าลืมไป Like ใน Fanpage mosfex กันด้วยนะ ^^

- รับลิงก์
- X
- อีเมล
- แอปอื่นๆ
ความคิดเห็น
แสดงความคิดเห็น