examples/SFExamples/S60_weather/src/weatherinfo.cpp

00001 /*
00002 Copyright (c) 2002-2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008   list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010   this list of conditions and the following disclaimer in the documentation
00011   and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013   may be used to endorse or promote products derived from this software
00014   without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description:  
00028 */
00029 
00030 
00031 /*===========================================================================
00032      This file contains the active object for collecting the weather info
00033      from the network.
00034 
00035      The sequence of events to collect the temparature is started by the
00036      GetTemperature() method and issueing the host resolve.  When that is complete
00037      RunL() is invoked and the next network call in the sequence and is called and so on
00038      until temperature is retrieved. 
00039 ============================================================================*/
00040 
00041 #include "weatherinfo.h"
00042 
00043 CWeatherInfo* CWeatherInfo::NewL(MWeatherObserver& aObserver)
00044     {    
00045     CWeatherInfo* self = new(ELeave) CWeatherInfo(aObserver);
00046     CActiveScheduler::Add(self);
00047     return self;
00048     }
00049 
00050 // This isn't a UI object, but is performing background network retrieval so
00051 // doesn't need user input priority...or does it?
00052 CWeatherInfo::CWeatherInfo(MWeatherObserver& aObserver) 
00053     : CActive(CActive::EPriorityStandard), iObserver(aObserver)
00054 {}
00055 
00056 
00057 void CWeatherInfo::GetTemperature(const TDesC& aCity)
00058     {
00059 // if we are already in the middle of getting the temperature, then
00060 // return.
00061     if (IsActive())
00062         return;
00063        
00064     iCommState=EInitializing;
00065 
00066     TInt res =iSocketSrv.Connect();
00067     if (res != KErrNone)
00068         {
00069         Cleanup(res);  
00070         return;
00071         }
00072    
00073     iCityCode.Copy(aCity);
00074 /*-------------------------------------------------------------------------------------
00075    Use the RConnection API to start the network connection if not already started.
00076 ------------------------------------------------------------------------------------- */
00077     res = iConnection.Open(iSocketSrv);
00078     if (res != KErrNone)
00079         {
00080         Cleanup(res);
00081         return;
00082         }
00083     res = iConnection.Start();
00084     if (res != KErrNone)
00085         {
00086         Cleanup(res);
00087         return;
00088         }
00089 /*------------------------------------------------------------------------------------
00090     Open the socket.
00091 ------------------------------------------------------------------------------------*/
00092         iSocket.Open(iSocketSrv,KAfInet,KSockStream,KProtocolInetTcp,iConnection);  
00093         if (res != KErrNone)
00094             {
00095             Cleanup(res);         
00096             return;
00097             }
00098       
00099 /* Resolve name, rest handled by RunL() */
00100  
00101         res = iResolver.Open(iSocketSrv, KAfInet, KProtocolInetTcp,iConnection);
00102         if (res != KErrNone)
00103             {
00104             Cleanup(res);  
00105             return;
00106             }
00107         iCommState=EResolvingName;
00108        
00109         _LIT(KWeatherServerName,"rainmaker.wunderground.com");
00110         iResolver.GetByName(KWeatherServerName, iNameEntry, iStatus);
00111         SetActive();       
00112         }
00113 
00114 CWeatherInfo::~CWeatherInfo()
00115     {
00116     // Make sure we're cancelled
00117     Cancel();
00118     }
00119 
00120 void CWeatherInfo::RunL()
00121     {
00122     if (iStatus != KErrNone)
00123         {
00124         Cleanup(iStatus.Int());  
00125         }
00126     else
00127         {
00128         switch(iCommState)
00129             {
00130             case  EResolvingName:
00131                 {
00132                 TInetAddr destAddr;
00133                 destAddr=iNameEntry().iAddr;
00134                 destAddr.SetPort(3000);
00135 
00136                 // Connect to the remote host
00137                 iCommState=EConnecting;
00138                 iSocket.Connect(destAddr,iStatus);
00139                 SetActive();
00140                 break;
00141                 }
00142             case EConnecting:
00143                 {
00144                 _LIT(KCRLF,"\xD\xA");
00145 
00146                 TBuf8<300> getBuff;
00147                 getBuff.Copy(KCRLF);
00148                 getBuff.Append(iCityCode);
00149                 getBuff.Append(KCRLF);
00150                 
00151                 iCommState=ESending;
00152                 iSocket.Send(getBuff,0,iStatus);
00153                 SetActive();
00154                 break;
00155                 }
00156             case ESending:
00157                 {
00158               // Start receiving
00159               
00160                 iCommState=EReceiving;
00161              
00162                 iSocket.RecvOneOrMore(iNetBuff,0,iStatus,iLen);
00163                 SetActive();
00164                 break;             
00165                 }
00166            case EReceiving:
00167                 {
00168 /*------------------------------------------------------------------- 
00169    The rainmaker.wunderground.com line with the temperature starts 
00170    after a line filled with '='s. 
00171 -------------------------------------------------------------------*/
00172                 _LIT8(KFileTok,"=\xA");
00173                 TInt pos = iNetBuff.FindF(KFileTok);
00174                 TBuf<100> temp;
00175                 if (pos != KErrNotFound)
00176                     {
00177                     temp.Copy(iNetBuff.Mid(pos+2,10));
00178                     temp.Trim();
00179                     iObserver.TemperatureReport(iCityCode,temp);  
00180                     Cleanup(KErrNone);
00181                     } 
00182                 else
00183                     {                 
00184                     iSocket.RecvOneOrMore(iNetBuff,0,iStatus,iLen);
00185                     SetActive();
00186                     }
00187                 break;
00188                 }  
00189             default:
00190                 ASSERT(EFalse); //      Should never get here
00191             }            
00192         }
00193     }
00194 
00195 void CWeatherInfo::DoCancel()
00196     {
00197     iSocket.CancelAll();
00198     Cleanup(KErrCancel);
00199     }
00200 
00201 void CWeatherInfo::Cleanup(TInt aError)
00202     {
00203     iSocket.Close();
00204     iResolver.Close();  
00205     iConnection.Close();
00206     iSocketSrv.Close();
00207 
00208     TBuf<50> errStr;
00209     if (aError!=KErrNone)
00210         {
00211         switch (iCommState)
00212             {
00213             case EInitializing:
00214                 {
00215                 _LIT(KErrStr,"Error initializing communications");
00216                 errStr.Copy(KErrStr);
00217                 break;
00218                 }
00219             case EResolvingName:
00220                 {
00221                 _LIT(KErrStr,"Error resolving name");
00222                 errStr.Copy(KErrStr);
00223                 break;
00224                 }
00225             case EConnecting:
00226                 {
00227                 _LIT(KErrStr,"Error connecting to server");
00228                 errStr.Copy(KErrStr);
00229                 break;
00230                 }
00231             case ESending:
00232                 {
00233                 _LIT(KErrStr,"Error sending request");
00234                 errStr.Copy(KErrStr);
00235                 break;
00236                 }   
00237             case EReceiving:
00238                 {
00239                 _LIT(KErrStr,"Error receiving data");
00240                 errStr.Copy(KErrStr);
00241                 break;
00242                 }
00243             default:
00244                 {
00245                 _LIT(KErrStr,"Unknown error");
00246                 errStr.Copy(KErrStr);
00247                 break;
00248                 }
00249             }
00250         iObserver.TemperatureError(errStr,aError);
00251         }
00252     }   
00253 

Generated by  doxygen 1.6.2