commands/lbs/lbs.cpp
author Tom Sutcliffe <thomas.sutcliffe@accenture.com>
Sat, 31 Jul 2010 19:07:57 +0100
changeset 23 092bcc217d9d
parent 0 7f656887cf89
permissions -rw-r--r--
Tidied iocli exports, build macro tweaks. Removed 4 overloads of CCommandBase::RunCommand[L] that are no longer used at all, and changed one more to not be exported as it's only used internally to iocli.dll. fixed builds on platforms that don't support btrace or any form of tracing.

// lbs.cpp
// 
// Copyright (c) 2008 - 2010 Accenture. All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
// 
// Initial Contributors:
// Accenture - Initial contribution
//

#include <fshell/common.mmh>

#include <lbs.h>
#include <lbssatellite.h>
#include <LbsErrors.h>

#if defined (FSHELL_PLATFORM_S60) || defined (FSHELL_PLATFORM_FOUNDATION)
#include <EPos_CPosModules.h>
#include <EPos_CPosModuleUpdate.h>
#include <EPos_CPosModuleIdList.h> 
#endif

#if !defined (FSHELL_PLATFORM_S60) && !defined (FSHELL_PLATFORM_FOUNDATION)
#include <lbs/lbsadmin.h>
#endif

#include <fshell/ioutils.h>
using namespace IoUtils;

class CCmdLbs : public CCommandBase
	{
public:
	void PrintTime(const TTime& aTime, TBool aNewline);	
	static const TDesC* TechnologyTypeToString(TPositionModuleInfo::TTechnologyType aType);
	static const TDesC* DeviceLocationToString(TPositionModuleInfo::TDeviceLocation aLoc);
	static const TDesC* CostIndicatorToString(TPositionQuality::TCostIndicator aCost);
	static const TDesC* PowerConsumptionToString(TPositionQuality::TPowerConsumption aPower);
	static void CapabilitiesToString(TPositionModuleInfo::TCapabilities aCap, TDes &aDes);
	
	static CCommandBase* NewLC();
	~CCmdLbs();
private:
	CCmdLbs();
	void PrintModuleDetail(TPositionModuleInfo& aModInfo);
	void DoListModuleL();
	void DoListModuleS60L();
	void DoLocation();
	void DoEnableModuleL(TBool aEnable = ETrue);	
#if !defined (FSHELL_PLATFORM_S60)
	void DoSynchTimeL();
#endif

private: // From CCommandBase.
	virtual const TDesC& Name() const;
	virtual void DoRunL();
	virtual void ArgumentsL(RCommandArgumentList& aArguments);
	virtual void OptionsL(RCommandOptionList& aOptions);

private:
	CActiveSchedulerWait* iActiveWait;
	RPositionServer iPosSrv;
	RPositioner iPos;
	TPositionSatelliteInfo iSatelliteInfo;	//NOT all LBS modules accept satellite info
	TPositionInfo iPosInfo;	
	TPositionInfoBase* ipPosInfo;			//point to appropriate structure 
		
	RArray<TBool> iVerbose;
	TInt iOptModuleIndex;		//which module to use (module index, not id) 
	TInt iOptTimeoutSec;		//timeout in second, default is 60 second
	TInt iOptLoops;				//how many loops (default 1)
	
	enum TLbsCmd
		{
		ECmdLocation,		
		ECmdListModule,
		ECmdListModuleS60,
		ECmdEnableModule,
		ECmdDisableModule,
		ECmdSynchTime		//synchronise system time with GPS timestamp
		};
	
		
	TLbsCmd iCommand;
	};

CCommandBase* CCmdLbs::NewLC()
	{
	CCmdLbs* self = new(ELeave) CCmdLbs();
	CleanupStack::PushL(self);
	self->BaseConstructL();
	return self;
	}

CCmdLbs::CCmdLbs()
	{
	iOptModuleIndex = -1;
	iOptTimeoutSec = 300;
	iOptLoops = 1;
	iActiveWait = new (ELeave) CActiveSchedulerWait;	
	}


