ESP-WROOM-02でTFTに漢字を表示する

週間天気予報 その1


HSES-LCD-24を使えば、Wifi接続とTFTへの表示を簡単に行う事ができます。
そこで、何回かに分けて、 livedoorのWeather HacksのRSSフィードのページから、週間天気予報を抜き出してTFTに表示する方法を紹介します。





ネット上の文字データを取り込む方法はいくつか紹介されています。

@HTTPClientを使わない方法
/*
 * SimpleHTTPclient.ino
 * HTTPClientを使わない
 */
 
#include <ESP8266WiFi.h>
 
const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";
const int httpPort = 80;
const char* httpHost = "weather.livedoor.com";
const char* httpUrl = "/forecast/rss/area/230010.xml";

WiFiClient client;

void httpPrint(int len, char buff) {
  char ch[2];
  ch[1] = 0;
  for(int i=0; i<len; i++) {
    ch[0] = buff;
    if (isAlphaNumeric(ch[0])) {
      Serial.printf("%c",ch[0]);
    } else if (strstr("\"!#$%&'()=-<> ;:/,.@[]+*",ch)) {
      Serial.printf("%c",ch[0]);
    } else if (ch[0] == 0x0a) {
      Serial.printf("\n");
    } else {
//      Serial.printf("0x%02x",ch[0]);
      Serial.printf("*");
    }
  }
}

void setup() {
  Serial.begin(9600);
  delay(500);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  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() {
  int counter=0;
  long psize=0;
 
  Serial.print("connecting to ");
  Serial.println(httpHost);
 
  // Use WiFiClient class to create TCP connections
  if (!client.connect(httpHost, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  client.println(String("GET ") + httpUrl + " HTTP/1.1");
  client.println(String("Host: ") + httpHost);
  client.println("Connection: close");
  client.println();
  delay(100);

  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    counter++;
    psize=psize+line.length();
    for(int i=0;i<line.length();i++) {
//      httpPrint(1, (char)line[i]);
//      delay(1);
    }
  }
 
  Serial.printf("counter=%d psize=%d\n\n",counter,psize);
  delay(10000);
}

結果は以下のようになります。
この方法はHTTPヘッダーも取り込むことができます。


AHTTPClient+http.getStringを使う方法
/**
 * BasicHTTPClient.ino
 * HTTPClient+http.getStringを使う
 */

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";

WiFiClient client;
HTTPClient http;

void httpPrint(int len, char buff) {
  char ch[2];
  ch[1] = 0;
  for(int i=0; i<len; i++) {
    ch[0] = buff;
    if (isAlphaNumeric(ch[0])) {
      Serial.printf("%c",ch[0]);
    } else if (strstr("\"!#$%&'()=-<> ;:/,.@[]+*",ch)) {
      Serial.printf("%c",ch[0]);
    } else if (ch[0] == 0x0a) {
      Serial.printf("\n");
    } else {
//      Serial.printf("0x%02x",ch[0]);
      Serial.printf("*");
    }
  }
}

void setup() {
  Serial.begin(9600);
  delay(500);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  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() {
  int counter=0;
  long psize=0;

  Serial.print("[HTTP] begin...\n");
  http.begin("weather.livedoor.com", 80, "/forecast/rss/area/230010.xml");

  Serial.print("[HTTP] GET...\n");
  // start connection and send HTTP header
  int httpCode = http.GET();

  // httpCode will be negative on error
  if(httpCode > 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) {
      String line = http.getString();
      counter++;
      psize=psize+line.length();
      for(int i=0;i<line.length();i++) {
//        httpPrint(1, (char)line[i]);
//        delay(1);
      }
    }
  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end();
  Serial.printf("counter=%d psize=%d\n\n",counter,psize);
  delay(10000);
}

結果は以下のようになります。
この方法はHTTPヘッダーは取り込むことができません。HTTPボデーだけを取り込むことができます。


BHTTPClient+stream->readBytesを使う方法
/**
 * StreamHTTPClient.ino
 * HTTPClient+stream->readBytesを使う
 */

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパスワード";

WiFiClient client;
HTTPClient http;

void httpPrint(int len, uint8_t *buff) {
  char ch[2];
  ch[1] = 0;
  for(int i=0; i<len; i++) {
    ch[0] = buff[i];
    if (isAlphaNumeric(ch[0])) {
      Serial.printf("%c",ch[0]);
    } else if (strstr("\"!#$%&'()=-<> ;:/,.@[]+*",ch)) {
      Serial.printf("%c",ch[0]);
    } else if (ch[0] == 0x0a) {
      Serial.printf("\n");
    } else {
//      Serial.printf("0x%02x",ch[0]);
      Serial.printf("*");
    }
  }
}

void setup() {
  Serial.begin(9600);
  delay(500);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  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() {
  int counter=0;
  long psize=0;

  Serial.print("[HTTP] begin...\n");
  http.begin("weather.livedoor.com", 80, "/forecast/rss/area/230010.xml");

  Serial.print("[HTTP] GET...\n");
  // start connection and send HTTP header
  int httpCode = http.GET();

  // httpCode will be negative on error
  if(httpCode > 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 lenght of document (is -1 when Server sends no Content-Length header)
      int len = http.getSize();

      // 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();
        counter++;
        if(size) {
          // read up to 128 byte
          int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
          psize=psize+c;
//          httpPrint(c,buff);
//          delay(1);
          if(len > 0) {
            len -= c;
          }
        }
      }
      Serial.print("[HTTP] connection closed or file end.\n");
    }
  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end();
  Serial.printf("counter=%d psize=%d\n\n",counter,psize);
  delay(10000);
}


結果は以下の様になります。
この方法はHTTPヘッダーは取り込むことができません。HTTPボデーだけを取り込むことができます。


今回注目したのは、ページを何回に分けて取得できるかです。
@HTTPClientを使わない方法 16回
AHTTPClient+http.getStringを使う方法 1回
BHTTPClient+stream->readBytesを使う方法 200回以上

つまり、Aの方法は1回のhttp.getString()だけで全てのデータを取り込んでしまうので、
データ格納領域として一番多くメモ リ(今回は7449バイト)を使うはずです。
Bの方法は最大128バイトで何回もデータを取り込むので、128バイトしかデータ格納領域を使いません。
次回はBの方法を使ってRSSページから必要な情報を抜き取る方法を紹介します。

続く....