Tenki yoho LED kit2

Dependencies:   mbed

main.cpp

Committer:
kohacraft
Date:
2019-06-08
Revision:
3:40e16b6da0ea
Parent:
2:4ae4d4564c44

File content as of revision 3:40e16b6da0ea:

#include "mbed.h"
#include <string.h>

Serial wifi(dp16, dp15); // ESP-WROOM-02 tx, rx 
DigitalOut wifiRst(dp17); // /ESP-WROOM-02 RESET

DigitalOut sunny(dp1);    //dp1を晴れのLEDにつなぎます
DigitalOut cloudy(dp2);  //dp2を曇りのLEDにつなぎます
DigitalOut rainy(dp4);  //dp4を雨のLEDにつなぎます
DigitalOut snowy(dp6);  //dp6を雪のLEDににつなぎます

#define baudrate 115200

static char rxbuff[1000];   //ネットから取得するデータの格納場所
int buffAdr = 0;
const char SSID[] = "your SSDI";  //アクセスポイントのSSID
const char PASS[] = "password";    //アクセスポイントのパスワード
const char ZIP[] = "100-0000"; //天気予報を調べる郵便番号(半角XXX-XXXX形式)
const char CITY[] = "";         //天気予報を調べる地名(郵便番号か地名どちらかを設定すればOK)
const char APIKEY[] = "apiKey";  //OpenWeatherMapのAPI Key

//データを受信する(1秒くらいは受信する)
bool recvData(int throwDataSize)
{
    bool ret = false;
    buffAdr = 0;
    rxbuff[0] = '\0';
        
    int headerCount = 0;
     
    //700000回ループしたらタイムアウトする(約1秒)
    for( int i = 0; i < 700000 ; i++ )
    {
        if( wifi.readable() != 0 )
        {
            rxbuff[buffAdr++] = wifi.getc(); //Serial.getc()
            headerCount++;
            if( headerCount <= throwDataSize )   //最初のthrowDataSize文字捨てる
                buffAdr=0;
            if( buffAdr >= sizeof(rxbuff)-1 )   //バッファ溢れしたら終了
            {
                ret = true;
                i=700000;  //loopを早く終わらすために
                break;
            }

        }
    }
    
    //文字列の最後を終端
    buffAdr = '\0';
    rxbuff[sizeof(rxbuff)-1] = '\0';
    return ret;
} 

//文字列から予報天気を抽出
bool getWeather( char* str , int* weatherCord , float* tempLow , float* tempHi )
{
        //文字列探索
    char *forecast;
    if ( (forecast = strstr(str, "cod\":\"200\"") ) == NULL )
    {
        //取得できず
        weatherCord = 0;
        tempLow = 0;
        tempLow = 0;
        return false;
    }
    
    //最低気温を抽出
    char *lowStart,*lowEnd;
    lowStart = strstr(forecast, "temp_min\":");
    lowStart = strchr( lowStart , ':' );
    lowStart++; //"の次の文字のポインタ
    lowEnd = strchr( lowStart , ',' );
    *lowEnd = '\0';
    *tempLow =  atof( lowStart );    //最低気温を数字に変換
    //wifi.printf("Start:%d End:%d Low Temp is %s\n",lowStart,lowEnd,lowStart);

    //最高気温を抽出
    char *hiStart,*hiEnd;
    hiStart = strstr(lowEnd+1, "temp_max\":");
    hiStart = strchr( hiStart , ':' );
    hiStart++; //"の次の文字のポインタ
    hiEnd = strchr( hiStart , ',' );
    *hiEnd = '\0';
    *tempHi =  atof( hiStart );    //最高気温を数字に変換
    //wifi.printf("Start:%d End:%d Hi Temp is %s\n",hiStart,hiEnd,hiStart);
  
    //天気コードを抽出
    char *codeStart,*codeEnd;
    codeStart = strstr(hiEnd+1, "{\"id\":");
    codeStart = strchr( codeStart , ':' );
    codeStart++; //"の次の文字のポインタ
    codeEnd = strchr( codeStart , ',' );
    *codeEnd = '\0';
    *weatherCord =  atoi( codeStart );    //最高気温を数字に変換
    //wifi.printf("Start:%d End:%d Code is %s\n",codeStart,codeEnd,codeStart);
    
    //天気を抽出
    char *textStart,*textEnd;
    char weatherText[32];
    textStart = strstr(codeEnd+1, "description\":");
    textStart = strchr( textStart+13 , '\"' );
    textStart++; //"の次の文字のポインタ
    textEnd = strchr( textStart , '\"' );
    *textEnd = '\0';
    strncpy( weatherText, textStart , 32);
    //wifi.printf("Start:%d End:%d Code is %s\n",textStart,textEnd,textStart);
    
    return true;
}

//LEDを順番に光らせる
void ledIlluminationWait()
{
    snowy = 0;
    sunny = 1;
    wait(0.5);
    
    sunny = 0;
    cloudy = 1;
    wait(0.5);
    
    cloudy = 0;
    rainy = 1;
    wait(0.5);
    
    rainy = 0;
    snowy = 1;
    wait(0.5);

}


