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

週間天気予報 その2


livedoorの Weather HacksのRSSフィードのページから地域を選ぶと、その地域の週間天気予報のRSSが表示されます。

東京の場合 http://weather.livedoor.com/forecast/rss/area/130010.xml
大阪の場合 http://weather.livedoor.com/forecast/rss/area/270000.xml
名古屋の場合 http://weather.livedoor.com/forecast/rss/area/230010.xml

RSSを見ると<title>〜</title>、または<description>〜< /description>を抜き出して表示すればいいことが分かります。
そこで、<description>〜</description>だけを抜き出してみます。
/*
 *  Simple HTTP get webclient test
 */
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <SPI.h>

#define TAGMAX 10
#define LENMAX 128

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

HTTPClient http;

struct TAG {
  uint8_t StartName;
  uint8_t StartValue;
  uint8_t TagPos;
  unsigned char TagName[LENMAX];
  unsigned char TagCurrent[LENMAX];
  uint8_t ValueCount;
  unsigned char TagValue[TAGMAX][LENMAX];
};

struct TAG description;

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 initTag(struct TAG* hoge,char* name) {
   hoge->StartName=0;
   hoge->StartValue=0;
   hoge->TagPos=0;
   strcpy((char *)hoge->TagName,name);
   memset(hoge->TagCurrent,0,sizeof(hoge->TagCurrent));
   hoge->ValueCount=0;
   memset(hoge->TagValue,0,sizeof(hoge->TagValue));
}

void addTagCurrent(struct TAG* hoge, char ch) {
   int pos;
   pos=hoge->TagPos;
   if (pos == LENMAX-1) return;
   hoge->TagCurrent[pos]=ch;
   hoge->TagCurrent[++pos]=0;
   (hoge->TagPos)++;
}

void startTag(struct TAG* hoge) {
   hoge->StartName=1;
   hoge->TagPos=0;
   if (hoge->StartValue) {
     hoge->StartValue=0;
     (hoge->ValueCount)++;
   }
}

void endTag(struct TAG* hoge) {
   hoge->StartName=0;
   hoge->TagPos=0;
   if (strcmp ((char *)hoge->TagName, (char *)hoge->TagCurrent) == 0) {
     if (hoge->ValueCount == TAGMAX) return;
     hoge->StartValue=1;
   }
}

void addTagValue(struct TAG* hoge, char ch) {
   int pos;
   int count;
   pos=hoge->TagPos;
   count=hoge->ValueCount;
   if (pos == LENMAX-1) return;
   hoge->TagValue[count][pos]=ch;
   hoge->TagValue[count][++pos]=0;
   (hoge->TagPos)++;
}

void dumpTag(struct TAG hoge) {
   int i;
   Serial.printf("\nTagName=%s\n",hoge.TagName);
   Serial.printf("TagCurrent=%s\n",hoge.TagCurrent);
   Serial.printf("ValueCount=%d\n",hoge.ValueCount);
   for(i=0;i<hoge.ValueCount;i++){
   Serial.printf("TagValue[%d]=%s\n",i,hoge.TagValue[i]);
   }
}


void httpParse(int len, uint8_t *buff, struct TAG *hoge) {
   int i;
   char ch;
   for(i=0;i<len;i++) {
     ch=buff[i];
     if (ch == '<') {
       startTag(hoge);
     } else if (ch == '>') {
       endTag(hoge);
     } else {
       if (hoge->StartName) addTagCurrent(hoge,ch);
       if (hoge->StartValue) addTagValue(hoge,ch);
     }
   }
}