CCmdLbs::~CCmdLbs()
	{
	iPos.Close();
	iPosSrv.Close();
	
	iVerbose.Close();
	delete iActiveWait;
	}

//////////////////////////////////////////////////////


//////////////////////////////////////////////////////

const TDesC& CCmdLbs::Name() const
	{
	_LIT(KName, "lbs");
	return KName;
	}

void CCmdLbs::ArgumentsL(RCommandArgumentList& aArguments)
	{
	_LIT(KArgCommand, "command");
	aArguments.AppendEnumL((TInt&)iCommand, KArgCommand);
	}

void CCmdLbs::OptionsL(RCommandOptionList& aOptions)
	{
	_LIT(KOptVerbose, "verbose");
	aOptions.AppendBoolL(iVerbose, KOptVerbose);
	
	_LIT(KOptModuleIndex, "module-index");
	aOptions.AppendUintL((TUint&)iOptModuleIndex, KOptModuleIndex);

	_LIT(KOptLoops, "loops");
	aOptions.AppendUintL((TUint&)iOptLoops, KOptLoops);

	_LIT(KOptTimeout, "timeout");
	aOptions.AppendUintL((TUint&)iOptTimeoutSec, KOptTimeout);
	}

void CCmdLbs::DoRunL()
	{
	Printf(_L("Connecting to RPositionServer...\r\n"));
	TInt err = iPosSrv.Connect();
	LeaveIfErr(err, _L("Cannot connect to position server"));
	
	switch(iCommand)
		{
		case ECmdLocation:
			DoLocation();
			break;
		case ECmdListModule:
			DoListModuleL();
			break;
		case ECmdListModuleS60:
			DoListModuleS60L();
			break;
		case ECmdEnableModule:
			DoEnableModuleL(ETrue);
			break;
		case ECmdDisableModule:
			DoEnableModuleL(EFalse);
			break;
		case ECmdSynchTime:
		//TODO There's no way of actually specifying this command
#if !defined (FSHELL_PLATFORM_S60)
			DoSynchTimeL();
#else
			LeaveIfErr(KErrNotSupported, _L("SynchTime not supported on S60"));
#endif
			break;
		}	
		
	}