//OKの文字列を受信するまで待つ timeが0なら永久に待つ
//time*1[秒]待つ (time=10は10秒待つ)
bool waitOk(int time)
{
    bool ret = false;
    int addNumber = 1;
    if( time == 0 )
    {
        addNumber = 0;
        time = 1;
    }
    for( int i = 0 ; i<time ; i+=addNumber )
    {
        recvData(0);
        if( strstr(rxbuff, "OK") != NULL )
        {
            ret = true;
            break;
        }
    }
    return ret;
}

int main() {

    //天気情報
    bool sun = 0;
    bool rain = 0;
    bool cloud = 0;
    bool snow = 0;
    
    wifi.baud(baudrate);    //ビットレートを設定

    while(1)
    {
        //無線LANモジュールをリセット
        wifiRst = 0;
        wait_ms(100);
        wifiRst = 1;
        
        //無線LANモジュールが安定するのを待つ
        ledIlluminationWait();
        ledIlluminationWait();
        ledIlluminationWait();
        ledIlluminationWait();
        ledIlluminationWait();
        
        //最初にlanモジュールから出力される文字列を捨てる
        char temp;
        while( wifi.readable() == true )
             temp = wifi.getc();
             temp = temp++;
        
        //ATコマンドで無線LANモジュールをクライアントモードにする
        sunny = 1; cloudy = 1; rainy = 0; snowy = 0; //晴れと曇りが光っぱなしの場合はwifiジュールと通信できていない
        wifi.printf("AT\r\n");    
        waitOk(0);

        wifi.printf("AT+CWMODE=1\r\n");
        waitOk(0);

        //アクセスポイントに接続
        sunny = 0; cloudy = 0; rainy = 1; snowy = 1; //雨と雪が光っぱなしの場合はアクセスポイントにつながらない
        wifi.printf("AT+CWJAP=\"%s\",\"%s\"\r\n",SSID,PASS);
        waitOk(0);

        while(1)
        {
            //LEDを消灯
            sunny = 0; cloudy = 0; rainy = 0; snowy = 0; //全てが消え続ける場合はサーバーにつながらない

            //サーバに接続
            wifi.printf("AT+CIPSTART=\"TCP\",\"api.openweathermap.org\",80\r\n");
           if( waitOk(3600) == false )
                break;  //1時間待っても返事が無ければ最初からやり直し
         
            //サーバに天気データを要求
            char str[250];
            if( sizeof(CITY) <= 1 )
                //郵便番号で天気を検索
                sprintf(str , "GET http://api.openweathermap.org/data/2.5/forecast?&zip=%s,JP&units=metric&cnt=1&appid=%s\r\nHost:api.openweathermap.org\r\nConnection:close\r\n\r\n",ZIP,APIKEY);
            else
                //地名で天気予報を検索
                sprintf(str , "GET http://api.openweathermap.org/data/2.5/forecast?&q=%s,JP&units=metric&cnt=1&appid=%s\r\nHost:api.openweathermap.org\r\nConnection:close\r\n\r\n",CITY,APIKEY);
            
            wifi.printf("AT+CIPSEND=%d\r\n",strlen(str));
            if( waitOk(3600) == false )
                break;  //1時間待っても返事が無ければ最初からやり直し
        
            wifi.printf("%s",str);
            recvData(1); //データの受信(最初の1500文字を捨てる)
            
            //*** デバッグ用 *** バッファの内容を出力
            //wait(1);
            //wifi.printf("%s\r\n",rxbuff);   
        
            //文字列探索
            int weatherCord;
            float tempHi , tempLow;
            if( getWeather( rxbuff , &weatherCord , &tempLow , &tempHi ) == false ) //データの受信
            {
                //予報の文字列がない
                wait(30);
                break;  //30秒待って最初からやり直す
            }
            
            //*** ↓デバッグ用 *** 受信したデータから抽出した天気情報を出力 
            //wifi.printf("weatherCord:%d tempLow:%f tempHi:%f\r\n",weatherCord , tempLow , tempHi);
        
       
            //天気コードから天気をLEDの色に変換する
 
            if( weatherCord < 600 ){ //雨
                sun = 0;
                rain = 1;
                cloud = 0;
                snow = 0;                
            }else if( weatherCord < 700 ){  //雪
                sun = 0;
                rain = 0;
                cloud = 0;
                snow = 1;                
            }else  if( weatherCord < 800 ){ //曇り
                sun = 0;
                rain = 0;
                cloud = 1;
                snow = 0;                
            }else if( weatherCord <= 802 ){ //晴れ
                sun = 1;
                rain = 0;
                cloud = 0;
                snow = 0;                
            }else{  //曇り
                sun = 0;
                rain = 0;
                cloud = 1;
                snow = 0;                
            }
            
            //LEDを点滅させながら30分待つ
            for(int i=0 ; i<30*60 ; i++)
            {
                //LEDを点灯
                sunny = sun;
                rainy = rain;
                cloudy = cloud;
                snowy = snow;
                wait(0.5);
                    
                //LEDを消灯
                sunny = 0;
                rainy = 0;
                cloudy = 0;
                snowy = 0;
                wait(0.5);
            }
        }
    }
}