私が研究したオプションの多くは、クリエイターの思考の飛行という観点から興味深いものです。それらの多くから、私は隠していないアイデアを得ました。 独自のセンサーから読み取り値をキャプチャし、あらゆる種類のディスプレイやWebページなどのさまざまなインターフェイスを介して視覚化することに加えて、今後しばらく天気予報データを使用することに興味がありました。
ここで、私の意見では、2つの方法があります。 この記事の最初の記事に精通しましたが、インターネットから予測を得る機会が好きでした。 Amperkaの記事からこれに関する基本的な情報を得て、このアイデアをさらに発展させました。記事で提案されているリソースにより、さらに無料でこれを行うことができます。
その結果、私の測候所のバージョンは、天気予報を担当するForecasterクラスを受け取りました。 このクラスは、テストプロジェクトのコンテキストで、一般に紹介したいと思います。
すぐに予約する:
1.私はArduino Mega 2560上に構築された気象ステーションのサーバー部分を持っているので、プロジェクトでメモリ不足を経験することはありません。
2.標準のイーサネットライブラリにいくつかの変更を加える必要がありました。変更はソケットの数とそれらに割り当てられたバッファメモリに影響しました。
元のバージョンには、ソケットあたり2 kBのソケットが4つありましたが、4 kBのソケットを2つ作成しました。 サーバーから天気予報に関する情報を受信すると、情報量が15〜18 kBに達する可能性があるため(3時間の予報を受信する場合)、バッファーメモリを増やす必要がありました。 つまり 2kBのバッファサイズでは、ほとんどが失われました。 4kBバッファーを使用すると、3時間の解像度で2日間の予測を取得することができます。これはまったく悪くありません。 ライブラリへのすべての変更は、クラス自体のコードに直接文書化されます。 ソケットに触れずに別の方法でこの問題を解決する方法を誰かが教えてくれたら、私はうれしいだけです。
時々、3時間の予測を受け取って解析するときに、より少ない数の要素(16ではなく3-6のみ)を処理することが可能ですが、なぜこれが起こっているのかまだわかりません。おそらく、Arduinkaにはバッファからデータを選択する時間がありません。 Forecasterの動作を実証するために、2つのデバイスでテストしたテストプロジェクトをまとめました。
1. Arduino Uno +イーサネットシールド(w5100)
2. iBoard
これらのデバイスにはメモリが不足しているため、いくつかの関連機能をコメントアウトする必要がありました。 クラス内:
int FORECAST::GetForecastDays(FORECAST::_WeatherDay* wdp) // 4 int FORECAST::GetForecast(FORECAST::_WeatherPacket& whr) //
メインループの本体は、これらの関数を呼び出すコードをコメント化します。 それらの作業は、コードの対応するセクションから順番にコメントを付けて削除することで確認できます。 Mega2560にコードを入力すると、コメントの必要性がなくなり、すべてが機能します。 このプロジェクトはIDEバージョン1.6.5の下で行われています。 (1.0.5r2では-問題ありません)。
私も予約をしたいのですが、私はC(C ++)の支持者ではないので、私はよくフォーラムでストリングスなどの操作方法について質問します。 この点で、コードの一部が奇妙に書かれているか、最適に書かれていない可能性があります。要するに、健全な批判を歓迎します。
予測を要求する都市はクラス発表に登録されています:
const char p_request3Hour[] PROGMEM = "GET /data/2.5/forecast?q=Krasnoyarsk&mode=xml&units=metric"; const char p_request4Day[] PROGMEM = "GET /data/2.5/forecast/daily?q=Krasnoyarsk&mode=xml&units=metric&cnt=4"; const char p_requestToDay[] PROGMEM = "GET /data/2.5/weather?q=Krasnoyarsk&mode=xml&units=metric";
天気予報クラスのお知らせ:
FORECAST frc; FORECAST::_WeatherPacket weather; // FORECAST::_WeatherDay wPack1Day; // 4 ( ) FORECAST::_WeatherThreeHour wPack3Hour; // 3 2
初期化:
frc.Init(client, 7); // client - EthernetClient, 7 -
サーバー上の天気リクエスト:
frc.GetForecast(weather) // weather - frc.GetForecast3Hour(&wPack3Hour) //wPack3Hour - 16 3 frc.GetForecastDays(&wPack1Day) //wPack1Day - 4 4
気象データを含む構造の説明
// struct _WeatherPacket { int P; // int T; // int H; // int WS; // (/) char WD[4]; // char Icon[4]; // }; // 4 typedef struct OneDay { time_t Data; // "20141010' int TD; // int TN; // byte H; // int P; // byte WS; // char WD[4]; // byte Cloud; // % int RainVal; // (*100), 0 - , - + char Icon[4]; //Icon } wdPack; // 3 2 typedef struct ThreeHour { time_t Data; // "2014-10-10 21:00' int T; // int TT; // Min Max byte H; // int P; // byte WS; // char WD[4]; // byte Cloud; // % int RainVal; // (*100), 0 - , - + char Icon[4]; //Icon } whPack;
気象データを含む構造は短いため、nRF24を介して簡単に送信できます。 当然、1つの構造には1日または3時間のデータが含まれ、すべてのメロンを完全に送信するには、適切な数の送信セッションが必要になります。 このために、ディスプレイとサーバーモジュール間の交換用の特別なプロトコルを作成しました。 まあ、実際にはソース自体:
predict.h
#ifndef FORECAST_H #define FORECAST_H #include "Arduino.h" #include <Ethernet.h> #include <Time.h> // 4 typedef struct OneDay { time_t Data; // "20141010' int TD; // int TN; // byte H; // int P; // byte WS; // char WD[4]; // byte Cloud; // % int RainVal; // (*100), 0 - , - + char Icon[4]; //Icon } wdPack; // = 23 byte // 3 2 typedef struct ThreeHour { time_t Data; // "2014-10-10 21:00' int T; // int TT; // Min Max byte H; // int P; // byte WS; // char WD[4]; // byte Cloud; // % int RainVal; // (*100), 0 - , - + char Icon[4]; //Icon } whPack; //=23 byte class FORECAST { private : EthernetClient client; void clearStr (char* str); void addChar (char ch, char* str); void SubStrA(int Num,String& source, String& str); void SubStrB(int Num,String& source, String& str); time_t _ConvertDate(char _Data[10]); time_t _ConvertDateTime(char DatTim[16]); char* GetWord(uint8_t numWord); String dataString; boolean tagFlag; boolean dataFlag; int tZone; long tDelay; public : FORECAST(); void Init (EthernetClient& clnt,int timeZone); struct _WeatherPacket { int P; // int T; // int H; // int WS; // char WD[4]; // char Icon[4]; //Icon }; typedef wdPack _WeatherDay[4]; typedef whPack _WeatherThreeHour[16]; int GetForecast(_WeatherPacket& whr); int GetForecastDays(_WeatherDay *wdp); int GetForecast3Hour(_WeatherThreeHour *whp); int iPacket3H; time_t SunRise; time_t SunSet; boolean fDebug; }; #endif
predict.cpp
#include "forecast.h" #include "math.h" #include <string.h> #include <stdlib.h> #include <math.h> #include <Time.h> #include <avr/pgmspace.h> ////////////////////////////////////////////////////////////////////////// // w5100 2 (4 2) // XML 3 15-18 // // 4 ( 1 8, ). ////////////////////////////////////////////////////////////////////////// // w5100.h // MAX_SOCK_NUM 2 // SOCKETS = 2; // SMASK = 0x0FFF; // Tx buffer MASK // RMASK = 0x0FFF; // Rx buffer MASK // SSIZE = 4096; // Max Tx buffer size // RSIZE = 4096; // Max Rx buffer size ////////////////////////////////////////////////////////////////////////// // w5100.cpp // TX_RX_MAX_BUF_SIZE 4096 // writeTMSR(0xAA); // writeRMSR(0xAA); ////////////////////////////////////////////////////////////////////////// // Ethernet.h // MAX_SOCK_NUM 2 ////////////////////////////////////////////////////////////////////////// // Ethernet.cpp // uint8_t EthernetClass::_state[MAX_SOCK_NUM] = { 0, 0 }; // uint16_t EthernetClass::_server_port[MAX_SOCK_NUM] = { 0 , 0 }; ////////////////////////////////////////////////////////////////////////// #include <Ethernet.h> /////////////////////////////////////////////////////////////////////////////////////////////// // PROGMEM , . 504 RAM const char p_FCserver[] PROGMEM = "api.openweathermap.org"; const char p_APIID[] PROGMEM = "&APPID="; // API-, ! const char p_request3Hour[] PROGMEM = "GET /data/2.5/forecast?q=Krasnoyarsk&mode=xml&units=metric"; const char p_request4Day[] PROGMEM = "GET /data/2.5/forecast/daily?q=Krasnoyarsk&mode=xml&units=metric&cnt=4"; const char p_requestToDay[] PROGMEM = "GET /data/2.5/weather?q=Krasnoyarsk&mode=xml&units=metric"; const char p_ConnClose[] PROGMEM = "Connection: close"; const char p_HTTP[] PROGMEM = " HTTP/1.1"; PGM_P const string_table[] PROGMEM = {p_FCserver, p_APIID,p_request3Hour,p_request4Day,p_requestToDay,p_ConnClose,p_HTTP}; char words[80]; /////////////////////////////////////////////////////////////////////////////////////////////// #define MAX_STRING_LEN 100 char tagStr[MAX_STRING_LEN] = ""; char tmpStr[MAX_STRING_LEN] = ""; char endTag[3] = {'<', '/', '\0'}; char inChar; // FORECAST::FORECAST() { fDebug = false; } // EthernetClient, // , .. void FORECAST::Init(EthernetClient& clnt, int timeZone) { client = clnt; tZone = timeZone; tDelay = 1000; } // 3 (2 3 ) int FORECAST::GetForecast3Hour(FORECAST::_WeatherThreeHour *whp) { int p1 = 0,p2 = 0; char TMP[20]; String temp = ""; float T; if (client.connected()) client.stop(); if (client.connect(GetWord(0), 80)) { temp = GetWord(2); //temp += GetWord(1); temp += GetWord(6); //if (fDebug) Serial.println(temp); client.println(temp); client.print("Host: "); client.println(GetWord(0)); client.println(GetWord(5)); client.println(); temp = ""; // , - while (!client.available()) { p1++; delay(50); if ( p1 > tDelay ) { client.stop(); return 0; } } iPacket3H = 0; while (client.available()) { //----------------------------------------------------------- inChar = client.read(); if (inChar == '<') // { addChar(inChar, tmpStr); tagFlag = true; } else if (inChar == '>') // { addChar(inChar, tmpStr); if (tagFlag) // { strncpy(tagStr, tmpStr, strlen(tmpStr)+1); } clearStr(tmpStr); tagFlag = false; } else if (inChar != 10) { if (tagFlag) { addChar(inChar, tmpStr); // Check for </XML> end tag, ignore it if ( tagFlag && strcmp(tmpStr, endTag) == 0 ) { clearStr(tmpStr); tagFlag = false; } } } // - if ((inChar == 10 ) || (inChar == '>')) { dataString = tagStr; if( !strncmp(tagStr,"<time from",10)) { //<time from="2014-11-26T03:00:00" to="2014-11-26T06:00:00"> //if (fDebug) Serial.println(tagStr); p1 = dataString.indexOf('"',1); p1++; p2 = dataString.indexOf('"',p1); temp = dataString.substring(p1,p2-3); temp.replace("T"," "); temp.toCharArray(TMP,temp.length()+1); (*whp)[iPacket3H].Data = _ConvertDateTime(TMP); } else if( !strncmp(tagStr,"<symbol",7)) { // <symbol number="600" name="light snow" var="13d"/> p1 = dataString.indexOf("var"); SubStrA(p1,dataString,temp); temp.toCharArray((*whp)[iPacket3H].Icon,temp.length()+1); } else if( !strncmp(tagStr,"<precipitation",14)) { // <precipitation unit="3h" value="0.125" type="rain"> //if (fDebug) Serial.println(tagStr); int sign; clearStr(TMP); if (dataString.indexOf("rain") > 0) sign = 1; // else if (dataString.indexOf("snow") > 0 || dataString.indexOf("show") > 0) sign = -1; // //29.09.2015 - snow show else sign = 0; // p1 = dataString.indexOf("value"); if (sign != 0) { SubStrA(p1,dataString,temp); temp.toCharArray(TMP,temp.length()+1); (*whp)[iPacket3H].RainVal = atof(TMP) * sign * 100; } else (*whp)[iPacket3H].RainVal = 0; } else if( !strncmp(tagStr,"<windDirection",14)) { //<windDirection deg="235" code="SW" name="Southwest"/> p1 = dataString.indexOf("code"); SubStrA(p1,dataString,temp); temp.toCharArray((*whp)[iPacket3H].WD,temp.length()+1); } else if( !strncmp(tagStr,"<windSpeed",10)) { //<windSpeed mps="4.62" name="Gentle Breeze"/> clearStr(TMP); SubStrA(1,dataString,temp); temp.toCharArray(TMP,temp.length()+1); T = atof(TMP); (*whp)[iPacket3H].WS = round(T); } else if( !strncmp(tagStr,"<temperature",12)) { //<temperature unit="celsius" value="-12.92" min="-17.91" max="-12.92"/> clearStr(TMP); p1 = dataString.indexOf("value"); SubStrA(p1,dataString,temp); temp.toCharArray(TMP,temp.length()+1); T = atof(TMP); (*whp)[iPacket3H].T = round(T); if (T < 0) p1 = dataString.indexOf("min"); else p1 = dataString.indexOf("max"); clearStr(TMP); SubStrA(p1,dataString,temp); temp.toCharArray(TMP,temp.length()+1); T = atof(TMP); (*whp)[iPacket3H].TT = round(T); } else if( !strncmp(tagStr,"<pressure",9)) { //<pressure unit="hPa" value="999.14"/> p1 = dataString.indexOf("value"); SubStrA(p1,dataString,temp); (*whp)[iPacket3H].P = temp.toInt(); (*whp)[iPacket3H].P =((*whp)[iPacket3H].P * 0.75); // - 17 } else if( !strncmp(tagStr,"<humidity",9)) { //<humidity value="73" unit="%"/> SubStrA(1,dataString,temp); (*whp)[iPacket3H].H = temp.toInt(); } else if( !strncmp(tagStr,"<clouds",7)) { // <clouds value="broken clouds" all="56" unit="%"/> p1 = dataString.indexOf("all"); SubStrA(p1,dataString,temp); (*whp)[iPacket3H].Cloud = temp.toInt(); iPacket3H++; } clearStr(tmpStr); clearStr(tagStr); tagFlag = false; } //----------------------------------------------------------- if (iPacket3H==16) {break;} } client.stop(); return 1; } else {return 0;} } /////////////////////////////////////////////// 4 /////////////////////////////////////////////////////// /* int FORECAST::GetForecastDays(FORECAST::_WeatherDay* wdp) { int iPack=0,p=0; char TMP[20]; String temp; float T; if (client.connected()) client.stop(); if (client.connect(GetWord(0), 80)) { temp = GetWord(3); //temp += GetWord(1); temp += GetWord(6); if (fDebug) Serial.println(temp); client.println(temp); client.print("Host: "); client.println(GetWord(0)); client.println(GetWord(5)); client.println(); temp = ""; while (!client.available()) { p++; delay(50); if ( p > tDelay ) { client.stop(); return 0; } } while (client.available()) { inChar = client.read(); if (inChar == '<') // { addChar(inChar, tmpStr); tagFlag = true; } else if (inChar == '>') // { addChar(inChar, tmpStr); if (tagFlag) // { strncpy(tagStr, tmpStr, strlen(tmpStr)+1); } clearStr(tmpStr); tagFlag = false; } else if (inChar != 10) { if (tagFlag) { addChar(inChar, tmpStr); // Check for </XML> end tag, ignore it if ( tagFlag && strcmp(tmpStr, endTag) == 0 ) { clearStr(tmpStr); tagFlag = false; } } } // - if ((inChar == 10 ) || (inChar == '>')) { dataString = tagStr; if( !strncmp(tagStr,"<time day",9)) { //<time day="2014-10-09"> SubStrA(1,dataString,temp); //temp.toCharArray((*wdp)[iPack].Data,temp.length()+1); temp.toCharArray(TMP,temp.length()+1); (*wdp)[iPack].Data = _ConvertDate(TMP); //if (fDebug) Serial.println(temp); } else if( !strncmp(tagStr,"<symbol",7)) { // <symbol number="600" name="light snow" var="13d"/> p = dataString.indexOf("var"); SubStrA(p,dataString,temp); temp.toCharArray((*wdp)[iPack].Icon,temp.length()+1); } else if( !strncmp(tagStr,"<precipitation",14)) { // <precipitation value="1.25" type="snow"/> int sign; clearStr(TMP); if (dataString.indexOf("rain") > 0) sign = 1; // else if (dataString.indexOf("snow") > 0 || dataString.indexOf("show") > 0) sign = -1; // else sign = 0; // if (sign != 0) { p=1; SubStrA(p,dataString,temp); temp.toCharArray(TMP,temp.length()+1); (*wdp)[iPack].RainVal = atof(TMP) * sign * 100; } else (*wdp)[iPack].RainVal = 0; } else if( !strncmp(tagStr,"<windDirection",14)) { //<windDirection deg="235" code="SW" name="Southwest"/> p = dataString.indexOf("code"); SubStrA(p,dataString,temp); temp.toCharArray((*wdp)[iPack].WD,temp.length()+1); } else if( !strncmp(tagStr,"<windSpeed",10)) { //<windSpeed mps="4.62" name="Gentle Breeze"/> clearStr(TMP); SubStrA(1,dataString,temp); temp.toCharArray(TMP,temp.length()+1); T = atof(TMP); (*wdp)[iPack].WS = round(T); } else if( !strncmp(tagStr,"<temperature",12)) { //<temperature day="4.48" min="-1.12" max="4.48" night="-0.94" eve="-1.12" morn="2.26"/> clearStr(TMP); SubStrA(1,dataString,temp); temp.toCharArray(TMP,temp.length()+1); T = atof(TMP); (*wdp)[iPack].TD = round(T); clearStr(TMP); p = dataString.indexOf("night"); SubStrA(p,dataString,temp); temp.toCharArray(TMP,temp.length()+1); T = atof(TMP); (*wdp)[iPack].TN = round(T); } else if( !strncmp(tagStr,"<pressure",9)) { //<pressure unit="hPa" value="999.14"/> p = dataString.indexOf("value"); SubStrA(p,dataString,temp); (*wdp)[iPack].P = temp.toInt(); (*wdp)[iPack].P =((*wdp)[iPack].P * 0.75 - 17); } else if( !strncmp(tagStr,"<humidity",9)) { //<humidity value="73" unit="%"/> SubStrA(1,dataString,temp); (*wdp)[iPack].H = temp.toInt(); } else if( !strncmp(tagStr,"<clouds",7)) { // <clouds value="broken clouds" all="56" unit="%"/> p = dataString.indexOf("all"); SubStrA(p,dataString,temp); (*wdp)[iPack].Cloud = temp.toInt(); iPack++; } clearStr(tmpStr); clearStr(tagStr); tagFlag = false; } } // client.stop(); return 1; } else {return 0;} } */ ///////////////////////////// ////////////////////////////////////////////////////////////// /* int FORECAST::GetForecast(FORECAST::_WeatherPacket& whr) { int p1 = 0; char TMP[20]; String temp = ""; float T; int step = 0; if (client.connected()) client.stop(); if (client.connect(GetWord(0), 80)) { temp = GetWord(4); //temp += GetWord(1); temp += GetWord(6); if (fDebug) Serial.println(temp); client.println(temp); client.print("Host: "); client.println(GetWord(0)); client.println(GetWord(5)); client.println(); temp = ""; while (!client.available()) // { p1++; delay(50); if ( p1 > tDelay ) // - { client.stop(); return 0; } } while (client.available()) // - { // Read a char inChar = client.read(); //if (fDebug) Serial.print(inChar); if (inChar == '<') { addChar(inChar, tmpStr); tagFlag = true; } else if (inChar == '>') { addChar(inChar, tmpStr); if (tagFlag) { strncpy(tagStr, tmpStr, strlen(tmpStr)+1); } clearStr(tmpStr); tagFlag = false; dataFlag = true; } else if (inChar != 10) { if (tagFlag) { addChar(inChar, tmpStr); // Check for </XML> end tag, ignore it if ( tagFlag && strcmp(tmpStr, endTag) == 0 ) { clearStr(tmpStr); tagFlag = false; dataFlag = false; } } } // If a LF, process the line if ((inChar == 10 ) || (inChar == '>')) { dataString = tagStr; if( !strncmp(tagStr,"<sun",4)) { // <sun rise="2014-10-14T00:18:33" set="2014-10-14T10:51:01"/> SubStrA(1,dataString,temp); temp.replace("T"," "); temp.toCharArray(TMP,temp.length()+1); if (fDebug) {Serial.print("SunRise_w_");Serial.println(TMP);} SunRise = _ConvertDateTime(TMP); p1 = dataString.indexOf("set"); p1++; SubStrA(p1,dataString,temp); temp.replace("T"," "); temp.toCharArray(TMP,temp.length()+1); SunSet = _ConvertDateTime(TMP); step++; } else if( !strncmp(tagStr,"<temperature",12)) { //<temperature value="-9.86" min="-16" max="-6.3" unit="celsius"/> clearStr(TMP); SubStrA(1,dataString,temp); temp.toCharArray(TMP,temp.length()+1); T = atof(TMP); whr.T = round(T); step++; if (fDebug) Serial.println(tagStr); } else if( !strncmp(tagStr,"<humidity",9)) { //<humidity value="65" unit="%"/> SubStrA(1,dataString,temp); whr.H = temp.toInt(); step++; } else if( !strncmp(tagStr,"<pressure",9) ) { //<pressure value="1027" unit="hPa"/> SubStrA(1,dataString,temp); // whr.P = round(temp.toInt() * 0.75 - 17); whr.P = temp.toInt() ; step++; if (fDebug) Serial.println(tagStr); } else if( !strncmp(tagStr,"<speed",6) ) { //<speed value="1.51" name=""/> clearStr(TMP); SubStrA(1,dataString,temp); temp.toCharArray(TMP,temp.length()+1); T = atof(TMP); whr.WS = round(T); step++; if (fDebug) Serial.println(tagStr); } else if( !strncmp(tagStr,"<direction",10) ) { //<direction value="160.501" code="SSE" name="South-southeast"/> p1 = dataString.indexOf("code"); SubStrB(p1,dataString,temp); temp.toCharArray(whr.WD,temp.length()+1); step++; if (fDebug) Serial.println(tagStr); } else if( !strncmp(tagStr,"<weather",8) ) { //<weather number="803" value="broken clouds" icon="04d"/> p1 = dataString.indexOf("icon"); SubStrA(p1,dataString,temp); temp.toCharArray(whr.Icon,temp.length()+1); step++; if (fDebug) {Serial.println(tagStr);Serial.println("-------------------");} } clearStr(tmpStr); clearStr(tagStr); tagFlag = false; dataFlag = false; } } // client.stop(); if (step > 5) return 1; else return 0; } else {return 0;} } */ //////////////////// //////////////////////////////////////////////////// void FORECAST::SubStrA(int Num,String& source, String& str) { int p1 = source.indexOf('"',Num); p1++; int p2 = source.indexOf('"',p1); str = source.substring(p1,p2); } // void FORECAST::SubStrB(int Num,String& source, String& str) { int p1 = source.indexOf('"',Num); p1++; int p2 = source.indexOf('"',p1+1); if (p2 - p1 < 1) str = "WNW"; else str = source.substring(p1,p2); } //Function to add a char to a string and check its length void FORECAST::addChar(char ch, char* str) { char const *tagMsg = "!=!"; if (strlen(str) > MAX_STRING_LEN - 2) { if (tagFlag) { clearStr(tagStr); strcpy(tagStr,tagMsg); } // Clear the temp buffer and flags to stop current processing clearStr(tmpStr); tagFlag = false; } else { // Add char to string str[strlen(str)] = ch; } } // Function to clear a string void FORECAST::clearStr(char* str) { int len = strlen(str); for (int c = 0; c < len; c++) { str[c] = 0; } } time_t FORECAST::_ConvertDate(char _Data[11]) { int Y, M, D; TimeElements te; sscanf ( _Data,"%i-%d-%d", &Y, &M, &D); te.Year = Y -1900; te.Month = M; te.Day = D; te.Hour=0; te.Minute=0; te.Second=0; return makeTime(te); } time_t FORECAST::_ConvertDateTime(char _DateTime[17]) { int Y, M, D, hh, mm; TimeElements te; // ( ) sscanf ( _DateTime,"%i-%d-%d %d:%d", &Y, &M, &D, &hh, &mm ); // TimeZone hh = hh + tZone; if (hh > 24) { hh = hh - 24; if ( (M == 2 && D == 28 && Y%4 != 0)|| (M == 2 && D == 29 && Y%4 == 0) || ((M == 1 || M == 3 || M == 5 || M == 7 || M == 8 || M == 10 || M == 12) && D == 31) || ((M == 4 || M == 6 || M == 9 || M == 11) && D == 30) ) { M++; D = 1; if (M==13) {M=1;Y++;} } else D++; } te.Year = Y -1900; te.Month = M; te.Day = D; te.Hour = hh; te.Minute = mm; te.Second=0; return makeTime(te); } // flash - № char* FORECAST::GetWord(uint8_t numWord) { strcpy_P(words, (PGM_P)pgm_read_word(&(string_table[numWord]))); return words; }
Forecast.ino
#include <Time.h> #include <SPI.h> #include <Ethernet.h> #include "forecast.h" /////////////////////////////////////////////////// byte mac[] = { 0xEA, 0xCD, 0xCE, 0x17, 0x19, 0x66 }; char server[] = "192.168.1.120"; // EthernetClient client; ////////////////////////////////////////////////// // FORECAST frc; FORECAST::_WeatherPacket weather; // FORECAST::_WeatherDay wPack1Day; // 4 ( ) FORECAST::_WeatherThreeHour wPack3Hour; // 3 2 // 4 const unsigned long dInterval = 300000; unsigned long last_dForecast; // 3 const unsigned long hInterval = 300000; // unsigned long last_hForecast; // const unsigned long wInterval = 200000; //~30 . unsigned long last_wForecast; ////////////////////////////////////// #define DEBUG_MODE 1 ////////////////////////////////////// void setup() { frc.fDebug = false; if (Ethernet.begin(mac) == 0) { while (1) { delay(1000); } } // unsigned long now = millis(); frc.Init(client, 7); last_wForecast = now - wInterval + 2000; last_hForecast = now - hInterval + 15000; last_dForecast = now - dInterval + 25000; } void loop() { unsigned long now = millis(); /* if ( now - last_wForecast > wInterval ) { if (frc.GetForecast(weather) == 1) // { last_wForecast = now; } } */ if ( now - last_hForecast > hInterval) { if (frc.GetForecast3Hour(&wPack3Hour) == 1) // 2 3 { if ( frc.iPacket3H > 2 ) // , 2 last_hForecast = millis(); else last_hForecast = millis() - hInterval + 30000; PrintForecast3H(); } } /* if ( now - last_dForecast > dInterval) { if (frc.GetForecastDays(&wPack1Day) == 1) // 4 { last_dForecast = millis(); PrintForecastDay(); } } */ } void ConvertDT(time_t tt, char dt[17]) { TimeElements t_e; int Y, M, D, hh, mm; breakTime(tt, t_e); Y = t_e.Year + 1900; M = t_e.Month; D = t_e.Day; hh = t_e.Hour; mm = t_e.Minute; sprintf(dt, "%i.%i.%i %i:%i", D, M, Y, hh, mm); } void PrintForecast3H() { char DT[17]; for (int i = 0; i < frc.iPacket3H; i++) { ConvertDT(wPack3Hour[i].Data, DT); Serial.print("Data= "); Serial.print(DT); Serial.print("; "); Serial.print(wPack3Hour[i].RainVal / 100.0); Serial.print("; "); Serial.print(wPack3Hour[i].WS); Serial.print("; "); Serial.print(wPack3Hour[i].WD); Serial.print("; "); Serial.print(wPack3Hour[i].T); Serial.print("; "); Serial.print(wPack3Hour[i].TT); Serial.print("; "); Serial.print(wPack3Hour[i].H); Serial.print("; "); Serial.print(wPack3Hour[i].P); Serial.print("; "); Serial.println(wPack3Hour[i].Icon); } } /* void ConvertD(time_t tt, char dd[11]) { TimeElements t_e; int Y, M, D; breakTime(tt, t_e); Y = t_e.Year + 1900; M = t_e.Month; D = t_e.Day; sprintf(dd, "%i.%i.%i", D, M, Y); } void PrintForecastDay() { char D[11]; for (int i = 0; i < 4; i++) { ConvertD(wPack1Day[i].Data, D); Serial.print("Data= "); Serial.print(D); Serial.print("; "); Serial.print(wPack1Day[i].RainVal / 100.0); Serial.print("; "); Serial.print(wPack1Day[i].WS); Serial.print("; "); Serial.print(wPack1Day[i].WD); Serial.print("; "); Serial.print(wPack1Day[i].TD); Serial.print("; "); Serial.print(wPack1Day[i].TN); Serial.print("; "); Serial.print(wPack1Day[i].P); Serial.print("; "); Serial.print(wPack1Day[i].H); Serial.print("; "); Serial.print(wPack1Day[i].Cloud); Serial.print("; "); Serial.println(wPack1Day[i].Icon); } } */