void CCmdLbs::DoLocation()
	{
	TInt VerboseLevel = iVerbose.Count();		
	TInt err;
	TBool bSatelliteCapable = EFalse;
	TPositionModuleId modId; //which module to use
	if (iOptModuleIndex != -1) 
		{
		TPositionModuleInfo modInfo;
		err = iPosSrv.GetModuleInfoByIndex(iOptModuleIndex, modInfo);
		LeaveIfErr(err, _L("invalid module index"));
		modId = modInfo.ModuleId();						
		}
	else
		{	//use the default module
		err = iPosSrv.GetDefaultModuleId(modId);
		LeaveIfErr(err, _L("Invalid default module"));
		}		
	
	TPositionModuleInfo modInfo;
	err = iPosSrv.GetModuleInfoById(modId, modInfo);
	TBuf<128> modName;
	modInfo.GetModuleName(modName);	
	
	Printf(_L("Openning RPositioner...(Module ID: 0x%X \"%S\")\r\n"), modId.iUid, &modName);
	err = iPos.Open(iPosSrv, modId);
	LeaveIfErr(err, _L("Cannot open positioner"));
	
   // Set position requestor, it is compulsory on S60 only
    err = iPos.SetRequestor( CRequestor::ERequestorService ,
         CRequestor::EFormatApplication , _L("FSHELL FLBS COMMAND") );
	LeaveIfErr(err, _L("Cannot set requestor"));
			
	TPositionUpdateOptions UpdateOption;
	TTimeIntervalMicroSeconds TimeoutMs = (TInt64)iOptTimeoutSec * (TInt64)1000000;
	UpdateOption.SetUpdateTimeOut(TimeoutMs);
	
	Printf(_L("SetUpdateOptions... Timeout = %d seconds\r\n"), iOptTimeoutSec);
	err = iPos.SetUpdateOptions(UpdateOption);
	LeaveIfErr(err, _L("Cannot set update options"));
	
	//check if the module is capable of satellite info
	{
		TPositionModuleInfo::TCapabilities modCap = modInfo.Capabilities();
		bSatelliteCapable = modCap & TPositionModuleInfo::ECapabilitySatellite;
		if (bSatelliteCapable)
			{
			ipPosInfo = &iSatelliteInfo;
			Printf(_L("This module is capable of receiving satellite information\r\n"));
			}
		else
			ipPosInfo = &iPosInfo;			
	}
	
	for (TInt i=0; i<iOptLoops; i++)
		{
		TRequestStatus status;
		TPosition pos;
		Printf(_L("Calling RPositioner::NotifyPositionUpdate...\r\n"));
		iPos.NotifyPositionUpdate(*ipPosInfo, status);
		User::WaitForRequest(status);
		
		err = status.Int();
		if (err != KErrNone)
			LeaveIfErr(err, _L("NotifyPositionUpdate encountered an error"));
				
		static_cast <TPositionInfo*>(ipPosInfo) -> GetPosition(pos);
		TTime LocTime = pos.Time();
		TReal32 HorizontalAccuracy = pos.HorizontalAccuracy();
		TReal32 VerticalAccuracy = pos.VerticalAccuracy();
		//print current location information
		Printf(_L("Altit:%f Latit:%f Longt:%f HAccu:%.2f VAccu:%.2f\r\n"), 
				pos.Altitude(), pos.Latitude(), pos.Longitude(), 
				HorizontalAccuracy, VerticalAccuracy);		
		
		Printf(_L("Location Signal Time:"));
		PrintTime(LocTime, ETrue);
		
		//if there is satellite information, optionally print it out
		if (bSatelliteCapable && (VerboseLevel>0) )
			{
			TPositionSatelliteInfo* pSateInfo = static_cast <TPositionSatelliteInfo*> (ipPosInfo);
			
			TInt NumSatellitesInView = pSateInfo->NumSatellitesInView();
			TInt NumSatellitesUsed = pSateInfo->NumSatellitesUsed();
			TTime SatelliteTime = pSateInfo->SatelliteTime();
			TReal32 HorizontalDoP = pSateInfo->HorizontalDoP();
			TReal32 VerticalDoP = pSateInfo->VerticalDoP();
			TReal32 TimeDoP = pSateInfo->TimeDoP(); 
			Printf(_L("Satellite In View:%d Used:%d Time:"), 
					NumSatellitesInView, NumSatellitesUsed );
			PrintTime(SatelliteTime, ETrue);
			Printf(_L("HoriDop:%f VertDop:%f TimeDop:%f \r\n"), 
					HorizontalDoP, VerticalDoP, TimeDoP);
			
			//Print each satellite info
			for (TInt i=0; i<NumSatellitesInView; i++ )
				{
				TSatelliteData SatellliteData;
				err = pSateInfo->GetSatelliteData((TUint)i, SatellliteData);
				if (err == KErrNotFound)
					{
					Printf(_L("Satellite #%d Not Found\r\n"), i);
					continue;
					}
				else
					{
					User::LeaveIfError(err);
					}
				
				TInt SatelliteId = SatellliteData.SatelliteId(); 
				TReal32 Azimuth = SatellliteData.Azimuth();
				TReal32 Elevation = SatellliteData.Elevation();
				TBool IsUsed = SatellliteData.IsUsed();
				TInt SignalStrength = SatellliteData.SignalStrength();
				
				Printf(_L("Satellite #%d, ID:%d Azimuth %.2f Elevation %.2f IsUsed:%d Strenth:%d\r\n"), 
						i, SatelliteId, Azimuth, Elevation, IsUsed, SignalStrength);
			
				}
			}			
		}	
	}

