Twitter Hash Search Application with #️⃣NodeMCU(ESP8266) #️⃣ILI9341

This commit is contained in:
Eric
2020-08-15 20:08:33 -07:00
parent 0c34731714
commit 94d21da617
4 changed files with 350 additions and 0 deletions

View File

@@ -0,0 +1,184 @@
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
#include <ArduinoJson.h>
#include <TwitterWebAPI.h>
#include <TJpg_Decoder.h>
// Include SPIFFS
#define FS_NO_GLOBALS
#include <FS.h>
#include "List_SPIFFS.h"
#include "Web_Fetch.h"
#include "SPI.h"
#include "TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
#ifndef WIFICONFIG
const char* ssid = "<YOUR_WIFI_SSID>";
const char* password = "<YOUR_WIFI_PW>";
#endif
std::string search_str = "#WeWantToPlay"; // Default search word for twitter
const char *ntp_server = "pool.ntp.org"; // time1.google.com, time.nist.gov, pool.ntp.org
int timezone = -7; // Pacific Daylight Time -07:00 HRS
unsigned long twi_update_interval = 10; // (seconds) minimum 5s (180 API calls/15 min). Any value less than 5 is ignored!
#ifndef TWITTERINFO // Obtain these by creating an app @ https://apps.twitter.com/
static char const consumer_key[] = "<API_Key>";
static char const consumer_sec[] = "<API_Key_Secret>";
static char const accesstoken[] = "<Access_Token>";
static char const accesstoken_sec[] = "<Access_Token_Secret>";
#endif
const char* userProfileImage = "/profile_user.jpg";
const char* placeholderImage = "/placeholder.jpg";
unsigned long api_mtbs = twi_update_interval * 1000; //mean time between api requests
unsigned long api_lasttime = 0;
String search_msg = "No Message Yet!";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, ntp_server, timezone*3600, 60000); // NTP server pool, offset (in seconds), update interval (in milliseconds)
TwitterClient tcr(timeClient, consumer_key, consumer_sec, accesstoken, accesstoken_sec);
void initSPIFFS(){
// Initialise SPIFFS
if (!SPIFFS.begin()) {
Serial.println("SPIFFS initialisation failed!");
while (1) yield(); // Stay here twiddling thumbs waiting
}
Serial.println("\r\nInitialisation done.");
//SPIFFS.format(); //Only for the first time!
listSPIFFS();
}
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
if ( y >= tft.height() ) return 0;
tft.pushImage(x, y, w, h, bitmap);
return 1;
}
void initTFT(){
tft.init();
tft.fillScreen(TFT_BLACK);
tft.setRotation(3);
tft.setTextColor(TFT_WHITE);
tft.setFreeFont(&FreeSans9pt7b);
tft.setCursor(0, 30);
tft.println("Twitter Hashtag Search");
TJpgDec.setJpgScale(1);
TJpgDec.setSwapBytes(true);
TJpgDec.setCallback(tft_output);
}
void printToTFT(String msg){
tft.println(msg);
}
void showTweet(){
tft.fillScreen(TFT_BLACK);
tft.setTextColor(TFT_WHITE);
tft.setFreeFont(&FreeSansBold12pt7b);
tft.setCursor(120, 40);
tft.println(search_str.c_str());
tft.setFreeFont(&FreeSans9pt7b);
tft.setCursor(0, 80);
tft.println(search_msg.c_str());
}
void setup(void){
Serial.begin(115200);
initSPIFFS();
initTFT();
// WiFi Connection
WiFi.begin(ssid, password);
Serial.print("\nConnecting to ");
Serial.print(ssid);
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected. yay!");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
printToTFT("WIFI Connected!");
delay(100);
// Connect to NTP and force-update time
tcr.startNTP();
Serial.println("NTP Synced");
printToTFT("NTP Synced!");
delay(100);
printToTFT("Loading...");
}
void extractJSON(String tmsg) {
//Serial.println(tmsg);
size_t len = tmsg.length();
Serial.printf("msg length: %d\n", len);
if(len < 1000) return;
DynamicJsonDocument doc(len*2);
DeserializationError error = deserializeJson(doc, tmsg, DeserializationOption::NestingLimit(20));
if(error){
Serial.print(F("DeserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
if(doc.containsKey("statuses")){
String userT = doc["statuses"][0]["user"]["screen_name"];
String text = doc["statuses"][0]["text"];
if(text != ""){
search_msg = "@" + userT + " says " + text;
}
showTweet();
TJpgDec.drawFsJpg(10, 10, placeholderImage);
String profile_image_url = doc["statuses"][0]["user"]["profile_image_url"];
Serial.println(profile_image_url);
if(profile_image_url.indexOf("_normal") > 0){
bool loaded_ok = getFile(profile_image_url, userProfileImage);
listSPIFFS();
if(loaded_ok){
uint16_t w = 0, h = 0;
TJpgDec.getFsJpgSize(&w, &h, userProfileImage);
if(w !=0 && h != 0){
TJpgDec.drawFsJpg(10, 10, userProfileImage);
}
}
}
}else if(doc.containsKey("errors")){
String err = doc["errors"][0];
search_msg = err;
}else{
Serial.println("No Useful Data");
}
}
void loop(void){
if (millis() > api_lasttime + api_mtbs) {
extractJSON(tcr.searchTwitter(search_str));
api_lasttime = millis();
}
delay(2);
yield();
}

View File

@@ -0,0 +1,88 @@
//https://github.com/Bodmer/TJpg_Decoder
/***************************************************************************************
** Function name: listSPIFFS
** Description: Listing SPIFFS files
***************************************************************************************/
#ifdef ESP8266
void listSPIFFS(void) {
Serial.println(F("\r\nListing SPIFFS files:"));
fs::Dir dir = SPIFFS.openDir("/"); // Root directory
static const char line[] PROGMEM = "=================================================";
Serial.println(FPSTR(line));
Serial.println(F(" File name Size"));
Serial.println(FPSTR(line));
while (dir.next()) {
String fileName = dir.fileName();
Serial.print(fileName);
int spaces = 33 - fileName.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
fs::File f = dir.openFile("r");
String fileSize = (String) f.size();
spaces = 10 - fileSize.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
Serial.println(fileSize + " bytes");
}
Serial.println(FPSTR(line));
Serial.println();
delay(1000);
}
//====================================================================================
#elif defined ESP32
void listSPIFFS(void) {
Serial.println(F("\r\nListing SPIFFS files:"));
static const char line[] PROGMEM = "=================================================";
Serial.println(FPSTR(line));
Serial.println(F(" File name Size"));
Serial.println(FPSTR(line));
fs::File root = SPIFFS.open("/");
if (!root) {
Serial.println(F("Failed to open directory"));
return;
}
if (!root.isDirectory()) {
Serial.println(F("Not a directory"));
return;
}
fs::File file = root.openNextFile();
while (file) {
if (file.isDirectory()) {
Serial.print("DIR : ");
String fileName = file.name();
Serial.print(fileName);
} else {
String fileName = file.name();
Serial.print(" " + fileName);
// File path can be 31 characters maximum in SPIFFS
int spaces = 33 - fileName.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
String fileSize = (String) file.size();
spaces = 10 - fileSize.length(); // Tabulate nicely
if (spaces < 1) spaces = 1;
while (spaces--) Serial.print(" ");
Serial.println(fileSize + " bytes");
}
file = root.openNextFile();
}
Serial.println(FPSTR(line));
Serial.println();
delay(1000);
}
#endif

View File

@@ -0,0 +1,78 @@
//https://github.com/Bodmer/TJpg_Decoder
// Fetch a file from the URL given and save it in SPIFFS
// Return 1 if a web fetch was needed or 0 if file already exists
bool getFile(String url, String filename) {
// If it exists then no need to fetch it
// if (SPIFFS.exists(filename) == true) {
// Serial.println("Found " + filename);
// return 0;
// }
Serial.println("Downloading " + filename + " from " + url);
// Check WiFi connection
if ((WiFi.status() == WL_CONNECTED)) {
HTTPClient http;
Serial.print("[HTTP] begin...\n");
// Configure server and url
http.begin(url);
Serial.print("[HTTP] GET...\n");
// Start connection and send HTTP header
int httpCode = http.GET();
if (httpCode > 0) {
fs::File f = SPIFFS.open(filename, "w+");
if (!f) {
Serial.println("file open failed");
return 0;
}
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
// File found at server
if (httpCode == HTTP_CODE_OK) {
// Get length of document (is -1 when Server sends no Content-Length header)
int total = http.getSize();
int len = total;
// Create buffer for read
uint8_t buff[128] = { 0 };
// Get tcp stream
WiFiClient * stream = http.getStreamPtr();
// Read all data from server
while (http.connected() && (len > 0 || len == -1)) {
// Get available data size
size_t size = stream->available();
if (size) {
// Read up to 128 bytes
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
// Write it to file
f.write(buff, c);
// Calculate remaining bytes
if (len > 0) {
len -= c;
}
}
yield();
}
Serial.println();
Serial.print("[HTTP] connection closed or file end.\n");
}
f.close();
}
else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
return 1; // File was fetched from web
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB