/******************************************************************************* * File: localtemp.cpp * * Version: 0.3 * * Date: 20080508 * * Author: Gaspar Fernández (helyo@totaki.com) * * * * Copyright (C) 2008 Gaspar Fernández * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * * * ******************************************************************************** * Description: * It is part of a Window Maker dockapp called dwgo. This class reads weather * of a selected location from National Weather Service (http://weather.noaa.gov/) * and parses some information to display it formatted on screen. * I know it parses unnecesary information, but I'm planning to update dwgo * with some improvements that use all this information. * * Change History: * Date (D.M.Y) Author Modification * 08.05.2008 Gaspar Fernández Initial release * 31.10.2010 Gaspar Fernández Bug Corrections * ********************************************************************************/ #include "localtemp.h" #include "MySock.h" #include "dwgo.h" // Theme numbers using namespace std; /************************************************************* * Constructur: localtemp * ************************************************************* * Description: * * Initializes variables * * * * Input: * * char *metar - ICAO name locator (4 chars) * * char location_name - Name of this location * * * * Change History: * * Date Author Modification * * * *************************************************************/ localtemp::localtemp(char *metar, char *location_name) { this->metar=metar; this->location_name=location_name; this->celsius=0; this->fahrenheit=0; this->loaded=false; this->theme=DEFAULT_THEME; } /************************************************************* * Method: set_temp * ************************************************************* * Description: * * Extract temperature information. In Celsius and * * Fahrenheit * * * * Input: * * string tmp_str - Temporary string containing * * temperature in Celsius and Fahrenheit * * * * Change History: * * Date Author Modification * * * *************************************************************/ void localtemp::set_temp(string tmp_str) { char buf[8],buf3[8]; // Format xx F (xx C) sscanf(tmp_str.data(), "%s %s (%s", buf, buf3, buf3); // We don't want to store the middle F this->celsius=atoi(buf3); this->fahrenheit=atoi(buf); } /************************************************************* * Method: set_humidity * ************************************************************* * Description: * * Extract humidity information. * * * * Input: * * string hum - Temporary string containing humidity info. * * * * Change History: * * Date Author Modification * * * *************************************************************/ void localtemp::set_humidity(string hum) { char buf[5]; // Be able to store a 100%\0 // Format (xxx%) sscanf(hum.data(), "%s", buf); this->humidity=atoi(buf); } /************************************************************* * Method: get_ob_info * ************************************************************* * Description: * * Extracts METAR encoded information. We find it in * * the line starting with "ob: ". We parse this information * * and fill in variables. Used for time and sky conditions. * * * * Input: * * Nothing * * * * Change History: * * Date Author Modification * * * *************************************************************/ void localtemp::get_ob_info() // ob: line stores METAR information. This info. is useful to know more exactly sky conditions. { // It stores also temperature, time and other info extracted by the decoded text size_t pos; struct tm *localtm; struct tm *remotetm; remotetm =new struct tm; string timeinfo; try { timeinfo=this->ob.substr(6,this->ob.find(' ',6)-6); // DDHHMM[Z] Day Hour Minute Z (Zulu, Aviation Time Reference) } catch (exception &e) { cout<<"fallo en 1"<tm_mday=atoi(timeinfo.substr(0,2).data()); remotetm->tm_hour=atoi(timeinfo.substr(2,2).data()); remotetm->tm_min=atoi(timeinfo.substr(4,2).data()); } catch (exception &e) { cout<<"fallo en 2"<tm_mon=localtm->tm_mon; remotetm->tm_year=localtm->tm_year; remotetm->tm_sec=0; if (remotetm->tm_mday==1) // Month of the data { if (remotetm->tm_mday!=localtm->tm_mday) remotetm->tm_mon++; if (remotetm->tm_mon==12) // It can't be 12!! { remotetm->tm_mon=0; remotetm->tm_year++; } } info_time=mktime(remotetm); try { this->ob=this->ob.substr(ob.find(' ',6)); // Extract ICAO station name and TIME INFO. // It will prevent some errors. We could find any of these strings in that name. //this->ob=this->ob.substr(this->ob.find(this->metar)+5); this->ob=this->ob.substr(0,this->ob.rfind('/')-2); // The info. we want is located betweet the last pos=this->ob.rfind('/'); // 2 slashes. The las one indicates temperature and dew point if (pos!=string::npos) // The other one, may not exists but sometimes it does. this->ob=this->ob.substr(this->ob.rfind('/')); } catch (exception &e) { cout <<"Fallo en 3"<ob.find("TCU")!=string::npos) mInfo.sky=tcu; else if ((this->ob.find("BKN")!=string::npos) || (this->ob.find("OVC")!=string::npos)) mInfo.sky=brkovc; else if ((this->ob.find("FEW")!=string::npos) || (this->ob.find("SCT")!=string::npos)) mInfo.sky=cloudy; else if ((this->ob.find("CAVOK")!=string::npos) || (this->ob.find("SKC")!=string::npos) || (this->ob.find("CLR")!=string::npos)) mInfo.sky=clear; else mInfo.sky=undef_sky; mInfo.CB=(this->ob.find("CB")!=string::npos); //Rain if ((this->ob.find("DZ")!=string::npos) || (this->ob.find("RA")!=string::npos)) mInfo.rain=rain; else if ((this->ob.find("SN")!=string::npos) || (this->ob.find("SG")!=string::npos)) mInfo.rain=snow; else if ((this->ob.find("GS")!=string::npos) || (this->ob.find("GR")!=string::npos)) mInfo.rain=hail; else mInfo.rain=undef_rain; //Fog if ((this->ob.find("BR")!=string::npos) || (this->ob.find("FG")!=string::npos)) mInfo.fog=fog; else if ((this->ob.find("DU")!=string::npos) || (this->ob.find("DS")!=string::npos)) mInfo.fog=dust; else if ((this->ob.find("FC")!=string::npos) || (this->ob.find("FU")!=string::npos) || (this->ob.find("HZ")!=string::npos) || (this->ob.find("SA")!=string::npos) || (this->ob.find("SS")!=string::npos) || (this->ob.find("VA")!=string::npos)) mInfo.fog=other; else mInfo.fog=undef_fog; // The most important for the display theme is rain, then fog and then sky conditions if (mInfo.rain!=undef_rain) { switch (mInfo.rain) { case rain: theme=RAINY_THEME; break; case snow: theme=SNOWY_THEME; break; case hail: theme=HAIL_THEME; break; default: break; } } else if (mInfo.fog!=undef_fog) { switch (mInfo.fog) { case fog : theme=FOG_THEME; break; case dust : theme=DUST_THEME; break; case other: theme=PARTS_THEME; break; default: break; } } else if (mInfo.sky!=undef_sky) { switch (mInfo.sky) { case clear : theme=CLEAR_THEME; break; case cloudy : theme=CLOUDY_THEME; break; case brkovc : theme=BROKEN_THEME; break; case tcu : theme=TCU_THEME; break; default: break; } } else theme=DEFAULT_THEME; // Nothing significant found. } /************************************************************* * Method: getInfo * ************************************************************* * Description: * * Fetch information and parse the file * * * * Output: * * True if we downloaded it right, false if not. * * * * Change History: * * Date Author Modification * * 20101031 Gaspar Fernández Bug in skt * *************************************************************/ bool localtemp::getInfo() { char *metar_fetch; // Get Metar data URL MySock *skt; HTTP_Request *http; string::size_type pos, pos2; TKey_Value datarl; this->error=0; // No error this->loaded=false; metar_fetch= (char*) malloc(80); string tmp; sprintf(metar_fetch, METAR_URL, this->metar.data()); skt = new MySock(metar_fetch); verbsth(VERB_ASTTO, "Open connection: "); http=skt->GetHTTPData(); delete skt; // We don't need this anymore if (http!=NULL) { if (http->status==200) { time(&get_time); // We got the file at this moment pos=0; verbsth(VERB_ASTTO, "Get Data: "); do { pos2=http->data.find("\n",pos+1); if (pos==0) // Extracts the first line (Name of the Station) { this->long_location=http->data.substr(0, http->data.find("(",0)-1); verbsth(VERB_ASTTO, "Station name: "+this->long_location); } if (pos2!=string::npos) { tmp = http->data.substr(pos,pos2-pos); datarl.key=tmp.substr(0, tmp.find(":")); datarl.value=tmp.substr(tmp.find(":")+1); if (datarl.key=="Temperature") this->set_temp(datarl.value); else if (datarl.key=="Relative Humidity") this->set_humidity(datarl.value); else if (datarl.key=="Sky conditions") this->sky=datarl.value; else if (datarl.key=="ob") this->ob=datarl.value; // Search interesting data pos=pos2+1; } } while (pos2!=string::npos); verbsth(VERB_ASTTO, "Get ob info: "); get_ob_info(); // Get info from the METAR string this->loaded=true; verbsth(VERB_ASTTO, "Close connection: "); } else // { this->error=1; // Not found // Print request // cout<data<