void CCmdLbs::DoListModuleL()
	{
	TInt err;
	TUint numModules;
	TPositionModuleInfo modInfo;
	
	err = iPosSrv.GetNumModules(numModules);
	User::LeaveIfError(err);

	Printf(_L("%d Modules found\r\n"), 
			numModules);
	
	for (TUint i=0 ; i < numModules ; i++)
		{
		Printf(_L("============================\r\n")); 		
		err = iPosSrv.GetModuleInfoByIndex(i, modInfo);
		User::LeaveIfError(err);
		
		Printf(_L("Module Index: %d\r\n"), i);
		
		PrintModuleDetail(modInfo);
		}
	
	Printf(_L("=================================\r\n"));
	//print default module ID
	TPositionModuleId DefaultId;
	err = iPosSrv.GetDefaultModuleId(DefaultId);		
	Printf(_L("Default Module ID 0x%X\r\n"), DefaultId.iUid );
	}

//S60 proprietary
//similar to DoListModuleL, but list module based on S60 API,
//and sometimes it gives different results than symbain API
void CCmdLbs::DoListModuleS60L()
	{
#ifdef FSHELL_PLATFORM_S60
	//TInt err;
	TUint numModules;
	CPosModules* pModHand = CPosModules::OpenL();
	CleanupStack::PushL(pModHand);
	
	CPosModuleIdList* pIdList = pModHand->ModuleIdListL();
	CleanupStack::PushL(pIdList);
	
	numModules = pIdList->Count();
	Printf(_L("%d Modules found\r\n"), 
			numModules);
	
	for (TUint i=0 ; i < numModules ; i++)
		{
		Printf(_L("============================\r\n"));
		TPositionModuleId S60modId = (*pIdList) [i];
		TPositionModuleInfo S60modInfo;
		TBuf<128> S60modName;			//to store module name
		
		pModHand->GetModuleInfoL(S60modId, S60modInfo);
		S60modInfo.GetModuleName(S60modName);
				
		Printf(_L("Module Index: %d\r\n"), i);
		
		PrintModuleDetail(S60modInfo);
		}

	Printf(_L("=================================\r\n"));		
	
	CleanupStack::PopAndDestroy(pIdList);
	CleanupStack::PopAndDestroy(pModHand);		
#endif
	}

void CCmdLbs::PrintModuleDetail(TPositionModuleInfo& aModInfo)
	{
	//TInt err;
	TBool bAvailable = aModInfo.IsAvailable();
	
	TPositionModuleId modId;
	modId = aModInfo.ModuleId();
	
	TBuf<128> modName;
	aModInfo.GetModuleName(modName);
	
	//==quality
	TPositionQuality modQuality;
	aModInfo.GetPositionQuality(modQuality);
	TTimeIntervalMicroSeconds firstFix = modQuality.TimeToFirstFix();
	TTimeIntervalMicroSeconds nextFix = modQuality.TimeToNextFix();
	TReal32 horiAccu = modQuality.HorizontalAccuracy();
	TReal32 vertAccu = modQuality.VerticalAccuracy();
	TPositionQuality::TCostIndicator cost = modQuality.CostIndicator();
	TPositionQuality::TPowerConsumption power = modQuality.PowerConsumption();
	////////////////////////////////////////////////////////////////
	TPositionModuleInfo::TTechnologyType modType = aModInfo.TechnologyType();		
	TPositionModuleInfo::TDeviceLocation modLoc = aModInfo.DeviceLocation();		
	TPositionModuleInfo::TCapabilities modCap = aModInfo.Capabilities();
	TVersion modVersion = aModInfo.Version();
	TVersionName VersionName = modVersion.Name(); 
	
	//TPositionClassFamily aClassType;
	//modInfo.ClassesSupported(aClassType);
	
	Printf(_L("Module Id:0x%X, Name:\"%S\" Available:%d \r\n"),
			modId.iUid, &modName, bAvailable);
	Printf(_L("Type:%S Version:%S\r\n"), 
			TechnologyTypeToString(modType), &VersionName );
	Printf(_L("Location:%S\r\n"), DeviceLocationToString (modLoc));

	Printf(_L("Quality first fix:%Ld next fix:%Ld \r\n"),
			firstFix.Int64(), nextFix.Int64());
	Printf(_L("Horizontal Accuracy:%f Vertical Accuray:%f \r\n"),
			horiAccu, vertAccu);
	Printf(_L("Cost Indicator:%S\r\n"), CostIndicatorToString(cost));
	Printf(_L("Power Consumption:%S\r\n"), PowerConsumptionToString(power));		
				
	TBuf<256> CapString;
	CapabilitiesToString(modCap, CapString);
	Printf(_L("Capabilities:%S\r\n"), &CapString);	
	}
	