void setup() {
  int httpCode;
  delay(1000);Serial.begin(9600);

  // start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Wait for WiFi...");
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  initTag(&description,"description");
  dumpTag(description);

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

  httpCode = http.GET();
  if(httpCode > 0){
    Serial.printf("[HTTP] GET ... code: %d\n",httpCode);
    if(httpCode == HTTP_CODE_OK) {
      Serial.printf("[HTTP] OK\n");
      int len = http.getSize();
      uint8_t buff[128] = {0};
      WiFiClient *stream = http.getStreamPtr();
      while(http.connected() && (len > 0 || len == -1)){
        size_t size = stream->available();
        if(size){
          if(size > sizeof buff) size = sizeof buff;
          int c = stream->readBytes(buff,size);
//          httpPrint(c,buff);
//          delay(1);
          httpParse(c,buff,&description);
        }
      }
      Serial.printf("[HTTP] Disconnected\n");
      dumpTag(description);
    } else {
      Serial.printf("[HTTP] Server response Not OK\n");
    }
  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end();
}

void loop() {
}

このスケッチを実行すると以下のように表示されます。
Arduino-IDEのシリアルコンソールはUTF-8に対応していないので、TeraTermを使いました。
-->Arduino-IDE 1.8.5ではUTF-8に対応していました。



TagValue[0]とTagValue[1]は無視して、それ以降を表示すると以下のようになります。
/*
 *  Simple HTTP get webclient test
 */
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <SPI.h>

#define TAGMAX 10
#define LENMAX 128

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

HTTPClient http;

struct TAG {
  uint8_t StartName;
  uint8_t StartValue;
  uint8_t TagPos;
  unsigned char TagName[LENMAX];
  unsigned char TagCurrent[LENMAX];
  uint8_t ValueCount;
  unsigned char TagValue[TAGMAX][LENMAX];
};

struct TAG description;

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 initTag(struct TAG* hoge,char* name) {
   hoge->StartName=0;
   hoge->StartValue=0;
   hoge->TagPos=0;
   strcpy((char *)hoge->TagName,name);
   memset(hoge->TagCurrent,0,sizeof(hoge->TagCurrent));
   hoge->ValueCount=0;
   memset(hoge->TagValue,0,sizeof(hoge->TagValue));
}

void addTagCurrent(struct TAG* hoge, char ch) {
   int pos;
   pos=hoge->TagPos;
   if (pos == LENMAX-1) return;
   hoge->TagCurrent[pos]=ch;
   hoge->TagCurrent[++pos]=0;
   (hoge->TagPos)++;
}

void startTag(struct TAG* hoge) {
   hoge->StartName=1;
   hoge->TagPos=0;
   if (hoge->StartValue) {
     hoge->StartValue=0;
     (hoge->ValueCount)++;
   }
}

void endTag(struct TAG* hoge) {
   hoge->StartName=0;
   hoge->TagPos=0;
   if (strcmp ((char *)hoge->TagName, (char *)hoge->TagCurrent) == 0) {
     if (hoge->ValueCount == TAGMAX) return;
     hoge->StartValue=1;
   }
}

void addTagValue(struct TAG* hoge, char ch) {
   int pos;
   int count;
   pos=hoge->TagPos;
   count=hoge->ValueCount;
   if (pos == LENMAX-1) return;
   hoge->TagValue[count][pos]=ch;
   hoge->TagValue[count][++pos]=0;
   (hoge->TagPos)++;
}

void dumpTag(struct TAG hoge) {
   int i;
   Serial.printf("\nTagName=%s\n",hoge.TagName);
   Serial.printf("TagCurrent=%s\n",hoge.TagCurrent);
   Serial.printf("ValueCount=%d\n",hoge.ValueCount);
   for(i=0;i<hoge.ValueCount;i++){
   Serial.printf("TagValue[%d]=%s\n",i,hoge.TagValue[i]);
   }
}


void httpParse(int len, uint8_t *buff, struct TAG *hoge) {
   int i;
   char ch;
   for(i=0;i<len;i++) {
     ch=buff[i];
     if (ch == '<') {
       startTag(hoge);
     } else if (ch == '>') {
       endTag(hoge);
     } else {
       if (hoge->StartName) addTagCurrent(hoge,ch);
       if (hoge->StartValue) addTagValue(hoge,ch);
     }
   }
}

void setup() {
  int httpCode;
  delay(1000);Serial.begin(9600);

  // start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Wait for WiFi...");
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  initTag(&description,"description");
  dumpTag(description);

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

  httpCode = http.GET();
  if(httpCode > 0){
    Serial.printf("[HTTP] GET ... code: %d\n",httpCode);
    if(httpCode == HTTP_CODE_OK) {
      Serial.printf("[HTTP] OK\n");
      int len = http.getSize();
      uint8_t buff[128] = {0};
      WiFiClient *stream = http.getStreamPtr();
      while(http.connected() && (len > 0 || len == -1)){
        size_t size = stream->available();
        if(size){
          if(size > sizeof buff) size = sizeof buff;
          int c = stream->readBytes(buff,size);
//          httpPrint(c,buff);
//          delay(1);
          httpParse(c,buff,&description);
        }
      }
      Serial.printf("[HTTP] Disconnected\n");
//      dumpTag(description);
      for(int i=2;i<description.ValueCount;i++) {
        Serial.printf("%s\n",description.TagValue[i]);
      }
    } else {
      Serial.printf("[HTTP] Server response Not OK\n");
    }
  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end();
}

void loop() {
}



あとはこの内容をTFTに表示するだけです。
/*
 *  Simple HTTP get webclient test
 */
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

#include <Adafruit_GFX.h>    // https://github.com/adafruit/Adafruit-GFX-Library
#include <Fontx.h>              // https://github.com/h-nari/Fontx
#include <Humblesoft_GFX.h>     // https://github.com/h-nari/Humblesoft_GFX
#include <Humblesoft_ILI9341.h> // https://github.com/h-nari/Humblesoft_ILI9341

#define TAGMAX 10
#define LENMAX 128

IMPORT_BIN("/fontx/ILGH16XB.FNT", ILH16XB); //16ドット半角ゴシックフォント
IMPORT_BIN("/fontx/ILGZ16XB.FNT", ILZ16XB); //16ドット全角ゴシックフォント
//IMPORT_BIN("/fontx/ILMH16XB.FNT", ILH16XB); //16ドット半角明朝フォント
//IMPORT_BIN("/fontx/ILMZ16XB.FNT", ILZ16XB); //16ドット全角明朝フォント
extern const uint8_t ILH16XB[], ILZ16XB[];

Humblesoft_ILI9341 tft = Humblesoft_ILI9341();
RomFontx fontx(ILH16XB,ILZ16XB);

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

HTTPClient http;

struct TAG {
  uint8_t StartName;
  uint8_t StartValue;
  uint8_t TagPos;
  unsigned char TagName[LENMAX];
  unsigned char TagCurrent[LENMAX];
  uint8_t ValueCount;
  unsigned char TagValue[TAGMAX][LENMAX];
};

struct TAG description;

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 initTag(struct TAG* hoge,char* name) {
   hoge->StartName=0;
   hoge->StartValue=0;
   hoge->TagPos=0;
   strcpy((char *)hoge->TagName,name);
   memset(hoge->TagCurrent,0,sizeof(hoge->TagCurrent));
   hoge->ValueCount=0;
   memset(hoge->TagValue,0,sizeof(hoge->TagValue));
}

void addTagCurrent(struct TAG* hoge, char ch) {
   int pos;
   pos=hoge->TagPos;
   if (pos == LENMAX-1) return;
   hoge->TagCurrent[pos]=ch;
   hoge->TagCurrent[++pos]=0;
   (hoge->TagPos)++;
}

void startTag(struct TAG* hoge) {
   hoge->StartName=1;
   hoge->TagPos=0;
   if (hoge->StartValue) {
     hoge->StartValue=0;
     (hoge->ValueCount)++;
   }
}

void endTag(struct TAG* hoge) {
   hoge->StartName=0;
   hoge->TagPos=0;
   if (strcmp ((char *)hoge->TagName, (char *)hoge->TagCurrent) == 0) {
     if (hoge->ValueCount == TAGMAX) return;
     hoge->StartValue=1;
   }
}

void addTagValue(struct TAG* hoge, char ch) {
   int pos;
   int count;
   pos=hoge->TagPos;
   count=hoge->ValueCount;
   if (pos == LENMAX-1) return;
   hoge->TagValue[count][pos]=ch;
   hoge->TagValue[count][++pos]=0;
   (hoge->TagPos)++;
}

void dumpTag(struct TAG hoge) {
   int i;
   Serial.printf("\nTagName=%s\n",hoge.TagName);
   Serial.printf("TagCurrent=%s\n",hoge.TagCurrent);
   Serial.printf("ValueCount=%d\n",hoge.ValueCount);
   for(i=0;i<hoge.ValueCount;i++){
   Serial.printf("TagValue[%d]=%s\n",i,hoge.TagValue[i]);
   }
}


void httpParse(int len, uint8_t *buff, struct TAG *hoge) {
   int i;
   char ch;
   for(i=0;i<len;i++) {
     ch=buff[i];
     if (ch == '<') {
       startTag(hoge);
     } else if (ch == '>') {
       endTag(hoge);
     } else {
       if (hoge->StartName) addTagCurrent(hoge,ch);
       if (hoge->StartValue) addTagValue(hoge,ch);
     }
   }
}

void setup() {
  int httpCode;
  Serial.begin(9600);
  delay(100);

  // start ttf
  tft.begin();

  // start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Wait for WiFi...");
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
 
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  initTag(&description,"description");
  dumpTag(description);

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

  httpCode = http.GET();
  if(httpCode > 0){
    Serial.printf("[HTTP] GET ... code: %d\n",httpCode);
    if(httpCode == HTTP_CODE_OK) {
      Serial.printf("[HTTP] OK\n");
      int len = http.getSize();
      uint8_t buff[128] = {0};
      WiFiClient *stream = http.getStreamPtr();
      while(http.connected() && (len > 0 || len == -1)){
        size_t size = stream->available();
        if(size){
          if(size > sizeof buff) size = sizeof buff;
          int c = stream->readBytes(buff,size);
//          httpPrint(c,buff);
//          delay(1);
          httpParse(c,buff,&description);
        }
      }
      Serial.printf("[HTTP] Disconnected\n");
      dumpTag(description);

      tft.setCursor(0, 0);
      tft.setFont(&fontx);
      tft.fillScreen("BLACK");
      tft.setTextSize(1);
      tft.setRotation(3);
      for(int i=2;i<description.ValueCount;i++) {
        tft.printf("%s\n",description.TagValue[i]);
        delay(10);
      }

    } else {
      Serial.printf("[HTTP] Server response Not OK\n");
    }
  } else {
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end();
}

void loop() {
}



次回は表示する文字の編集を紹介します。

続く....