Google weather APIから取得したお天気情報をVFDに表示します。

Dependencies:   NetServices mbed spxml

Revision:
0:e89d01416461
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sat Nov 26 12:12:08 2011 +0000
@@ -0,0 +1,411 @@
+//
+// VFD fontx2 weather
+//
+// 2011/11/26 by @kanpapa
+//
+// Special thanks: @gingaxx
+//
+
+#include "mbed.h"
+
+#include "EthernetNetIf.h"
+#include "HTTPClient.h"
+
+#include "spdomparser.hpp"
+#include "spxmlnode.hpp"
+#include "spxmlhandle.hpp"
+
+#include "vfd_gp1059.h"
+/*
+=========================
+FUTABA VFD GP1059A01(I/O)
+-------------------------
+p9     1 (D0)  I/O
+p10    2 (D1)  I/O
+p11    3 (D2)  I/O
+p12    4 (D3)  I/O
+p13    5 (D4)  I/O
+p14    6 (D5)  I/O
+p15    7 (D6)  I/O
+p16    8 (D7)  I/O
+p21    10 (INT) O
+p22    11 (WR)  I
+p23    12 (RD)  I
+p24    13 (CS)  I
+p25    14 (C/D) I
+*/
+
+VFD_GP1059   vfd(p9, p10, p11, p12, p13, p14, p15, p16,    p21, p22, p23, p24, p25);
+
+LocalFileSystem local("local");
+
+// LED Status
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+unsigned char reverse_bit(unsigned char x){
+    const unsigned int bit[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
+    unsigned char y = 0;
+    for (int i = 0; i < 8; i++){
+        if ((bit[i] & x) != 0){
+            y |= bit[7-i];
+        }
+    }
+    return(y);
+}
+
+//
+// FONTX2 test routine
+// original version @gingaxx
+//
+
+//#define  kanji_file    "/local/SHMZN16X.FNT"
+//#define  kanji_file  "/local/k12x10.fnt"
+//#define kanji_file "/local/J2KZN16A.FNT"
+//#define kanji_file "/local/XBGZN16X.TLF"
+#define kanji_file "/local/MGOZN16X.TLF"
+
+int cx = 0;
+int cy = 0;
+//int offsety = 0;
+//bool kstate = false;
+//unsigned char kbuf;
+
+FILE *fp;   // File open buffer
+
+unsigned short  start[92], end[92]; // table
+unsigned char   font[64];           // kanji image read buffer              
+
+char            Identifier[6+1];    // 00-05 "FONTX2"   
+char            FontName[8+1];      // 06-13 Font name    
+unsigned char   XSize;              // 14            
+unsigned char   YSize;              // 15
+unsigned char   CodeType;           // 16 0:ASCII, 1:KANJI   
+unsigned char   Tnum;               // 17 Table entry number
+
+//#define FONT_XBYTE        ((XSize + 7) >> 3)
+//#define FONT_YBYTE        ((YSize + 7) >> 3)
+
+void kanji_init(){ 
+    //move cursor 
+    fp = fopen(kanji_file , "r");
+
+    if(!fp) {
+        printf("File could not be opened!\n");
+        led1 = 1;
+        exit(1);
+    }
+
+    fgets(Identifier,   6+1, fp);    // FONTX2
+    fgets(FontName,     8+1, fp);        
+    fread(&XSize,       1, 1, fp);        
+    fread(&YSize,       1, 1, fp);        
+    fread(&CodeType,    1, 1, fp);  
+    fread(&Tnum,        1, 1, fp);
+
+    printf("Identifier: %s\n\r",Identifier);
+    printf("FontName: %s\n\r",FontName);
+    printf("XSize: %d\n\r",XSize);
+    printf("YSize: %d\n\r",YSize);
+    printf("CodeType: %d\n\r",CodeType);
+    printf("Tnum: %d\n\r",Tnum);
+    
+    // Table read
+    for (int a = 0; a < Tnum; a++){
+        fread(&start[a], 1, 2, fp);
+        fread(&end[a]  , 1, 2, fp);
+        printf("Table No.%d start:%04x end:%04x\n\r",a,start[a],end[a]);
+    }
+}
+
+//Kanji puts  cr = kanji code
+void k_puts(int cr){
+
+    const unsigned char bit_chk[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
+
+    // LF code control
+    if (cr == '\n') {
+        cx = 0;
+        cy++;
+        return;    
+    }
+    
+    // calculate kanji address
+    int c = 0;
+    int adrs = 0;
+    while(cr > start[c]){
+        if (cr > end[c]){
+            adrs += end[c] - start[c] + 1;
+        } else {
+            adrs += cr - start[c];
+        }
+        c++;
+    }
+    c--;
+    printf("cr=%X, table num=%d, adrs=%d \r\n",cr,c,adrs);
+    
+    // Kanji image Read
+    fseek( fp, Tnum * 4 + 18 + 32 * adrs, SEEK_SET );
+    fread( &font, 1, 32, fp);
+    
+    // debug dump
+    //for (int s = 0; s < 32 ; s++){
+    //    printf(" %02x ",font[s]);
+    //}
+    //printf("\r\n"); 
+
+    // kanji put
+    c = 0;
+    unsigned int vfd_address = cx * 8 * 16 + cy * 2;
+    //printf("VFD address: %04x\r\n",vfd_address);
+
+    int n = 0;
+    for (int j = 0; j < 2 ; j++) {
+        for (int x = 0; x < 8; x++) {
+            //printf("set VFD address: %04x\r\n",vfd_address);
+            vfd.set_write_read_address(vfd_address);
+            int m = 0;
+            for (int k = 0; k < 2 ; k++) {
+                unsigned int d = 0;      
+                for (int i = 0; i < 8; i++) {
+                    if (font[m * 2 + j] & bit_chk[x]) {
+                        //printf("BIT on!\r\n");
+                        d = d | 1;
+                    }   
+                    if (i < 7) {
+                        d = d << 1;
+                    }
+                    //printf("i:%d, k:%d, m:%d, font:%02x, bit_chk:%02x, data:%02x\r\n",i,k,m,font[m*2+j],bit_chk[x],d);
+                    m++;
+                }
+                //printf("send_data: %02x\r\n",d);
+                vfd.send_data(d);
+            }
+            vfd_address = vfd_address + 8;
+        }
+        n++;
+    }
+
+    // move cursor 
+    cx++;
+    if (cx >= 15){   //LF control
+        cx = 0;
+        cy++;
+    }
+}
+
+void kanji_end(){
+    fclose(fp);
+}
+
+void display_vfd_space(){
+    k_puts(0x8140);
+}    
+
+void display_vfd (const char * buf){
+    unsigned int kc = 0;
+    while (1) {
+        // "0" - "9"  0x30-0x39 824f-8258
+        // "A" - "Z"  0x41-0x4A 8260-8279
+        // "a" - "z"  0x61-0x7a 8281-829a
+        printf("check buf= %02x ", *buf);
+        if (*buf == 0) break;
+        if (*buf >= '0' && *buf <= '9') {
+            kc = 0x821f + *buf;
+        } else if (*buf >= 'A' && *buf <= 'Z') {
+            kc = 0x821f + *buf;
+        } else if (*buf >= 'a' && *buf <= 'z') {
+            kc = 0x8220 + *buf;
+        } else if (*buf == '%') {
+            kc = 0x8193;
+        } else if (*buf == '/') {
+            kc = 0x815e;
+        } else if (*buf == ':') {
+            kc = 0x8146;
+        } else if (*buf == '\n') {
+            kc = '\n';
+        } else if (*buf >= 0x80) {
+            // kanji
+            kc = *buf * 256 + *(buf + 1);
+            buf++;
+        } else {
+            kc = 0;
+        }
+        buf++;
+        
+        printf("kc: %04x ",kc);       
+        if (kc != 0) {
+            k_puts(kc);
+        }
+    }
+}
+
+const char tokyo[7] = {0x93, 0x8c, 0x8b, 0x9e, 0x93, 0x73, 0x00};
+const char otacity[7] = {0x91, 0xe5, 0x93, 0x63, 0x8b, 0xe6, 0x00};
+const char today_weather[7] = {0x82, 0xcc, 0x93, 0x56, 0x8b, 0x43, 0x00};
+const char kanji_condition[7] = {0x8b, 0x43, 0x89, 0xb7, 0x81, 0x46, 0x00};
+const char kanji_c[3] = {0x81, 0x8e, 0x00};
+
+EthernetNetIf eth;
+HTTPClient http;
+
+HTTPResult result;
+bool completed = false;
+void request_callback(HTTPResult r) {
+    result = r;
+    completed = true;
+}
+
+void blink_LED() {
+    for (int i = 0 ; i < 5 ; i++) {
+        led4 = 1;
+        wait(0.2);
+        led4 = 0;
+        wait(0.2);
+    }
+    return;
+}
+
+void dispCurrent() {
+    display_vfd(tokyo);
+    display_vfd(otacity);
+    display_vfd(today_weather);
+    display_vfd_space();
+    return;
+}
+     
+void parseWeather(SP_XmlElementNode *node) {
+    SP_XmlHandle handle(node);
+    SP_XmlElementNode * condition = handle.getChild( "condition" ).toElement();
+    if (condition) {
+        printf("current condition=%s\n",condition->getAttrValue("data"));
+        display_vfd(condition->getAttrValue("data"));
+        display_vfd_space();
+    } 
+    SP_XmlElementNode * tempc = handle.getChild( "temp_c" ).toElement();
+    if (tempc) {
+        printf("current temp=%sC\n",tempc->getAttrValue("data"));
+        display_vfd(kanji_condition);
+        display_vfd(tempc->getAttrValue("data"));
+        display_vfd(kanji_c);
+        display_vfd_space();
+    }
+    SP_XmlElementNode * humidity = handle.getChild( "humidity" ).toElement();
+    if (humidity) {
+        printf("current humidity=%s\n", humidity->getAttrValue("data"));
+        display_vfd(humidity->getAttrValue("data"));
+        display_vfd_space();
+    }
+    SP_XmlElementNode * wind_condition = handle.getChild( "wind_condition" ).toElement();
+    if (wind_condition) {
+        printf("current wind_condition=%s\n",wind_condition->getAttrValue("data"));
+        display_vfd(wind_condition->getAttrValue("data"));
+    }
+}
+
+int main() {
+    // the eth and HTTP code has be taken directly from the HTTPStream documentation page
+    // see http://mbed.org/cookbook/HTTP-Client-Data-Containers
+
+    // Start Sign
+    blink_LED();
+
+    // init VFD
+    vfd.cls();
+    vfd.set_disp_start_address(0);  // Display address: 000000H
+    vfd.luminance_adjustment(0x0f);    // 100%
+
+    // setup FONTX2
+    kanji_init();
+    printf("kanji_init()\r\n");
+    
+    printf("LAN setup\n");
+    EthernetErr ethErr = eth.setup();
+    if (ethErr) {
+        printf("Error in LAN setup\n");
+        vfd.cls();
+        display_vfd("Error in LAN setup");
+        // Close FONTX2 file    
+        kanji_end();
+        printf("kanji_end()\r\n");
+        return -1;
+    }
+    printf("LAN setup ok\n");
+
+    SP_XmlDomParser parser;
+
+    HTTPStream stream;
+
+    char BigBuf[512 + 1] = {0};
+    stream.readNext((byte*)BigBuf, 512); //Point to buffer for the first read
+
+    while(1){
+        led1 = 1;
+        //HTTPResult r = http.get("http://www.google.com/ig/api?weather=Los+Angeles", &stream, request_callback);
+        HTTPResult r = http.get("http://www.google.com/ig/api?weather=ota,tokyo&hl=ja", &stream, request_callback);
+
+        while (!completed) {
+            Net::poll(); //Polls the Networking stack
+            if (stream.readable()) {
+                BigBuf[stream.readLen()] = 0; //Transform this buffer in a zero-terminated char* string
+            
+                parser.append( BigBuf, strlen(BigBuf)); // stream current buffer data to the XML parser
+            
+                stream.readNext((byte*)BigBuf, 512); //Buffer has been read, now we can put more data in it
+            }
+        }
+        if (result == HTTP_OK) {
+            printf("HTTP Read completely\n");
+        } else {
+            printf("HTTP Error %d\n", result);
+            vfd.cls();
+            display_vfd("HTTP Error");
+            // Close FONTX2 file    
+            kanji_end();
+            printf("kanji_end()\r\n");
+            return -1;
+        }
+
+        SP_XmlHandle rootHandle( parser.getDocument()->getRootElement() );
+        SP_XmlElementNode * child2 = rootHandle.getChild( "weather" )
+                                 .getChild( "current_conditions").toElement();
+        led1 = 0;
+    
+        if ( child2 ) {
+            dispCurrent();
+            parseWeather(child2);
+        }
+
+        if ( NULL != parser.getError() ) {
+            printf( "\n\nerror: %s\n", parser.getError() );
+        }
+
+        // scrool 30 * (10sec + 1sec * 3 + 10sec)
+        led2 = 1;
+        for (int loop = 0; loop < 30 ; loop++) {
+            uint16_t address = 0;
+            vfd.set_disp_start_address(address);
+            wait(10);
+        
+            for (int dot = 0; dot < 3; dot++) {
+                vfd.set_disp_start_address(address);
+                wait(1);
+                address++;
+            }
+            wait(10);
+        }
+        led2 = 0;
+        
+        // END Sign
+        blink_LED();    
+
+        //kanji_end();
+        //printf("kanji_end()\r\n");
+
+        printf("end\n");
+
+        wait(60);
+    }
+}