//it is a S60 proprietary function
//
void CCmdLbs::DoEnableModuleL(TBool aEnable)
	{
	TInt err;
	TBuf<128> modName;			//to store module name
	TPositionModuleInfo modInfo;
	TPositionModuleId modId = TUid::Null(); //which module to use
	TBool bIsCurAvail;
	
	if (iOptModuleIndex != -1) 
		{
		err = iPosSrv.GetModuleInfoByIndex(iOptModuleIndex, modInfo);
		LeaveIfErr(err, _L("invalid module index"));
		modId = modInfo.ModuleId();						
		}
	else 
		{
		LeaveIfErr(KErrArgument, _L("Need to specify a module"));
		}
	
	bIsCurAvail = modInfo.IsAvailable();
	modInfo.GetModuleName(modName);
	
	TPtrC AvailNow = (bIsCurAvail)?_L("Yes"):_L("No");
	Printf(_L("Module Id=0x%08x Name:\"%S\" Current Availability:%S \r\n"), 
			modId.iUid, &modName, &AvailNow);
	
	//modInfo.SetIsAvailable(ETrue);	//Note: this has no effect on S60 platform
	
#ifdef FSHELL_PLATFORM_S60
	CPosModules* pModHand = CPosModules::OpenL();
	CleanupStack::PushL(pModHand);
	
	//diagnosis code: to verify the information given by S60 API matches Symbian API
	{
		CPosModuleIdList* pIdList = pModHand->ModuleIdListL();
		CleanupStack::PushL(pIdList);
		
		TPositionModuleId S60modId = (*pIdList) [iOptModuleIndex];
		TPositionModuleInfo S60modInfo;
		TBuf<128> S60modName;			//to store module name
				
		pModHand->GetModuleInfoL(S60modId, S60modInfo);
		S60modInfo.GetModuleName(S60modName);
		RDebug::Print(_L("S60 LBS module name:%S"), &S60modName);
		
		CleanupStack::PopAndDestroy(pIdList);
	}
	
	
	CPosModuleUpdate* pModUpdate = CPosModuleUpdate::NewLC();	
	TBool bNewAvail = aEnable;
	pModUpdate->SetUpdateAvailability(bNewAvail);	
	TRAP(err, pModHand->UpdateModuleL(modId, *pModUpdate));
	LeaveIfErr(err, _L("Could not update module information") );
		
	CleanupStack::PopAndDestroy(pModUpdate);		
	CleanupStack::PopAndDestroy(pModHand);		
#endif
	
	//verify if the change has take effect
		{
		err = iPosSrv.GetModuleInfoByIndex(iOptModuleIndex, modInfo);
		LeaveIfErr(err, _L("invalid module index"));
		modId = modInfo.ModuleId();						
		bIsCurAvail = modInfo.IsAvailable();
		TPtrC NewAvail = (bIsCurAvail)?_L("Yes"):_L("No");
		Printf(_L("Module Id=0x%08x Name:\"%S\" New Availability:%S \r\n"), 
				modId.iUid, &modName, &NewAvail);		
		}
		
	}
	
#if !defined (FSHELL_PLATFORM_S60)
void CCmdLbs::DoSynchTimeL()
	{
	// Set LBS setting to allow manual clock adjustment
	//This may not be set by default
    CLbsAdmin* admin = CLbsAdmin::NewL();
    CleanupStack::PushL(admin);
    CLbsAdmin::TClockAdjust clockAdjust;   
    User::LeaveIfError(admin->Get(KLbsSettingAllowManualClockAdjust,clockAdjust));
    admin->Set(KLbsSettingAllowManualClockAdjust,CLbsAdmin::EClockAdjustOn);
    CleanupStack::PopAndDestroy(admin);
	}
#endif

EXE_BOILER_PLATE(CCmdLbs)

void CCmdLbs::PrintTime(const TTime& aTime, TBool aNewline)
	{
	
	TTime NullTime = Time::NullTTime();
	if (aTime == NullTime) 
		{
		Printf(_L("(NullTime)"));
		}
	else
		{
		_LIT8(KDateTimeFormat, "%d-%02d-%02d %02d:%02d:%02d");
		TDateTime dt = aTime.DateTime();
		Printf(KDateTimeFormat, dt.Year(), dt.Month()+1, dt.Day()+1, dt.Hour(), dt.Minute(), dt.Second());
		}
	
	if (aNewline) Printf(_L("\r\n"));
	}


#define CASE_LIT(x) case x: { _LIT(KName, #x); return &KName; }

const TDesC* CCmdLbs::TechnologyTypeToString(TPositionModuleInfo::TTechnologyType aType)
	{
	switch(aType)
		{
		CASE_LIT(TPositionModuleInfo::ETechnologyUnknown);
		CASE_LIT(TPositionModuleInfo::ETechnologyTerminal);
		CASE_LIT(TPositionModuleInfo::ETechnologyNetwork);
		CASE_LIT(TPositionModuleInfo::ETechnologyAssisted);
		default:
			{			
			_LIT(KUnknown, "Unknown");
			return &KUnknown;
			}
		}
	}


const TDesC* CCmdLbs::DeviceLocationToString(TPositionModuleInfo::TDeviceLocation aLoc)
	{
	switch(aLoc)
		{
		CASE_LIT(TPositionModuleInfo::EDeviceUnknown);
		CASE_LIT(TPositionModuleInfo::EDeviceInternal);
		CASE_LIT(TPositionModuleInfo::EDeviceExternal);
		default:
			{			
			_LIT(KUnknown, "Unknown");
			return &KUnknown;
			}
		}
	}


const TDesC* CCmdLbs::CostIndicatorToString(TPositionQuality::TCostIndicator aCost)
	{
	switch(aCost)
		{
		CASE_LIT(TPositionQuality::ECostUnknown);
		CASE_LIT(TPositionQuality::ECostZero);
		CASE_LIT(TPositionQuality::ECostPossible);
		CASE_LIT(TPositionQuality::ECostCharge);
		default:
			{			
			_LIT(KUnknown, "Unknown");
			return &KUnknown;
			}
		}
	}

const TDesC* CCmdLbs::PowerConsumptionToString(TPositionQuality::TPowerConsumption aPower)
	{
	switch(aPower)
		{
		CASE_LIT(TPositionQuality::EPowerUnknown);
		CASE_LIT(TPositionQuality::EPowerZero);
		CASE_LIT(TPositionQuality::EPowerLow);
		CASE_LIT(TPositionQuality::EPowerMedium);
		CASE_LIT(TPositionQuality::EPowerHigh);
		default:
			{			
			_LIT(KUnknown, "Unknown");
			return &KUnknown;
			}
		}
	}
#define CAPFLAG(x) if (aCap & TPositionModuleInfo::x) { aDes += _L(#x); aDes += _L("|");}

void CCmdLbs::CapabilitiesToString(TPositionModuleInfo::TCapabilities aCap, TDes &aDes)
	{
	aDes.SetLength(0);
	//if (aCap & TPositionModuleInfo::ECapabilityNone) aDes += _L("ECapabilityNone|");
	CAPFLAG(ECapabilityNone);
	CAPFLAG(ECapabilityHorizontal);
	CAPFLAG(ECapabilityVertical);
	CAPFLAG(ECapabilitySpeed);
	CAPFLAG(ECapabilityDirection);
	CAPFLAG(ECapabilitySatellite);
	CAPFLAG(ECapabilityCompass);
	CAPFLAG(ECapabilityNmea);
	CAPFLAG(ECapabilityAddress);
	CAPFLAG(ECapabilityBuilding);
	CAPFLAG(ECapabilityMedia);
	}