|
1 /* |
|
2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implementation of coordinate supervisor class |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include <e32math.h> |
|
21 #include <e32const.h> |
|
22 #include <lbttriggerconditionarea.h> |
|
23 #include <lbtgeocircle.h> |
|
24 #include "lbtcelliddatabase.h" |
|
25 #include "lbtcellchangehandler.h" |
|
26 #include "lbtlogger.h" |
|
27 #include "lbtcoordinatesupervisor.h" |
|
28 #include "lbtstrategyengineobserver.h" |
|
29 #include "lbtpsychangelistner.h" |
|
30 |
|
31 // ==================== CONSTANTS =================================== |
|
32 |
|
33 /** |
|
34 * Constant used to adjust trigger radius to accomodate inaccuracy |
|
35 * of position fixes |
|
36 */ |
|
37 static const TReal32 KAccuracyMultiplier = 0.666667; |
|
38 |
|
39 /** |
|
40 * The cut off value of the ratio of radius to position accuracy. Over this |
|
41 * value the radius of a trigger will not be expanded. |
|
42 */ |
|
43 static const TReal32 KCofftOfHighEdgeLimit = 1.5; |
|
44 |
|
45 /** |
|
46 * Constant used in calculation of trigger hysteresis |
|
47 */ |
|
48 static const TUint16 KTriggerRadiusCutoff = 500; |
|
49 |
|
50 /** |
|
51 * Contant time use in calculation of speed |
|
52 */ |
|
53 static const TReal32 constantTime = 20; |
|
54 |
|
55 /** |
|
56 * Defines the number of historic speed values that will be stored |
|
57 * and used for calculation of current speed |
|
58 */ |
|
59 static const TUint16 maxObsValues = 10; |
|
60 |
|
61 /** |
|
62 * Minimum calculated speed. If this calculated speed drops below this value |
|
63 * then the below value is speed as the speed value |
|
64 */ |
|
65 static const TReal KMinProjSpeed = 20.0; |
|
66 |
|
67 static const TReal KMaxSpeedToUseMvmtDet = 5.0; |
|
68 /** |
|
69 * If the estimated sleep interval goes below this value then location request |
|
70 * will be issued immediately with the estimated interval as the time out value |
|
71 * for the location rquest |
|
72 */ |
|
73 static const TInt KMinSleepInterval = 2; |
|
74 |
|
75 /** |
|
76 * Multiplier used for 10 power 3. Used for conversion of seconds to micro |
|
77 * seconds |
|
78 */ |
|
79 static const TUint KMicroMultiplier = 1000000; |
|
80 |
|
81 /** |
|
82 * Number of seconds to sleep before making location request in cases where |
|
83 * a location acquisition attempt fails to obtain a fix |
|
84 */ |
|
85 static const TUint KSleepTimeOnLocAcqFailure = 10; // 10 seconds |
|
86 |
|
87 /** |
|
88 * Safe range of HA obtained from NPP |
|
89 */ |
|
90 //static const TUint KNppSafeHA = 1500; // 1500 meters |
|
91 |
|
92 // ============================== MEMBER FUNCTIONS ============================================ |
|
93 |
|
94 // ----------------------------------------------------------------------------- |
|
95 // CLbtCoOrdinateSupervisor::NewL |
|
96 // CLbtCoOrdinateSupervisor instantiation method |
|
97 // ----------------------------------------------------------------------------- |
|
98 // |
|
99 CLbtCoOrdinateSupervisor* CLbtCoOrdinateSupervisor::NewL( TAny* aConstructionParameters, |
|
100 CLbtTriggerView* aView, |
|
101 MLbtStrategyEngineObsrvr* aObserver, |
|
102 CLbtCellChangeHandler* aCellChangeHandler ) |
|
103 { |
|
104 CLbtCoOrdinateSupervisor* self = new ( ELeave ) CLbtCoOrdinateSupervisor(); |
|
105 CleanupStack::PushL( self ); |
|
106 self->ConstructL( aConstructionParameters, aView,aObserver,aCellChangeHandler ); |
|
107 CleanupStack::Pop(); |
|
108 return self; |
|
109 } |
|
110 |
|
111 |
|
112 // ----------------------------------------------------------------------------- |
|
113 // CLbtCoOrdinateSupervisor::~CLbtCoOrdinateSupervisor |
|
114 // Default destructor |
|
115 // ----------------------------------------------------------------------------- |
|
116 // |
|
117 CLbtCoOrdinateSupervisor::~CLbtCoOrdinateSupervisor() |
|
118 { |
|
119 // This is just done as a precautionary measure! |
|
120 StopSupervision(); |
|
121 delete iLocationRequestor; |
|
122 delete iStatusManager; |
|
123 delete iTimer; |
|
124 delete iPsyChangeListner; |
|
125 delete iCellIdDatabase; |
|
126 iNObservedValues.Close(); |
|
127 iNearestTriggers.Close(); |
|
128 } |
|
129 |
|
130 |
|
131 // ----------------------------------------------------------------------------- |
|
132 // CLbtCoOrdinateSupervisor::StartSupervision |
|
133 // |
|
134 // ----------------------------------------------------------------------------- |
|
135 // |
|
136 void CLbtCoOrdinateSupervisor::StartSupervision() |
|
137 { |
|
138 FUNC_ENTER("CLbtCoOrdinateSupervisor::StartSupervision"); |
|
139 iCellChangeHandler->SetObserver( this ); |
|
140 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
141 } |
|
142 |
|
143 |
|
144 // ----------------------------------------------------------------------------- |
|
145 // CLbtCoOrdinateSupervisor::StopSupervision |
|
146 // |
|
147 // ----------------------------------------------------------------------------- |
|
148 // |
|
149 void CLbtCoOrdinateSupervisor::StopSupervision() |
|
150 { |
|
151 FUNC_ENTER("CLbtCoOrdinateSupervisor::StopSupervision"); |
|
152 iCellChangeHandler->Remove( this ); |
|
153 Term(); |
|
154 } |
|
155 |
|
156 |
|
157 // ----------------------------------------------------------------------------- |
|
158 // CLbtCoOrdinateSupervisor::SettingsChanged |
|
159 // Handles notification of triggering settings change provided by server |
|
160 // ----------------------------------------------------------------------------- |
|
161 // |
|
162 void CLbtCoOrdinateSupervisor::SettingsChanged() |
|
163 { |
|
164 iEngObserver->RetrieveTriggeringSettings( iSettings ); |
|
165 } |
|
166 |
|
167 |
|
168 // ----------------------------------------------------------------------------- |
|
169 // CLbtCoOrdinateSupervisor::Resume |
|
170 |
|
171 // ----------------------------------------------------------------------------- |
|
172 // |
|
173 void CLbtCoOrdinateSupervisor::Resume() |
|
174 { |
|
175 FUNC_ENTER("CLbtCoOrdinateSupervisor::Resume"); |
|
176 TInt err = KErrNone; |
|
177 iCellChangeHandler->SetObserver( this ); |
|
178 |
|
179 switch( iProjectedState ) |
|
180 { |
|
181 case ELocationAcquisition: |
|
182 iProjectedState = EIdle; |
|
183 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
184 break; |
|
185 |
|
186 case ETriggerEvaluation: |
|
187 // Reset trigger iterator and start evaluation of all triggers in |
|
188 // view |
|
189 iProjectedState = EIdle; |
|
190 err = ResetViewIterator(); |
|
191 if( KErrNone != err ) |
|
192 { |
|
193 return; |
|
194 } |
|
195 iState = ETriggerEvaluation; |
|
196 SetEvent(); |
|
197 break; |
|
198 |
|
199 case EUpdateIntervalEstimation: |
|
200 |
|
201 // Evaluate triggers that have undergone changes during the state |
|
202 // change. This is to determine any new nearest trigger |
|
203 iProjectedState = EIdle; |
|
204 |
|
205 |
|
206 iView->DetermineNearestTriggerChanges( &iNearestTriggers ); |
|
207 if( iNearestTriggers.Count() == 0 ) |
|
208 { |
|
209 // This means all known nearest triggers have been modified. |
|
210 // Reset iterator re-evaluate all triggers in the system. |
|
211 TInt err = ResetViewIterator(); |
|
212 if( KErrNone != err ) |
|
213 { |
|
214 return; |
|
215 } |
|
216 |
|
217 iState = ETriggerEvaluation; |
|
218 SetEvent(); |
|
219 } |
|
220 else |
|
221 { |
|
222 // Evaluate only the modified triggers |
|
223 TBool makeLocReq = EFalse; |
|
224 TRAP( err, makeLocReq = EvaluateModifiedTriggersL() ); |
|
225 if( KErrNone == err ) |
|
226 { |
|
227 if( makeLocReq ) |
|
228 { |
|
229 // Location request is needed based on evaluating |
|
230 // modified triggers |
|
231 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
232 return; |
|
233 } |
|
234 // Switch to estimation of update interval |
|
235 iState = EUpdateIntervalEstimation; |
|
236 SetEvent(); |
|
237 } |
|
238 else |
|
239 { |
|
240 Term(); |
|
241 } |
|
242 } |
|
243 break; |
|
244 |
|
245 case ESleep: |
|
246 iProjectedState = EIdle; |
|
247 iState = ESleep; |
|
248 SetEvent(); |
|
249 break; |
|
250 |
|
251 case EIdle: |
|
252 if( EIdle == iState && EIdle == iProjectedState |
|
253 && iView->CoordTriggerCount() ) |
|
254 { |
|
255 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
256 } |
|
257 break; |
|
258 |
|
259 default: |
|
260 break; |
|
261 } |
|
262 } |
|
263 |
|
264 |
|
265 // ----------------------------------------------------------------------------- |
|
266 // CLbtCoOrdinateSupervisor::Suspend |
|
267 // ----------------------------------------------------------------------------- |
|
268 // |
|
269 void CLbtCoOrdinateSupervisor::Suspend() |
|
270 { |
|
271 FUNC_ENTER("CLbtCoOrdinateSupervisor::Suspend"); |
|
272 iCellChangeHandler->Remove( this ); |
|
273 switch( iState ) |
|
274 { |
|
275 case ELocationAcquisition: |
|
276 if( iLastLocationFixType == EProperFix ) |
|
277 { |
|
278 iLocationRequestor->Cancel(); |
|
279 } |
|
280 else |
|
281 { |
|
282 iLocationRequestor->CancelFixFromNpp(); |
|
283 } |
|
284 |
|
285 iProjectedState = iState; |
|
286 iState = EIdle; |
|
287 break; |
|
288 |
|
289 case ETriggerEvaluation: |
|
290 iProjectedState = ETriggerEvaluation; |
|
291 iState = EIdle; |
|
292 break; |
|
293 |
|
294 case EUpdateIntervalEstimation: |
|
295 iProjectedState = EUpdateIntervalEstimation; |
|
296 iState = EIdle; |
|
297 break; |
|
298 |
|
299 case ESleep: |
|
300 iTimer->Cancel(); |
|
301 iProjectedState = iState; |
|
302 iState = EIdle; |
|
303 |
|
304 case EIdle: |
|
305 break; |
|
306 |
|
307 default: |
|
308 break; |
|
309 } |
|
310 |
|
311 Cancel(); |
|
312 } |
|
313 |
|
314 |
|
315 // ----------------------------------------------------------------------------- |
|
316 // CLbtCoOrdinateSupervisor::Reset |
|
317 // ----------------------------------------------------------------------------- |
|
318 // |
|
319 void CLbtCoOrdinateSupervisor::Reset() |
|
320 { |
|
321 iState = iProjectedState = EIdle; |
|
322 iNearestTriggers.Reset(); |
|
323 iLocReqCount = 0; |
|
324 TPositionInfo posInfo; |
|
325 iPosInfo = posInfo; |
|
326 iFixForFiringCloseTriggers = EFalse; |
|
327 } |
|
328 |
|
329 |
|
330 // ----------------------------------------------------------------------------- |
|
331 // CLbtCoOrdinateSupervisor::GetPositionInfo |
|
332 // Processes the location information obtained from location requestor |
|
333 // ----------------------------------------------------------------------------- |
|
334 // |
|
335 void CLbtCoOrdinateSupervisor::GetPositionInfoL() |
|
336 { |
|
337 FUNC_ENTER("CLbtCoOrdinateSupervisor::GetPositionInfo"); |
|
338 |
|
339 // Update location acquisition status information |
|
340 |
|
341 if( !( (KErrNone == iStatus.Int()) || |
|
342 (KPositionQualityLoss == iStatus.Int()) ) ) |
|
343 { |
|
344 ERROR("Position Information with : %d",iStatus.Int()); |
|
345 iStatusManager->ReportLocationAcquisitionStatus( iStatus.Int() ); |
|
346 |
|
347 // The following check determines if there was a problem using the |
|
348 // specified positioning technology to retrieve position information |
|
349 if( KErrNotFound == iStatus.Int() && |
|
350 iLastLocationFixType == EProperFix ) |
|
351 { |
|
352 LOG("Specified PSY not found"); |
|
353 iAcquisitionStatus = ELocationAcquisitionNoMethod; |
|
354 |
|
355 if( iPsyChangeListner == NULL ) |
|
356 { |
|
357 iPsyChangeListner = CLbtPsyChangeListner::NewL( *this ); |
|
358 } |
|
359 iPsyChangeListner->StartToListen( iModuleId ); |
|
360 LOG1("Listen to PSY change:%x",iModuleId); |
|
361 TUid defaultID = { 0XFFFFFFFF }; |
|
362 if( iLocationRequestor->GetPositionModuleId() != defaultID ) |
|
363 { |
|
364 LOG("Use default proxy"); |
|
365 // switch to using default positioning technology |
|
366 iModuleId = defaultID; |
|
367 RequestTerminalPosition( iSettings.iLocationRequestTimeout,EProperFix ); |
|
368 } |
|
369 } |
|
370 else |
|
371 { |
|
372 LOG("Location acquisition failed"); |
|
373 if( iFixForFiringCloseTriggers && |
|
374 (KErrTimedOut == iStatus.Int())&& |
|
375 iLastLocationFixType == EProperFix ) |
|
376 { |
|
377 LOG("Firing Close triggers"); |
|
378 FireClosestTriggers(); |
|
379 RequestTerminalPosition(iSettings.iLocationRequestTimeout, EProperFix); |
|
380 } |
|
381 else |
|
382 { |
|
383 if( iLastLocationFixType == EProperFix ) |
|
384 { |
|
385 // Get fix from NPP PSY |
|
386 LOG("Timed Out. Taking fix from NPP"); |
|
387 RequestTerminalPosition( iSettings.iLocationRequestTimeout, EFixFromNpp ); |
|
388 return; |
|
389 |
|
390 /* |
|
391 iState = ESleep; |
|
392 iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue ); |
|
393 SetActive(); |
|
394 |
|
395 if( KErrAccessDenied == iStatus.Int() ) |
|
396 { |
|
397 iAcquisitionStatus = ELocationAcquisitionPrivacyReject; |
|
398 } |
|
399 else |
|
400 { |
|
401 iAcquisitionStatus = ELocationAcquisitionFailure; |
|
402 }*/ |
|
403 } |
|
404 else |
|
405 { |
|
406 LOG("Npp psy failed to provide fix. Sleep now"); |
|
407 iState = ESleep; |
|
408 iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue ); |
|
409 SetActive(); |
|
410 |
|
411 if( KErrAccessDenied == iStatus.Int() ) |
|
412 { |
|
413 iAcquisitionStatus = ELocationAcquisitionPrivacyReject; |
|
414 } |
|
415 else |
|
416 { |
|
417 iAcquisitionStatus = ELocationAcquisitionFailure; |
|
418 } |
|
419 } |
|
420 } |
|
421 } |
|
422 |
|
423 if( iFixForFiringCloseTriggers ) |
|
424 { |
|
425 iFixForFiringCloseTriggers = EFalse; |
|
426 } |
|
427 |
|
428 // Update supervision dynamic info to the strategy class |
|
429 TLbtStrategySupervisionDynamicInfo supervisionDynamicInfo; |
|
430 supervisionDynamicInfo.iDistanceToNearestTrigger = 0.0; |
|
431 supervisionDynamicInfo.iLatestAcquiredPosInfo = iPosInfo; |
|
432 supervisionDynamicInfo.iLocationAcquisitionStatus = iAcquisitionStatus; |
|
433 supervisionDynamicInfo.iNearestTriggerId = 0; |
|
434 |
|
435 iEngObserver->ReportTriggeringSupervisionStatus( supervisionDynamicInfo ); |
|
436 return; |
|
437 } |
|
438 |
|
439 if( iStatus.Int() == KPositionQualityLoss ) |
|
440 { |
|
441 // TODO: Remove this. Only for Debug |
|
442 TPosition currentPosition; |
|
443 iPosInfo.GetPosition( currentPosition ); |
|
444 LOG("Received KPositionQualityLoss"); |
|
445 LOG1("Lat:%f",currentPosition.Latitude()); |
|
446 LOG1("Long:%f",currentPosition.Longitude()); |
|
447 LOG1("HA:%f",currentPosition.HorizontalAccuracy()); |
|
448 } |
|
449 |
|
450 iStatusManager->ReportLocationAcquisitionStatus( KErrNone ); |
|
451 // The fix was taken to fire nearest triggers then reset the flag |
|
452 // to EFalse since the fix was successful and the nearest triggers will be |
|
453 // evaluated and will be fired |
|
454 if(iFixForFiringCloseTriggers) |
|
455 { |
|
456 iFixForFiringCloseTriggers = EFalse; |
|
457 } |
|
458 |
|
459 TPosition currentPosition, prevPosition; |
|
460 iPosInfo.GetPosition( currentPosition ); |
|
461 iPrevPosInfo.GetPosition( prevPosition ); |
|
462 |
|
463 if( Math::IsNaN( currentPosition.Latitude() ) || |
|
464 Math::IsNaN( currentPosition.Longitude() ) ) |
|
465 { |
|
466 LOG("ERROR:Lat/Long is Nan. Sleep now"); |
|
467 iState = ESleep; |
|
468 iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue ); |
|
469 SetActive(); |
|
470 |
|
471 if( KErrAccessDenied == iStatus.Int() ) |
|
472 { |
|
473 iAcquisitionStatus = ELocationAcquisitionPrivacyReject; |
|
474 } |
|
475 else |
|
476 { |
|
477 iAcquisitionStatus = ELocationAcquisitionFailure; |
|
478 } |
|
479 return; |
|
480 } |
|
481 |
|
482 // Record the time at which we got the fix |
|
483 iLastFixTime.UniversalTime(); |
|
484 |
|
485 // Take note of reference time that would be used during estimation of |
|
486 // sleep interval |
|
487 iAcquisitionStatus = ELocationAcquisitionActive; |
|
488 |
|
489 iLocReqCount++; |
|
490 iLocationRequestor->GetModuleInfo( iPosInfo.ModuleId() ); |
|
491 |
|
492 if( iLocArea.iCellId && iLastCellRequestStatus == KErrNone ) |
|
493 { |
|
494 LOG("Writing position to DB"); |
|
495 LOG1("Cell Id = %d", iLocArea.iCellId ); |
|
496 LOG1("LAC = %d", iLocArea.iLocationAreaCode ); |
|
497 // Add current cell id position to cell-id database |
|
498 TInt countryCode,networkCode; |
|
499 |
|
500 TLex lex( iNwInfo.iCountryCode ); |
|
501 lex.Val( countryCode ); |
|
502 |
|
503 lex.Assign( iNwInfo.iNetworkId ); |
|
504 lex.Val( networkCode ); |
|
505 |
|
506 TPosition cellPosition; |
|
507 iPosInfo.GetPosition( cellPosition ); |
|
508 if( iLastLocationFixType == EProperFix ) |
|
509 { |
|
510 cellPosition.SetHorizontalAccuracy( 3000 ); |
|
511 } |
|
512 |
|
513 iCellIdDatabase->InsertCidLocation( countryCode, |
|
514 networkCode, |
|
515 iLocArea.iLocationAreaCode, |
|
516 iLocArea.iCellId, |
|
517 cellPosition ); |
|
518 } |
|
519 |
|
520 // Check if there is no movement from last location fix. If true then |
|
521 // re-evaluate sleep interval |
|
522 TReal32 dist; |
|
523 currentPosition.Distance( prevPosition, dist ); |
|
524 if( dist == 0 ) |
|
525 { |
|
526 iState = EUpdateIntervalEstimation; |
|
527 SetEvent(); |
|
528 } |
|
529 |
|
530 LOG1("Lat:%f",currentPosition.Latitude()); |
|
531 LOG1("Long:%f",currentPosition.Longitude()); |
|
532 LOG1("HA:%f",currentPosition.HorizontalAccuracy()); |
|
533 |
|
534 // Switch to idle state as refresh is an async operation. Set projected |
|
535 // state to trigger evaluation which will commence once the refresh |
|
536 // operation is complete |
|
537 iState = ETriggerEvaluation; |
|
538 SetEvent(); |
|
539 |
|
540 } |
|
541 |
|
542 |
|
543 // ----------------------------------------------------------------------------- |
|
544 // CLbtCoOrdinateSupervisor::EvaluateTriggersL |
|
545 // Evaluates triggers based on the location information obtained |
|
546 // ----------------------------------------------------------------------------- |
|
547 // |
|
548 void CLbtCoOrdinateSupervisor::EvaluateTriggersL() |
|
549 { |
|
550 FUNC_ENTER("CLbtCoOrdinateSupervisor::EvaluateTriggersL"); |
|
551 |
|
552 // Reset nearest trigger array |
|
553 iNearestTriggers.Reset(); |
|
554 |
|
555 // TODO: In case of updates to trigger information do not change state |
|
556 // else change state to EUpdateIntervalEstimation |
|
557 CLbtContainerTriggerEntry* conTrigger; |
|
558 |
|
559 // ResetViewIterator will switch state to Idle if there are no triggers in |
|
560 // the system |
|
561 if( KErrNone != ResetViewIterator() ) |
|
562 { |
|
563 return; |
|
564 } |
|
565 |
|
566 while( iViewIterator.NextL( conTrigger ) ) |
|
567 { |
|
568 if( conTrigger ) |
|
569 { |
|
570 CLbtTriggerEntry* trigger = conTrigger->TriggerEntry(); |
|
571 if( CLbtTriggerConditionBase::ETriggerConditionArea == |
|
572 trigger->GetCondition()->Type() ) |
|
573 { |
|
574 // Area type trigger |
|
575 CLbtTriggerConditionArea* triggerConArea = |
|
576 static_cast< CLbtTriggerConditionArea* > |
|
577 ( trigger->GetCondition() ); |
|
578 |
|
579 switch( triggerConArea->TriggerArea()->Type() ) |
|
580 { |
|
581 // Circular area |
|
582 case CLbtGeoAreaBase::ECircle: |
|
583 { |
|
584 if( iLastLocationFixType == EProperFix ) |
|
585 { |
|
586 EvalCircularTriggerL( conTrigger ); |
|
587 } |
|
588 else if( iLastLocationFixType == EFixFromDb || iLastLocationFixType == EFixFromNpp ) |
|
589 { |
|
590 if( EvalCircularTriggerBasedOnCellPositionL( conTrigger ) ) |
|
591 { |
|
592 if( iLastLocationFixType == EFixFromNpp ) |
|
593 { |
|
594 // Fix is taken from NPP only when Proper Fix fails. Now we should |
|
595 // sleep for location acquisition failure time our period since there is no point |
|
596 // in attempting another proper fix |
|
597 iState = ESleep; |
|
598 iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue ); |
|
599 SetActive(); |
|
600 |
|
601 if( KErrAccessDenied == iStatus.Int() ) |
|
602 { |
|
603 iAcquisitionStatus = ELocationAcquisitionPrivacyReject; |
|
604 } |
|
605 else |
|
606 { |
|
607 iAcquisitionStatus = ELocationAcquisitionFailure; |
|
608 } |
|
609 } |
|
610 else |
|
611 { |
|
612 RequestTerminalPosition( iSettings.iLocationRequestTimeout,EProperFix ); |
|
613 } |
|
614 return; |
|
615 } |
|
616 } |
|
617 break; |
|
618 } |
|
619 default: |
|
620 break; |
|
621 } |
|
622 } |
|
623 } |
|
624 } |
|
625 |
|
626 // Update supervision dynamic info to the strategy class |
|
627 TLbtStrategySupervisionDynamicInfo supervisionDynamicInfo; |
|
628 if( iNearestTriggers.Count() ) |
|
629 { |
|
630 supervisionDynamicInfo.iDistanceToNearestTrigger = iNearestTriggers[0].distance; |
|
631 supervisionDynamicInfo.iNearestTriggerId = iNearestTriggers[0].id; |
|
632 } |
|
633 supervisionDynamicInfo.iLatestAcquiredPosInfo = iPosInfo; |
|
634 supervisionDynamicInfo.iLocationAcquisitionStatus = iAcquisitionStatus; |
|
635 |
|
636 |
|
637 iEngObserver->ReportTriggeringSupervisionStatus( supervisionDynamicInfo ); |
|
638 |
|
639 iState = EUpdateIntervalEstimation; |
|
640 SetEvent(); |
|
641 } |
|
642 |
|
643 |
|
644 // ----------------------------------------------------------------------------- |
|
645 // CLbtCoOrdinateSupervisor::EvaluateTriggers |
|
646 // Evaluates triggers based on the location information obtained |
|
647 // ----------------------------------------------------------------------------- |
|
648 // |
|
649 TBool CLbtCoOrdinateSupervisor::EvaluateModifiedTriggersL() |
|
650 { |
|
651 FUNC_ENTER("CLbtCoOrdinateSupervisor::EvaluateModifiedTriggersL"); |
|
652 |
|
653 // Retrieve modified trigger list from trigger view to be supervised |
|
654 RArray< TLbtTriggerId > modifiedTriggers; |
|
655 iView->GetModifiedTriggers( modifiedTriggers ); |
|
656 CleanupClosePushL( modifiedTriggers ); |
|
657 if( modifiedTriggers.Count() ) |
|
658 { |
|
659 // TODO: Need to check for the deletion of |
|
660 // Create an iterator to parse through the modified trigger list |
|
661 CLbtTriggerView::TTriggerViewIter iter = iView->Begin( &modifiedTriggers, CLbtGeoAreaBase::ECircle ); |
|
662 |
|
663 CLbtContainerTriggerEntry* conTrigger; |
|
664 while( iter.NextL( conTrigger ) ) |
|
665 { |
|
666 if( conTrigger ) |
|
667 { |
|
668 CLbtTriggerEntry* trigger = conTrigger->TriggerEntry(); |
|
669 if( CLbtTriggerConditionBase::ETriggerConditionArea == |
|
670 trigger->GetCondition()->Type() ) |
|
671 { |
|
672 // Area type trigger |
|
673 CLbtTriggerConditionArea* triggerConArea = |
|
674 static_cast< CLbtTriggerConditionArea* > |
|
675 ( trigger->GetCondition() ); |
|
676 |
|
677 switch( triggerConArea->TriggerArea()->Type() ) |
|
678 { |
|
679 // Circular area |
|
680 case CLbtGeoAreaBase::ECircle: |
|
681 if( iLastLocationFixType == EProperFix ) |
|
682 { |
|
683 EvalCircularTriggerL( conTrigger ); |
|
684 } |
|
685 else if( iLastLocationFixType == EFixFromDb || iLastLocationFixType == EFixFromNpp ) |
|
686 { |
|
687 if( EvalCircularTriggerBasedOnCellPositionL( conTrigger ) ) |
|
688 { |
|
689 CleanupStack::PopAndDestroy(); // modifiedTriggers |
|
690 return ETrue; |
|
691 } |
|
692 } |
|
693 break; |
|
694 |
|
695 // TODO: Cell ID triggers need to be handled |
|
696 default: |
|
697 break; |
|
698 } |
|
699 } |
|
700 } |
|
701 } |
|
702 } |
|
703 |
|
704 CleanupStack::PopAndDestroy(); // modifiedTriggers |
|
705 return EFalse; |
|
706 } |
|
707 |
|
708 |
|
709 // ----------------------------------------------------------------------------- |
|
710 // CLbtCoOrdinateSupervisor::EvalCircularTrigger |
|
711 // Evaluates triggers with circular area definition |
|
712 // ----------------------------------------------------------------------------- |
|
713 // |
|
714 void CLbtCoOrdinateSupervisor::EvalCircularTriggerL( |
|
715 CLbtContainerTriggerEntry* aTrigger ) |
|
716 { |
|
717 FUNC_ENTER("CLbtCoOrdinateSupervisor::EvalCircularTrigger"); |
|
718 |
|
719 |
|
720 // Extract strategy data |
|
721 TStrategyData strategyData = aTrigger->StrategyData(); |
|
722 |
|
723 TInt remRearmTime = 0; |
|
724 TReal distanceToLatestLocation = 0.0; |
|
725 TBool hasRearmTimeExpired = ETrue; |
|
726 |
|
727 LOGSTRING("Trigger: \"%S\" ", &(aTrigger->TriggerEntry()->Name())); |
|
728 |
|
729 if( strategyData.iFireTime ) |
|
730 { |
|
731 TTime triggerFiredTime( strategyData.iFireTime ); |
|
732 |
|
733 TTime currentTime; |
|
734 currentTime.UniversalTime(); |
|
735 |
|
736 TTimeIntervalSeconds interval; |
|
737 currentTime.SecondsFrom( triggerFiredTime, interval ); |
|
738 |
|
739 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm() - interval.Int(); |
|
740 |
|
741 |
|
742 if( remRearmTime <= 0 ) |
|
743 { |
|
744 remRearmTime = 0; |
|
745 strategyData.iFireTime = 0; |
|
746 } |
|
747 else |
|
748 { |
|
749 LOG("Rearm Time has not expired"); |
|
750 hasRearmTimeExpired = EFalse; |
|
751 } |
|
752 } |
|
753 |
|
754 CLbtTriggerConditionArea* trgCondition = |
|
755 static_cast< CLbtTriggerConditionArea* > |
|
756 ( ( aTrigger->TriggerEntry() )->GetCondition() ); |
|
757 |
|
758 CLbtGeoCircle* circularArea = static_cast< CLbtGeoCircle* > |
|
759 ( trgCondition->TriggerArea() ); |
|
760 |
|
761 // Calculate distance of trigger from current location |
|
762 TReal32 distanceToCenter; |
|
763 TPosition currentPosition; |
|
764 iPosInfo.GetPosition( currentPosition ); |
|
765 TInt err = currentPosition.Distance( circularArea->Center(), |
|
766 distanceToCenter ); |
|
767 if( KErrNone != err ) |
|
768 { |
|
769 ERROR("Error in calculating distance:%d",err); |
|
770 LOG1("Current Lat:%f",currentPosition.Latitude()); |
|
771 LOG1("Current Long:%f",currentPosition.Longitude()); |
|
772 LOG1("Trigger Lat:%f",circularArea->Center().Latitude()); |
|
773 LOG1("Trigger Long:%f",circularArea->Center().Longitude()); |
|
774 return; |
|
775 } |
|
776 |
|
777 // Determine trigger radius and hysteresis radius to be used for supervision |
|
778 // based on the accuracy of location fix |
|
779 TTriggerArea triggerArea; |
|
780 TReal positionAccuracy = currentPosition.HorizontalAccuracy(); |
|
781 triggerArea = EstimateTriggerRadii( circularArea->Radius(), |
|
782 aTrigger->ExtendedTriggerInfo()->HysteresisRadius(), |
|
783 positionAccuracy ); |
|
784 |
|
785 // ENTRY Trigger |
|
786 // Determine current position of terminal relative to the trigger area and |
|
787 // set trigger fire status accordingly |
|
788 if( CLbtTriggerConditionArea::EFireOnEnter == trgCondition->Direction() ) |
|
789 { |
|
790 TLbtTriggerDataMask dataMask = 0; |
|
791 |
|
792 TReal tolerableRadius = CalculateTolerableRadius( triggerArea.triggerRadius ); |
|
793 // Terminal is inside trigger area |
|
794 if( ( distanceToCenter < tolerableRadius ) && |
|
795 ( ( distanceToCenter + positionAccuracy ) <= triggerArea.hysteresisRadius ) ) |
|
796 { |
|
797 LOG("Inside triggerin area"); |
|
798 // If trigger in active state then fire trigger and set state to |
|
799 // inactive. If trigger is inactive nothing is to be done other |
|
800 // than calculating its distance from the hysteresis boundary |
|
801 if( EActive == strategyData.iActivityStatus ) |
|
802 { |
|
803 LOG("Active trigger"); |
|
804 // Check FireOnCreation flag here. If EFalse then dont |
|
805 // fire the trigger. Instead only change the activity |
|
806 // status. |
|
807 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() && |
|
808 hasRearmTimeExpired ) |
|
809 { |
|
810 // Set trigger state to fired |
|
811 aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue ); |
|
812 TLbtTriggerFireInfo triggerFireInfo; |
|
813 TPositionInfo positionInfo; |
|
814 triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id(); |
|
815 triggerFireInfo.iFiredPositionInfo = iPosInfo; |
|
816 |
|
817 aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo ); |
|
818 |
|
819 // Time at which trigger fired |
|
820 TTime triggerFiredTime; |
|
821 triggerFiredTime.UniversalTime(); |
|
822 LOG("TRIGGER FIRED"); |
|
823 |
|
824 strategyData.iFireTime = triggerFiredTime.Int64(); |
|
825 |
|
826 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm(); |
|
827 dataMask |= |
|
828 CLbtContainerTriggerEntry::EContainerAttributeIsFired | |
|
829 CLbtContainerTriggerEntry::EContainerAttributeFireInfo ; |
|
830 } |
|
831 |
|
832 // Set trigger to inactive state |
|
833 strategyData.iActivityStatus = EInactive; |
|
834 } |
|
835 |
|
836 // Calculate distance to current location and update trigger's |
|
837 // dynamic info. This distance is (rH - D) where D is the distance |
|
838 // between the two centers and rH is the radius of the hysteresis |
|
839 // circle. Here the radius of hysteresis boundary is considered for |
|
840 // distance calculation as this trigger would undergo a state |
|
841 // change only when it crosses the hysteresis area |
|
842 distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter ); |
|
843 } |
|
844 |
|
845 // Terminal is outside hysteresis area |
|
846 else if( distanceToCenter > ( triggerArea.hysteresisRadius + positionAccuracy ) ) |
|
847 { |
|
848 if( EInactive == strategyData.iActivityStatus ) |
|
849 { |
|
850 // Reset trigger state to valid |
|
851 strategyData.iActivityStatus = EActive; |
|
852 LOG("Trigger activated"); |
|
853 } |
|
854 |
|
855 // Calculate distance of trigger to current location and update |
|
856 // trigger's dynamic info. This distance is (D - rT) where D is |
|
857 // the distance between two centers and rT is the radius of trigger. |
|
858 // State change will occur only when the terminal moves beyond the |
|
859 // boundary of the trigger |
|
860 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius ); |
|
861 } |
|
862 |
|
863 // Terminal is inside hysteresis area. |
|
864 else |
|
865 { |
|
866 // Trigger does not undergo any state change in this region. Theres |
|
867 // only distance to be determined here |
|
868 if( EActive == strategyData.iActivityStatus ) |
|
869 { |
|
870 // Terminal was outside hysteresis area earlier. Distance is |
|
871 // therefore (D - rT) |
|
872 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius ); |
|
873 } |
|
874 else |
|
875 { |
|
876 // Terminal was inside trigger area earlier. Distance is |
|
877 // therefore (rH - D) |
|
878 distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter ); |
|
879 } |
|
880 } |
|
881 |
|
882 // Set FireOnCreation flag to ETrue here if its not already |
|
883 // ETrue. This is done to ensure that the trigger is fired |
|
884 // in the subsequent iterations if the triggering conditions |
|
885 // are satisfied. |
|
886 if( !aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() ) |
|
887 { |
|
888 aTrigger->ExtendedTriggerInfo()->SetTriggerFireOnCreation( ETrue ); |
|
889 dataMask |= CLbtContainerTriggerEntry::EContainerAttributeIsTriggerFireOnCreation; |
|
890 } |
|
891 |
|
892 if( dataMask ) |
|
893 { |
|
894 iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, aTrigger, dataMask ); |
|
895 } |
|
896 } |
|
897 |
|
898 // EXIT Trigger |
|
899 else |
|
900 { |
|
901 TLbtTriggerDataMask dataMask = 0; |
|
902 // Retrieve boundary information of trigger |
|
903 TTriggerBoundary boundary = EUndefined; |
|
904 |
|
905 // Retrieve boundary information of trigger |
|
906 ( strategyData.iBoundaryCondition >= 0 && strategyData.iBoundaryCondition <= 2 )?boundary = |
|
907 TTriggerBoundary( strategyData.iBoundaryCondition ):boundary; |
|
908 |
|
909 TReal tolerableRadius = CalculateTolerableRadius( triggerArea.triggerRadius ); |
|
910 |
|
911 // Terminal is inside trigger area |
|
912 if( ( distanceToCenter < tolerableRadius ) && |
|
913 ( ( distanceToCenter + positionAccuracy ) <= triggerArea.hysteresisRadius ) ) |
|
914 { |
|
915 // Check boundary condition to determine if the terminal has moved |
|
916 // inside the trigger area without having gone beyond the area of |
|
917 // hysteresis. In this case the trigger shall not be set as active |
|
918 if( EOutside != boundary && |
|
919 EInactive == strategyData.iActivityStatus ) |
|
920 { |
|
921 // Set trigger state to active |
|
922 strategyData.iActivityStatus = EActive; |
|
923 } |
|
924 |
|
925 // Set boundary as Outside |
|
926 strategyData.iBoundaryCondition = TInt( EOutside ); |
|
927 |
|
928 if( EActive == strategyData.iActivityStatus ) |
|
929 { |
|
930 // Set Distance to the border of trigger area. This distance is |
|
931 // (rT - D). |
|
932 distanceToLatestLocation = Abs( triggerArea.triggerRadius - distanceToCenter ); |
|
933 } |
|
934 else |
|
935 { |
|
936 // Set distance to border of hysteresis area. This distance is |
|
937 // (rH - D) where rH is the radius of hysteresis and D is the |
|
938 // distance between the center of trigger and the center of |
|
939 // location |
|
940 distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter ); |
|
941 } |
|
942 } |
|
943 |
|
944 // Terminal is outside hysteresis area |
|
945 else if( ( distanceToCenter > triggerArea.hysteresisRadius ) && |
|
946 ( distanceToCenter > ( triggerArea.triggerRadius + positionAccuracy ) ) ) |
|
947 { |
|
948 if( EActive == strategyData.iActivityStatus ) |
|
949 { |
|
950 // Check FireOnCreation flag here. If EFalse then dont |
|
951 // fire the trigger. Instead only change the activity |
|
952 // status. |
|
953 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() && |
|
954 hasRearmTimeExpired ) |
|
955 { |
|
956 // Set trigger state to fired |
|
957 aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue ); |
|
958 |
|
959 TLbtTriggerFireInfo triggerFireInfo; |
|
960 TPositionInfo positionInfo; |
|
961 triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id(); |
|
962 triggerFireInfo.iFiredPositionInfo = iPosInfo; |
|
963 |
|
964 aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo ); |
|
965 |
|
966 // Time at which trigger fired |
|
967 TTime triggerFiredTime; |
|
968 triggerFiredTime.UniversalTime(); |
|
969 strategyData.iFireTime = triggerFiredTime.Int64(); |
|
970 LOG("TRIGGER FIRED"); |
|
971 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm(); |
|
972 dataMask |= |
|
973 CLbtContainerTriggerEntry::EContainerAttributeIsFired | |
|
974 CLbtContainerTriggerEntry::EContainerAttributeFireInfo; |
|
975 } |
|
976 |
|
977 // Set the trigger state to inactive |
|
978 strategyData.iActivityStatus = EInactive; |
|
979 |
|
980 } |
|
981 |
|
982 // Set boundary as Inside |
|
983 strategyData.iBoundaryCondition = TInt( EInside ); |
|
984 |
|
985 // Calculate distance to border of trigger area. This distance |
|
986 // is (D - rT) |
|
987 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius ); |
|
988 } |
|
989 |
|
990 // Terminal is inside hysteresis area |
|
991 else |
|
992 { |
|
993 if( EOutside == boundary && EActive == strategyData.iActivityStatus ) |
|
994 { |
|
995 // Check FireOnCreation flag here. If EFalse then dont |
|
996 // fire the trigger. Instead only change the activity |
|
997 // status. |
|
998 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() ) |
|
999 { |
|
1000 // Set trigger state to fired |
|
1001 aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue ); |
|
1002 TLbtTriggerFireInfo triggerFireInfo; |
|
1003 TPositionInfo positionInfo; |
|
1004 triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id(); |
|
1005 triggerFireInfo.iFiredPositionInfo = iPosInfo; |
|
1006 |
|
1007 aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo ); |
|
1008 |
|
1009 // Time at which trigger fired |
|
1010 TTime triggerFiredTime; |
|
1011 triggerFiredTime.UniversalTime(); |
|
1012 |
|
1013 strategyData.iFireTime = triggerFiredTime.Int64(); |
|
1014 strategyData.iBoundaryCondition = TInt( EOutside ); |
|
1015 |
|
1016 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm(); |
|
1017 dataMask |= |
|
1018 CLbtContainerTriggerEntry::EContainerAttributeIsFired | |
|
1019 CLbtContainerTriggerEntry::EContainerAttributeFireInfo; |
|
1020 } |
|
1021 |
|
1022 // Set the trigger state to inactive |
|
1023 strategyData.iActivityStatus = EInactive; |
|
1024 } |
|
1025 |
|
1026 if( EOutside != boundary ) |
|
1027 { |
|
1028 // Set the trigger state to inactive. This is done here because |
|
1029 // if a trigger was newly created (state is active) and it is |
|
1030 // found to be within hysteresis area, then the activity status |
|
1031 // needs to be set to inactive to enable the trigger to be |
|
1032 // handled appropriately when terminal moves inside trigger |
|
1033 // area. |
|
1034 strategyData.iActivityStatus = EInactive; |
|
1035 // Calclulate distance to border of trigger area. This |
|
1036 // distance is (D - rT) |
|
1037 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius ); |
|
1038 } |
|
1039 else |
|
1040 { |
|
1041 // Calculate distance to the boundary of hysteresis. This |
|
1042 // distance is (rH - D) |
|
1043 distanceToLatestLocation = |
|
1044 Abs( triggerArea.hysteresisRadius - distanceToCenter ); |
|
1045 } |
|
1046 } |
|
1047 |
|
1048 // Set FireOnCreation flag to ETrue here if its not already |
|
1049 // ETrue. This is done to ensure that the trigger is fired |
|
1050 // in the subsequent iterations if the triggering conditions |
|
1051 // are satisfied. |
|
1052 if( !aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() ) |
|
1053 { |
|
1054 aTrigger->ExtendedTriggerInfo()->SetTriggerFireOnCreation( ETrue ); |
|
1055 dataMask |= CLbtContainerTriggerEntry::EContainerAttributeIsTriggerFireOnCreation; |
|
1056 } |
|
1057 |
|
1058 if( dataMask ) |
|
1059 { |
|
1060 iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, aTrigger, dataMask ); |
|
1061 } |
|
1062 } |
|
1063 aTrigger->SetStrategyData( strategyData ); |
|
1064 UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation , remRearmTime ); |
|
1065 LOG1("DistToTrig:%f",distanceToLatestLocation ); |
|
1066 } |
|
1067 |
|
1068 |
|
1069 // ----------------------------------------------------------------------------- |
|
1070 // CLbtCoOrdinateSupervisor::EvalCircularTriggerBasedOnCellPosition |
|
1071 // Evaluates triggers with circular area definition |
|
1072 // ----------------------------------------------------------------------------- |
|
1073 // |
|
1074 TBool CLbtCoOrdinateSupervisor::EvalCircularTriggerBasedOnCellPositionL( |
|
1075 CLbtContainerTriggerEntry* aTrigger ) |
|
1076 { |
|
1077 TTime currentTime; |
|
1078 currentTime.UniversalTime(); |
|
1079 |
|
1080 CLbtTriggerConditionArea* trgCondition = |
|
1081 static_cast< CLbtTriggerConditionArea* > |
|
1082 ( ( aTrigger->TriggerEntry() )->GetCondition() ); |
|
1083 |
|
1084 // Extract strategy data |
|
1085 TStrategyData strategyData = aTrigger->StrategyData(); |
|
1086 |
|
1087 TInt remRearmTime = 0; |
|
1088 TReal distanceToLatestLocation = 0.0; |
|
1089 |
|
1090 if( strategyData.iFireTime ) |
|
1091 { |
|
1092 TTime triggerFiredTime( strategyData.iFireTime ); |
|
1093 |
|
1094 TTimeIntervalSeconds interval; |
|
1095 currentTime.SecondsFrom( triggerFiredTime, interval ); |
|
1096 |
|
1097 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm() - interval.Int(); |
|
1098 |
|
1099 if( remRearmTime <= 0 ) |
|
1100 { |
|
1101 remRearmTime = 0; |
|
1102 strategyData.iFireTime = 0; |
|
1103 aTrigger->SetStrategyData( strategyData ); |
|
1104 } |
|
1105 } |
|
1106 |
|
1107 |
|
1108 TPosition currentPosition; |
|
1109 iPosInfo.GetPosition( currentPosition ); |
|
1110 TReal positionAccuracy = currentPosition.HorizontalAccuracy(); |
|
1111 |
|
1112 CLbtGeoCircle* circularArea = static_cast< CLbtGeoCircle* > |
|
1113 ( trgCondition->TriggerArea() ); |
|
1114 |
|
1115 TReal32 distanceToCenter; |
|
1116 TInt err = currentPosition.Distance( circularArea->Center(), |
|
1117 distanceToCenter ); |
|
1118 if( err!=KErrNone ) |
|
1119 { |
|
1120 return ETrue; |
|
1121 } |
|
1122 |
|
1123 // If the trigger is entry type,we calculate distance to the hysterisis radius |
|
1124 if( CLbtTriggerConditionArea::EFireOnEnter == trgCondition->Direction() ) |
|
1125 { |
|
1126 distanceToLatestLocation = distanceToCenter - |
|
1127 ( positionAccuracy+aTrigger->ExtendedTriggerInfo()->HysteresisRadius()); |
|
1128 |
|
1129 if( distanceToLatestLocation < 0 && (remRearmTime == 0) ) |
|
1130 { |
|
1131 // Request fix using any of the available psy |
|
1132 LOG("Request Proper Fix"); |
|
1133 return ETrue; |
|
1134 } |
|
1135 |
|
1136 // Activate the trigger if the trigger is outside Hysteresis area |
|
1137 if( EInactive == strategyData.iActivityStatus && distanceToLatestLocation > 0 ) |
|
1138 { |
|
1139 // Activate the trigger |
|
1140 strategyData.iActivityStatus = EActive; |
|
1141 aTrigger->SetStrategyData( strategyData ); |
|
1142 LOG("Trigger activated based on NPP fix"); |
|
1143 } |
|
1144 UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation, remRearmTime ); |
|
1145 } |
|
1146 // If the trigger is exit type,we calculate distance to the radius |
|
1147 else if( CLbtTriggerConditionArea::EFireOnExit == trgCondition->Direction() ) |
|
1148 { |
|
1149 distanceToLatestLocation = distanceToCenter - |
|
1150 ( positionAccuracy+circularArea->Radius() ); |
|
1151 |
|
1152 if( distanceToLatestLocation < 0 && (remRearmTime == 0) ) |
|
1153 { |
|
1154 // Request fix using any of the available psy |
|
1155 LOG("Request Proper Fix"); |
|
1156 return ETrue; |
|
1157 } |
|
1158 UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation,remRearmTime ); |
|
1159 } |
|
1160 return EFalse; |
|
1161 } |
|
1162 |
|
1163 // ----------------------------------------------------------------------------- |
|
1164 // CLbtCoOrdinateSupervisor::EstimateSleepInterval |
|
1165 // Calculates the sleep interval |
|
1166 // ----------------------------------------------------------------------------- |
|
1167 // |
|
1168 void CLbtCoOrdinateSupervisor::EstimateSleepInterval() |
|
1169 { |
|
1170 FUNC_ENTER("CLbtCoOrdinateSupervisor::EstimateSleepInterval"); |
|
1171 |
|
1172 // TODO: Need to use GPS speed for observed speed values |
|
1173 TReal maxUserSpeed = iSettings.iMaximumUserSpeed; |
|
1174 |
|
1175 TReal actualEstimatedSpeed = KMinProjSpeed; |
|
1176 // Flag to determine if the nearest trigger is an inactive trigger |
|
1177 TBool nearestTriggerInactive = EFalse; |
|
1178 |
|
1179 // This is first time when there are no previously observed values |
|
1180 if( iLocReqCount == 1 ) |
|
1181 { |
|
1182 // First iteration use the minimum update interval |
|
1183 if( iNearestTriggers.Count() ) |
|
1184 { |
|
1185 iSleepInterval = iNearestTriggers[0].distance / maxUserSpeed; |
|
1186 } |
|
1187 else |
|
1188 { |
|
1189 iSleepInterval = iSettings.iMinimumLocationUpdateInterval; |
|
1190 } |
|
1191 } |
|
1192 else |
|
1193 { |
|
1194 iEstimatedUserSpeed = 0.0; |
|
1195 if( (iLastLocationFixType == EFixFromDb) || |
|
1196 (iLastLocationFixType == EFixFromNpp) ) |
|
1197 { |
|
1198 iEstimatedUserSpeed = (maxUserSpeed + KMinProjSpeed)/2; |
|
1199 } |
|
1200 else if( iLastLocationFixType == EProperFix ) |
|
1201 { |
|
1202 // determine average speed from previous location request which is the |
|
1203 // observed speed |
|
1204 TPosition currentPosition, prevPosition; |
|
1205 iPosInfo.GetPosition( currentPosition ); |
|
1206 iPrevPosInfo.GetPosition( prevPosition ); |
|
1207 |
|
1208 TReal32 avgSpeed = 0.0; |
|
1209 |
|
1210 currentPosition.Speed( prevPosition, avgSpeed ); |
|
1211 TObservedValues obsValue; |
|
1212 obsValue.speed = avgSpeed; |
|
1213 obsValue.time = currentPosition.Time(); |
|
1214 |
|
1215 if( iNObservedValues.Count() == maxObsValues ) |
|
1216 { |
|
1217 iNObservedValues.Remove( 0 ); |
|
1218 } |
|
1219 iNObservedValues.Append( obsValue ); |
|
1220 |
|
1221 TReal num = 0.0; |
|
1222 TReal den = 0.0; |
|
1223 TReal obsSpeed = 0.0; |
|
1224 TReal obsTime = 0.0; |
|
1225 TTime currentTime; |
|
1226 |
|
1227 // Determine average of previously obtained observed speed, time values. |
|
1228 // Use the current time value obtained from the approximation of speed. |
|
1229 currentTime.UniversalTime(); |
|
1230 |
|
1231 for( TInt i = 0; i < iNObservedValues.Count(); i++ ) |
|
1232 { |
|
1233 obsSpeed = maxUserSpeed - ( iNObservedValues[i] ).speed; |
|
1234 TTimeIntervalSeconds timediff; |
|
1235 currentTime.SecondsFrom( ( iNObservedValues[i] ).time, timediff ); |
|
1236 obsTime = timediff.Int() / constantTime; |
|
1237 TReal timeExp = 0.0; |
|
1238 Math::Exp( timeExp, (-1 * obsTime ) ); |
|
1239 |
|
1240 num += obsSpeed * timeExp * timeExp; |
|
1241 den += timeExp; |
|
1242 } |
|
1243 |
|
1244 iEstimatedUserSpeed = maxUserSpeed - ( num / den ); |
|
1245 |
|
1246 if( Math::IsNaN(iEstimatedUserSpeed) ) |
|
1247 { |
|
1248 iEstimatedUserSpeed = maxUserSpeed; |
|
1249 } |
|
1250 |
|
1251 actualEstimatedSpeed = iEstimatedUserSpeed; |
|
1252 LOG1("Actual estimated speed:%f",actualEstimatedSpeed); |
|
1253 |
|
1254 if(iEstimatedUserSpeed < KMinProjSpeed) |
|
1255 { |
|
1256 iEstimatedUserSpeed = KMinProjSpeed; |
|
1257 } |
|
1258 // There are some cases estimate user speed goes to infinty. |
|
1259 else if( iEstimatedUserSpeed > maxUserSpeed ) |
|
1260 { |
|
1261 iEstimatedUserSpeed = maxUserSpeed; |
|
1262 } |
|
1263 } |
|
1264 |
|
1265 /** |
|
1266 * Find the position of the nearest trigger which: - |
|
1267 * |
|
1268 * a) Is Active |
|
1269 * b) Its rearm time has expired |
|
1270 */ |
|
1271 TInt position = -1; |
|
1272 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1273 { |
|
1274 iNearestTriggers[i].minTimeRequired = iNearestTriggers[i].distance / iEstimatedUserSpeed; |
|
1275 |
|
1276 if( iNearestTriggers[i].remRearmTime == 0 ) |
|
1277 { |
|
1278 // It is enough for us to know the approx time required to reach nearest trigger whose |
|
1279 // rearm time is not zero( nearest which is not fired ) |
|
1280 position = i; |
|
1281 break; |
|
1282 } |
|
1283 } |
|
1284 |
|
1285 /** |
|
1286 * Determine the sleep interval considering the rearm time of all the fired triggers. |
|
1287 * Sleep interval should be min[max[rearm time,minimum time to reach trigger]]. Flag needed |
|
1288 * for determining if movement detection is needed. Movement detector will be used if |
|
1289 * position acquisition should be made to re-activate the trigger. |
|
1290 */ |
|
1291 iSleepInterval = 0; |
|
1292 TLbtTriggerId nearestTriggerId = 0; |
|
1293 |
|
1294 // Sleep interval should be min[max[rearm time,minimum time to reach trigger]] |
|
1295 if( position >= 0 ) |
|
1296 { |
|
1297 for( TInt i=0;i<=position;i++ ) |
|
1298 { |
|
1299 // Sleep interval for a trigger is the maximum of time to trigger and rearm time |
|
1300 TInt maxSleepTimeForTrigger; |
|
1301 if( iNearestTriggers[i].remRearmTime < iNearestTriggers[i].minTimeRequired ) |
|
1302 { |
|
1303 maxSleepTimeForTrigger = iNearestTriggers[i].minTimeRequired; |
|
1304 } |
|
1305 else |
|
1306 { |
|
1307 maxSleepTimeForTrigger = iNearestTriggers[i].remRearmTime; |
|
1308 } |
|
1309 |
|
1310 // Sleep interval for system is minimum sleep interval of all triggers |
|
1311 if( ( !iSleepInterval.Int() && maxSleepTimeForTrigger ) || |
|
1312 iSleepInterval.Int() > maxSleepTimeForTrigger ) |
|
1313 { |
|
1314 iSleepInterval = maxSleepTimeForTrigger; |
|
1315 nearestTriggerId = iNearestTriggers[i].id; |
|
1316 } |
|
1317 } |
|
1318 } |
|
1319 // Case where all the triggers are waiting for rearm time to elapse |
|
1320 else |
|
1321 { |
|
1322 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1323 { |
|
1324 if( !iSleepInterval.Int() || |
|
1325 ( iSleepInterval.Int() > iNearestTriggers[i].remRearmTime )) |
|
1326 { |
|
1327 iSleepInterval = iNearestTriggers[i].remRearmTime; |
|
1328 } |
|
1329 } |
|
1330 } |
|
1331 |
|
1332 LOG1("Estimated speed:%f",iEstimatedUserSpeed); |
|
1333 |
|
1334 |
|
1335 if( nearestTriggerId ) |
|
1336 { |
|
1337 // Update the nearestTriggerInactive flag |
|
1338 CLbtContainerTriggerEntry* trigEntry = NULL; |
|
1339 TBool found = iView->GetTriggerByID( nearestTriggerId, trigEntry ); |
|
1340 |
|
1341 if( found && (trigEntry != NULL) ) |
|
1342 { |
|
1343 TStrategyData strategyData = trigEntry->StrategyData(); |
|
1344 |
|
1345 if( strategyData.iActivityStatus == EInactive ) |
|
1346 { |
|
1347 // Inside triggering area |
|
1348 nearestTriggerInactive = ETrue; |
|
1349 } |
|
1350 else |
|
1351 { |
|
1352 // Outside triggering area |
|
1353 nearestTriggerInactive = EFalse; |
|
1354 } |
|
1355 } |
|
1356 } |
|
1357 |
|
1358 // Reduce the time taken from last position fix |
|
1359 if( iLastLocationFixType == EProperFix ) |
|
1360 { |
|
1361 TTime currentTime; |
|
1362 currentTime.UniversalTime(); |
|
1363 TTimeIntervalSeconds seconds; |
|
1364 currentTime.SecondsFrom(iLastFixTime, seconds); |
|
1365 iProcessingInterval = seconds.Int(); |
|
1366 iSleepInterval = iSleepInterval.Int() - iProcessingInterval; |
|
1367 } |
|
1368 |
|
1369 // TODO: Check with Krishna on the commented code |
|
1370 // Check to determine if GPS method used for location information. If |
|
1371 // true, then need to use the GPS tracking mode interval here |
|
1372 /*if( iLocationRequestor->GPSUsed() ) |
|
1373 { |
|
1374 if( ( iSleepInterval.Int() < |
|
1375 iSettings.iMinimumLocationUpdateInterval ) || |
|
1376 ( iSleepInterval.Int() - iSettings.iGpsTrackingModeInterval ) < 5 ) |
|
1377 { |
|
1378 iSleepInterval = iSettings.iGpsTrackingModeInterval; |
|
1379 } |
|
1380 } |
|
1381 else |
|
1382 // |
|
1383 { |
|
1384 // If GPS not used check if sleep interval is less than minimum |
|
1385 // update interval. If true then use minimum update interval |
|
1386 if( iSleepInterval.Int() < |
|
1387 iSettings.iMinimumLocationUpdateInterval ) |
|
1388 { |
|
1389 iSleepInterval = iSettings.iMinimumLocationUpdateInterval; |
|
1390 } |
|
1391 }*/ |
|
1392 } |
|
1393 |
|
1394 // If sleep interval is less than KMinSleepInterval and the UE is travelling in |
|
1395 // high speed then request terminal position immediately |
|
1396 if( !nearestTriggerInactive && |
|
1397 ( iSleepInterval.Int() <= KMinSleepInterval ) && |
|
1398 ( iLastLocationFixType == EProperFix ) ) |
|
1399 { |
|
1400 LOG1("Requesting time out %d", iSleepInterval.Int()); |
|
1401 iFixForFiringCloseTriggers = ETrue; |
|
1402 // Here we need fix with in the estimated time to reach trigger.Hence setting timeout value to |
|
1403 // estimated sleep interval |
|
1404 RequestTerminalPosition( (KMinSleepInterval * KMicroMultiplier),EProperFix ); |
|
1405 return; |
|
1406 } |
|
1407 |
|
1408 iState = ESleep; |
|
1409 TBool useMvmtDet = ETrue; |
|
1410 if( iLastLocationFixType != EProperFix ) |
|
1411 { |
|
1412 useMvmtDet = ETrue; |
|
1413 } |
|
1414 else if( nearestTriggerInactive ) |
|
1415 { |
|
1416 useMvmtDet = ETrue; |
|
1417 } |
|
1418 else if( iSleepInterval.Int() < 20 ) |
|
1419 { |
|
1420 useMvmtDet = EFalse; |
|
1421 } |
|
1422 else if( actualEstimatedSpeed > KMaxSpeedToUseMvmtDet ) |
|
1423 { |
|
1424 useMvmtDet = EFalse; |
|
1425 } |
|
1426 LOG1("useMvmtDet = %d", useMvmtDet); |
|
1427 iTimer->Set( iStatus, iSleepInterval, useMvmtDet ); |
|
1428 SetActive(); |
|
1429 } |
|
1430 |
|
1431 |
|
1432 // ----------------------------------------------------------------------------- |
|
1433 // CLbtCoOrdinateSupervisor::ProcessInterrupt |
|
1434 // Evaluates the cause of a timer interrupt and determines the necessary |
|
1435 // actions to be performed |
|
1436 // ----------------------------------------------------------------------------- |
|
1437 // |
|
1438 void CLbtCoOrdinateSupervisor::ProcessInterrupt() |
|
1439 { |
|
1440 FUNC_ENTER("CLbtCoOrdinateSupervisor::ProcessInterrupt"); |
|
1441 |
|
1442 // This is when errors occur while acquiring terminal position |
|
1443 if( !iStatusManager->LocationAcqSuccess() ) |
|
1444 { |
|
1445 // Check sleep interval and determine if sleep mode can continue else |
|
1446 // retry acquiring terminal position. This happens when there are |
|
1447 // changes to triggers in the sleep mode during which the sleep is |
|
1448 // cancelled and trigger view is refreshed. Once the refresh operation |
|
1449 // is completed, this method is invoked. |
|
1450 TTimeIntervalSeconds interval; |
|
1451 if( iTimer->RemainingSleepInterval( interval ) ) |
|
1452 { |
|
1453 iState = ESleep; |
|
1454 if( interval.Int() < 5 ) |
|
1455 { |
|
1456 iTimer->ResetInterval( iStatus, interval,EFalse ); |
|
1457 } |
|
1458 else |
|
1459 { |
|
1460 iTimer->ResetInterval( iStatus, interval,ETrue ); |
|
1461 } |
|
1462 SetActive(); |
|
1463 } |
|
1464 else |
|
1465 { |
|
1466 // If the last location acqusition has failed and the location information for the current cell |
|
1467 // is unavailable then request location from NPP PSY else request from DB itself |
|
1468 if( (iLastCellRequestStatus == KErrNone) && |
|
1469 iLocArea.iCellId ) |
|
1470 { |
|
1471 // Cell information is available |
|
1472 if( !(KErrNone == GetCellIdPosition( iPosInfo ) ) ) |
|
1473 { |
|
1474 RequestTerminalPosition( iSettings.iLocationRequestTimeout, EProperFix ); |
|
1475 } |
|
1476 else |
|
1477 { |
|
1478 RequestTerminalPosition( iSettings.iLocationRequestTimeout, EFixFromDb ); |
|
1479 } |
|
1480 } |
|
1481 else |
|
1482 { |
|
1483 // Current cell information un-available. Make proper fix |
|
1484 RequestTerminalPosition( iSettings.iLocationRequestTimeout, EProperFix ); |
|
1485 } |
|
1486 } |
|
1487 } |
|
1488 |
|
1489 |
|
1490 // This is when sleep mode is interrupted due to notifications from |
|
1491 // container for addition/modification/deletion of triggers in the system |
|
1492 else if( iTimer->SleepIntervalInterrupted() ) |
|
1493 { |
|
1494 TLbtTriggerId nearestTrigger = 0; |
|
1495 if( iNearestTriggers.Count() ) |
|
1496 { |
|
1497 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1498 { |
|
1499 if( iNearestTriggers[i].remRearmTime == 0 ) |
|
1500 { |
|
1501 nearestTrigger = iNearestTriggers[i].id; |
|
1502 break; |
|
1503 } |
|
1504 } |
|
1505 } |
|
1506 iView->DetermineNearestTriggerChanges( &iNearestTriggers ); |
|
1507 |
|
1508 if( iNearestTriggers.Count() == 0 ) |
|
1509 { |
|
1510 // This means the nearest 5 triggers have been changed. Reset |
|
1511 // iterator re-evaluate all triggers in the system. |
|
1512 if( KErrNone != ResetViewIterator() ) |
|
1513 { |
|
1514 return; |
|
1515 } |
|
1516 iState = ETriggerEvaluation; |
|
1517 SetEvent(); |
|
1518 } |
|
1519 else |
|
1520 { |
|
1521 TBool makeLocReq = EFalse; |
|
1522 TRAPD( err, makeLocReq = EvaluateModifiedTriggersL( ) ); |
|
1523 |
|
1524 if( KErrNone != err ) |
|
1525 { |
|
1526 ERROR("EvaluateTriggersL leaving with %d", err); |
|
1527 Term(); |
|
1528 return; |
|
1529 } |
|
1530 |
|
1531 if( makeLocReq ) |
|
1532 { |
|
1533 // Location request is needed based on evaluating |
|
1534 // modified triggers |
|
1535 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
1536 return; |
|
1537 } |
|
1538 |
|
1539 // Check if nearest trigger has changed |
|
1540 TLbtTriggerId nearestTriggerAfterEvaluation = 0; |
|
1541 if( iNearestTriggers.Count() ) |
|
1542 { |
|
1543 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1544 { |
|
1545 if( iNearestTriggers[i].remRearmTime == 0 ) |
|
1546 { |
|
1547 nearestTriggerAfterEvaluation = iNearestTriggers[i].id; |
|
1548 break; |
|
1549 } |
|
1550 } |
|
1551 } |
|
1552 // This is check is required when all triggers in the system has fired |
|
1553 // and new trigger has been added. |
|
1554 if( (nearestTriggerAfterEvaluation) && |
|
1555 (nearestTrigger != nearestTriggerAfterEvaluation) ) |
|
1556 { |
|
1557 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
1558 } |
|
1559 else |
|
1560 { |
|
1561 // Check if there be any remaining sleep interval. If true, |
|
1562 // then switch to sleep mode for the remaining time period. |
|
1563 // Else switch to acquiring location information. |
|
1564 TTimeIntervalSeconds remainingInterval; |
|
1565 if( iTimer->RemainingSleepInterval( remainingInterval ) ) |
|
1566 { |
|
1567 iState = ESleep; |
|
1568 if( remainingInterval.Int() < 5 ) |
|
1569 { |
|
1570 iTimer->ResetInterval( iStatus, remainingInterval,EFalse ); |
|
1571 } |
|
1572 else |
|
1573 { |
|
1574 iTimer->ResetInterval( iStatus, remainingInterval,ETrue ); |
|
1575 } |
|
1576 SetActive(); |
|
1577 } |
|
1578 else |
|
1579 { |
|
1580 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
1581 } |
|
1582 } |
|
1583 } |
|
1584 } |
|
1585 else if( KErrNone == iStatus.Int() || KErrAbort == iStatus.Int() ) |
|
1586 { |
|
1587 // TODO: Check accuracy of movement monitor and |
|
1588 // if there was any detection made. |
|
1589 // For accuracy, pass the distance to nearest trigger as a reference |
|
1590 // for movement detector plugin. If accuracy cannot be met then |
|
1591 // go ahead with acquiring current location else need to switch to |
|
1592 // movement detection mode. |
|
1593 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
1594 } |
|
1595 |
|
1596 // Error in timer operation |
|
1597 else |
|
1598 { |
|
1599 } |
|
1600 |
|
1601 } |
|
1602 |
|
1603 |
|
1604 // ----------------------------------------------------------------------------- |
|
1605 // CLbtCoOrdinateSupervisor::RequestTerminalPosition |
|
1606 // Issues an asynchronous request to determine terminal's position |
|
1607 // ----------------------------------------------------------------------------- |
|
1608 // |
|
1609 void CLbtCoOrdinateSupervisor::RequestTerminalPosition( TInt aLocationRequestTimeout, |
|
1610 TLocationFixType aFixLocationFixType ) |
|
1611 { |
|
1612 FUNC_ENTER("CLbtCoOrdinateSupervisor::RequestTerminalPosition"); |
|
1613 iPrevPosInfo = iPosInfo; |
|
1614 LOG1("aFixLocationFixType = %d", aFixLocationFixType); |
|
1615 LOG1("Cell Id = %d", iLocArea.iCellId); |
|
1616 |
|
1617 if( (aFixLocationFixType == EFixFromDb) && |
|
1618 (iLastCellRequestStatus == KErrNone) && |
|
1619 iLocArea.iCellId ) |
|
1620 { |
|
1621 LOG("Taking fix from DB"); |
|
1622 TInt error = GetCellIdPosition( iPosInfo ); |
|
1623 if( KErrNone == error) |
|
1624 { |
|
1625 LOG("Fix From DB"); |
|
1626 TPosition position; |
|
1627 iPosInfo.GetPosition(position); |
|
1628 LOG1("Lat:%f", position.Latitude()); |
|
1629 LOG1("Long:%f", position.Longitude()); |
|
1630 LOG1("HA:%f", position.HorizontalAccuracy()); |
|
1631 iLastLocationFixType = EFixFromDb; |
|
1632 iState = ETriggerEvaluation; |
|
1633 SetEvent(); |
|
1634 return; |
|
1635 } |
|
1636 else |
|
1637 { |
|
1638 LOG1("Failed to get Fix From DB with %d", error); |
|
1639 } |
|
1640 } |
|
1641 else if( aFixLocationFixType == EFixFromNpp ) |
|
1642 { |
|
1643 iLastLocationFixType = EFixFromNpp; |
|
1644 iLocationRequestor->CurrentLocationFromNpp( iPosInfo, iStatus, |
|
1645 TTimeIntervalMicroSeconds( aLocationRequestTimeout ) ); |
|
1646 iState = ELocationAcquisition; |
|
1647 SetActive(); |
|
1648 return; |
|
1649 } |
|
1650 |
|
1651 iLastLocationFixType = EProperFix; |
|
1652 iLocationRequestor->CurrentLocation( iPosInfo, iStatus, |
|
1653 iModuleId, |
|
1654 TTimeIntervalMicroSeconds( aLocationRequestTimeout ) ); |
|
1655 iState = ELocationAcquisition; |
|
1656 SetActive(); |
|
1657 } |
|
1658 |
|
1659 |
|
1660 // ----------------------------------------------------------------------------- |
|
1661 // CLbtCoOrdinateSupervisor::GetCellIdPosition |
|
1662 // Get the position corresponding to current cell id |
|
1663 // ----------------------------------------------------------------------------- |
|
1664 // |
|
1665 TInt CLbtCoOrdinateSupervisor::GetCellIdPosition( TPositionInfo& aPositionInfo ) |
|
1666 { |
|
1667 FUNC_ENTER("CLbtCoOrdinateSupervisor::GetCellIdPosition"); |
|
1668 TInt countryCode,networkCode; |
|
1669 |
|
1670 TLex lex( iNwInfo.iCountryCode ); |
|
1671 lex.Val( countryCode ); |
|
1672 |
|
1673 lex.Assign( iNwInfo.iNetworkId ); |
|
1674 lex.Val( networkCode ); |
|
1675 |
|
1676 TPosition position; |
|
1677 TInt error = iCellIdDatabase->GetLocationForCid( countryCode,networkCode,iLocArea.iLocationAreaCode, |
|
1678 iLocArea.iCellId,position ); |
|
1679 if( error == KErrNone ) |
|
1680 { |
|
1681 aPositionInfo.SetPosition( position ); |
|
1682 } |
|
1683 return error; |
|
1684 } |
|
1685 |
|
1686 |
|
1687 // ----------------------------------------------------------------------------- |
|
1688 // CLbtCoOrdinateSupervisor::UpdateNearestTriggers |
|
1689 // Updates the record of nearest triggers |
|
1690 // ----------------------------------------------------------------------------- |
|
1691 // |
|
1692 void CLbtCoOrdinateSupervisor::UpdateNearestTriggers( TLbtTriggerId aID, TReal aDistance , TInt aRemRearmTime ) |
|
1693 { |
|
1694 FUNC_ENTER("CLbtCoOrdinateSupervisor::UpdateNearestTriggers"); |
|
1695 TNearestTrigger nTrigger; |
|
1696 nTrigger.distance = aDistance; |
|
1697 nTrigger.id = aID; |
|
1698 nTrigger.remRearmTime = aRemRearmTime; |
|
1699 |
|
1700 TLinearOrder< TNearestTrigger > byDistance( CompareByDistance ); |
|
1701 iNearestTriggers.InsertInOrderAllowRepeats( nTrigger, byDistance ); |
|
1702 } |
|
1703 |
|
1704 |
|
1705 // ----------------------------------------------------------------------------- |
|
1706 // CLbtCoOrdinateSupervisor::EstimateTriggerRadii |
|
1707 // Calculcates the trigger radius and the radius of the hysteresis circle |
|
1708 // ----------------------------------------------------------------------------- |
|
1709 // |
|
1710 CLbtCoOrdinateSupervisor::TTriggerArea CLbtCoOrdinateSupervisor::EstimateTriggerRadii( |
|
1711 TReal aTriggerRadius, TReal aHysteresisRadius, |
|
1712 TReal aPositionAccuracy ) |
|
1713 { |
|
1714 TTriggerArea trgArea; |
|
1715 TReal ratioOfCircularAreas = aPositionAccuracy / aTriggerRadius; |
|
1716 |
|
1717 if( ratioOfCircularAreas >= KCofftOfHighEdgeLimit ) |
|
1718 { |
|
1719 trgArea.triggerRadius = aTriggerRadius; |
|
1720 trgArea.hysteresisRadius = aHysteresisRadius; |
|
1721 } |
|
1722 else |
|
1723 { |
|
1724 // Update radiusOfTrigger and radiusOfHysteresis accordingly |
|
1725 trgArea.triggerRadius = aTriggerRadius +( KAccuracyMultiplier * aPositionAccuracy ); |
|
1726 trgArea.hysteresisRadius = Hysteresis( trgArea.triggerRadius ); |
|
1727 } |
|
1728 |
|
1729 return trgArea; |
|
1730 } |
|
1731 |
|
1732 |
|
1733 // ----------------------------------------------------------------------------- |
|
1734 // CLbtCoOrdinateSupervisor::Hysteresis |
|
1735 // Calculates the hysteresis radius |
|
1736 // ----------------------------------------------------------------------------- |
|
1737 // |
|
1738 TReal CLbtCoOrdinateSupervisor::Hysteresis( TReal aTriggerRadius ) |
|
1739 { |
|
1740 TReal hysteresis; |
|
1741 if( aTriggerRadius > KTriggerRadiusCutoff ) |
|
1742 { |
|
1743 TReal logRadius; |
|
1744 Math::Ln( logRadius, aTriggerRadius / 10 ); |
|
1745 hysteresis = aTriggerRadius / logRadius; |
|
1746 } |
|
1747 else |
|
1748 { |
|
1749 hysteresis = aTriggerRadius / 4; |
|
1750 } |
|
1751 |
|
1752 return hysteresis + aTriggerRadius; |
|
1753 } |
|
1754 |
|
1755 |
|
1756 // ----------------------------------------------------------------------------- |
|
1757 // CLbtCoOrdinateSupervisor::DetermineNearestDistances |
|
1758 // Algorithm to determine the shortest distance |
|
1759 // ----------------------------------------------------------------------------- |
|
1760 // |
|
1761 TInt CLbtCoOrdinateSupervisor::CompareByDistance( const TNearestTrigger& src, |
|
1762 const TNearestTrigger& dst ) |
|
1763 { |
|
1764 if( src.distance > dst.distance ) |
|
1765 { |
|
1766 return 1; |
|
1767 } |
|
1768 else if( src.distance < dst.distance ) |
|
1769 { |
|
1770 return -1; |
|
1771 } |
|
1772 return 0; |
|
1773 } |
|
1774 |
|
1775 |
|
1776 // ----------------------------------------------------------------------------- |
|
1777 // CLbtCoOrdinateSupervisor::CompareByID |
|
1778 // Determine equality of nearest triggers by id |
|
1779 // ----------------------------------------------------------------------------- |
|
1780 // |
|
1781 TBool CLbtCoOrdinateSupervisor::CompareByID( const TNearestTrigger& src, |
|
1782 const TNearestTrigger& dst ) |
|
1783 { |
|
1784 if( src.id > dst.id ) |
|
1785 { |
|
1786 return ETrue; |
|
1787 } |
|
1788 return EFalse; |
|
1789 } |
|
1790 |
|
1791 |
|
1792 // ----------------------------------------------------------------------------- |
|
1793 // CLbtCoOrdinateSupervisor::ResetViewIterator |
|
1794 // Resets trigger view iterator. |
|
1795 // ----------------------------------------------------------------------------- |
|
1796 // |
|
1797 TInt CLbtCoOrdinateSupervisor::ResetViewIterator() |
|
1798 { |
|
1799 FUNC_ENTER("CLbtCoOrdinateSupervisor::ResetViewIterator"); |
|
1800 TInt err = iViewIterator.Reset(); |
|
1801 if( KErrNone != err ) |
|
1802 { |
|
1803 if( KErrNotFound == err ) |
|
1804 { |
|
1805 |
|
1806 // determine update interval |
|
1807 iState = iProjectedState = EIdle; |
|
1808 } |
|
1809 else |
|
1810 { |
|
1811 Term(); |
|
1812 // TODO: Server needs to be notified about termination of supervision |
|
1813 } |
|
1814 return err; |
|
1815 } |
|
1816 |
|
1817 return KErrNone; |
|
1818 } |
|
1819 |
|
1820 |
|
1821 // ----------------------------------------------------------------------------- |
|
1822 // CLbtCoOrdinateSupervisor::RunL |
|
1823 // Inherited from CActive - called when the request issued is completed. |
|
1824 // ----------------------------------------------------------------------------- |
|
1825 // |
|
1826 void CLbtCoOrdinateSupervisor::RunL() |
|
1827 { |
|
1828 FUNC_ENTER("CLbtCoOrdinateSupervisor::RunL"); |
|
1829 switch ( iState ) |
|
1830 { |
|
1831 case ELocationAcquisition: |
|
1832 GetPositionInfoL(); |
|
1833 break; |
|
1834 |
|
1835 case ETriggerEvaluation: |
|
1836 EvaluateTriggersL(); |
|
1837 break; |
|
1838 |
|
1839 case EUpdateIntervalEstimation: |
|
1840 EstimateSleepInterval(); |
|
1841 break; |
|
1842 |
|
1843 case ESleep: |
|
1844 LOG("Wakeup"); |
|
1845 ProcessInterrupt(); |
|
1846 break; |
|
1847 |
|
1848 default: |
|
1849 break; |
|
1850 } |
|
1851 } |
|
1852 |
|
1853 |
|
1854 // ----------------------------------------------------------------------------- |
|
1855 // CLbtCoOrdinateSupervisor::DoCancel |
|
1856 // Inherited from CActive - called to cancel outanding events. |
|
1857 // ----------------------------------------------------------------------------- |
|
1858 // |
|
1859 void CLbtCoOrdinateSupervisor::DoCancel() |
|
1860 { |
|
1861 FUNC_ENTER("CLbtCoOrdinateSupervisor::DoCancel"); |
|
1862 iFixForFiringCloseTriggers = EFalse; |
|
1863 } |
|
1864 |
|
1865 |
|
1866 // ----------------------------------------------------------------------------- |
|
1867 // CLbtCoOrdinateSupervisor::RunError |
|
1868 // Handles the event of leave from the request completion event handler RunL() |
|
1869 // ----------------------------------------------------------------------------- |
|
1870 // |
|
1871 TInt CLbtCoOrdinateSupervisor::RunError( TInt /*aError*/ ) |
|
1872 { |
|
1873 FUNC_ENTER("CLbtCoOrdinateSupervisor::RunError"); |
|
1874 Term(); |
|
1875 return KErrNone; |
|
1876 } |
|
1877 |
|
1878 |
|
1879 // ----------------------------------------------------------------------------- |
|
1880 // CLbtCoOrdinateSupervisor::CLbtCoOrdinateSupervisor |
|
1881 // C++ default constructor. |
|
1882 // ----------------------------------------------------------------------------- |
|
1883 // |
|
1884 CLbtCoOrdinateSupervisor::CLbtCoOrdinateSupervisor() : |
|
1885 CActive( EPriorityHigh ) |
|
1886 { |
|
1887 CActiveScheduler::Add( this ); |
|
1888 } |
|
1889 |
|
1890 |
|
1891 // ----------------------------------------------------------------------------- |
|
1892 // CLbtCoOrdinateSupervisor::ConstructL |
|
1893 // Symbian 2nd phase constructor. |
|
1894 // ----------------------------------------------------------------------------- |
|
1895 // |
|
1896 void CLbtCoOrdinateSupervisor::ConstructL( TAny* /*aConstructionParameters*/, |
|
1897 CLbtTriggerView* aView, |
|
1898 MLbtStrategyEngineObsrvr* aObserver, |
|
1899 CLbtCellChangeHandler* aCellChangeHandler ) |
|
1900 { |
|
1901 iEngObserver = aObserver; |
|
1902 iState = iProjectedState = EIdle; |
|
1903 iEngObserver->RetrieveTriggeringSettings( iSettings ); |
|
1904 iCellChangeHandler = aCellChangeHandler; |
|
1905 |
|
1906 iModuleId = iSettings.iPositioningTechnology; |
|
1907 |
|
1908 iLocationRequestor = CLbtLocationRequestor::NewL(); |
|
1909 |
|
1910 iStatusManager = CLbtStatusManager::NewL(); |
|
1911 iTimer = CLbtStrategyTimer::NewL(); |
|
1912 iView = aView; |
|
1913 |
|
1914 iViewIterator = iView->BeginL( CLbtGeoAreaBase::ECircle ); |
|
1915 iCellIdDatabase = CLbtCellIdDatabase::NewL(); |
|
1916 iLastCellRequestStatus = KErrUnknown; |
|
1917 iLastLocationFixType = EFixUnknown; |
|
1918 iPsyChangeListner = NULL; |
|
1919 iFixForFiringCloseTriggers = EFalse; |
|
1920 } |
|
1921 |
|
1922 |
|
1923 // ----------------------------------------------------------------------------- |
|
1924 // CLbtCoOrdinateSupervisor::SetEvent |
|
1925 // Completes the iRequestStatus with KErrNone. |
|
1926 // ----------------------------------------------------------------------------- |
|
1927 // |
|
1928 void CLbtCoOrdinateSupervisor::SetEvent() |
|
1929 { |
|
1930 if ( !IsActive() ) |
|
1931 { |
|
1932 TRequestStatus* lStatus = &iStatus; |
|
1933 User::RequestComplete( lStatus, KErrNone ); |
|
1934 SetActive(); |
|
1935 } |
|
1936 } |
|
1937 |
|
1938 |
|
1939 // ----------------------------------------------------------------------------- |
|
1940 // CLbtCoOrdinateSupervisor::Term |
|
1941 // |
|
1942 // ----------------------------------------------------------------------------- |
|
1943 // |
|
1944 void CLbtCoOrdinateSupervisor::Term() |
|
1945 { |
|
1946 FUNC_ENTER("CLbtCoOrdinateSupervisor::Term"); |
|
1947 |
|
1948 iSupervisionInitiated = EFalse; |
|
1949 |
|
1950 iView->Cancel(); |
|
1951 switch( iState ) |
|
1952 { |
|
1953 case ELocationAcquisition: |
|
1954 if( iLastLocationFixType == EProperFix ) |
|
1955 { |
|
1956 iLocationRequestor->Cancel(); |
|
1957 } |
|
1958 else |
|
1959 { |
|
1960 iLocationRequestor->CancelFixFromNpp(); |
|
1961 } |
|
1962 break; |
|
1963 |
|
1964 case ESleep: |
|
1965 iTimer->Cancel(); |
|
1966 break; |
|
1967 |
|
1968 default: |
|
1969 Cancel(); |
|
1970 break; |
|
1971 } |
|
1972 |
|
1973 iState = iProjectedState = EIdle; |
|
1974 iLastLocationFixType = EFixUnknown; |
|
1975 iFixForFiringCloseTriggers = EFalse; |
|
1976 } |
|
1977 |
|
1978 // ----------------------------------------------------------------------------- |
|
1979 // CLbtCoOrdinateSupervisor::FireClosestTriggers |
|
1980 // |
|
1981 // ----------------------------------------------------------------------------- |
|
1982 // |
|
1983 void CLbtCoOrdinateSupervisor::FireClosestTriggers() |
|
1984 { |
|
1985 FUNC_ENTER("CLbtCoOrdinateSupervisor::FireClosestTriggers"); |
|
1986 LOG1("NT Count = %d", iNearestTriggers.Count()); |
|
1987 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1988 { |
|
1989 if(iNearestTriggers[i].remRearmTime != 0) |
|
1990 { |
|
1991 continue; |
|
1992 } |
|
1993 |
|
1994 TInt timeToTrigger = (iNearestTriggers[i].distance / iEstimatedUserSpeed); |
|
1995 |
|
1996 TInt estimatedInterval = timeToTrigger - iProcessingInterval; |
|
1997 |
|
1998 LOG1("estimatedInterval = %d", estimatedInterval); |
|
1999 |
|
2000 if( estimatedInterval <= KMinSleepInterval ) |
|
2001 { |
|
2002 LOG("NEED TO FIRE"); |
|
2003 CLbtContainerTriggerEntry* trigger; |
|
2004 if( iView->GetTriggerByID( iNearestTriggers[i].id,trigger ) ) |
|
2005 { |
|
2006 LOGSTRING("Trigger: \"%S\" ", &(trigger->TriggerEntry()->Name())); |
|
2007 // check the activity status |
|
2008 TStrategyData strategyData = trigger->StrategyData(); |
|
2009 if( strategyData.iActivityStatus == EActive ) |
|
2010 { |
|
2011 // Fire the trigger |
|
2012 TLbtTriggerDataMask dataMask = 0; |
|
2013 |
|
2014 // Set trigger state to fired |
|
2015 trigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue ); |
|
2016 TLbtTriggerFireInfo triggerFireInfo; |
|
2017 TPositionInfo positionInfo; |
|
2018 triggerFireInfo.iTriggerId = trigger->TriggerEntry()->Id(); |
|
2019 triggerFireInfo.iFiredPositionInfo = iPrevPosInfo; |
|
2020 |
|
2021 trigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo ); |
|
2022 |
|
2023 // Time at which trigger fired |
|
2024 TTime triggerFiredTime; |
|
2025 triggerFiredTime.UniversalTime(); |
|
2026 LOG("NEAREST TRIGGER FIRED"); |
|
2027 |
|
2028 strategyData.iFireTime = triggerFiredTime.Int64(); |
|
2029 // Set trigger to inactive state |
|
2030 strategyData.iActivityStatus = EInactive; |
|
2031 |
|
2032 dataMask |= |
|
2033 CLbtContainerTriggerEntry::EContainerAttributeIsFired | |
|
2034 CLbtContainerTriggerEntry::EContainerAttributeFireInfo ; |
|
2035 |
|
2036 iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, trigger, dataMask ); |
|
2037 trigger->SetStrategyData( strategyData ); |
|
2038 } |
|
2039 } |
|
2040 else |
|
2041 { |
|
2042 LOG("TRIGGER NOT FOUND ??"); |
|
2043 } |
|
2044 } |
|
2045 else |
|
2046 { |
|
2047 LOG("ELSE"); |
|
2048 // Since the array is in the ascending order of distance( which is directly proportional to time ), |
|
2049 // we can need not search rest of the array. |
|
2050 break; |
|
2051 } |
|
2052 } |
|
2053 } |
|
2054 |
|
2055 // ----------------------------------------------------------------------------- |
|
2056 // CLbtCoOrdinateSupervisor::CalculateTolerableRadius |
|
2057 // |
|
2058 // ----------------------------------------------------------------------------- |
|
2059 // |
|
2060 TReal CLbtCoOrdinateSupervisor::CalculateTolerableRadius( TReal aRadius ) |
|
2061 { |
|
2062 // Tolerance can be calculated using the straight line equation. Slope of straight line is 0.07 and |
|
2063 // intercept is 22.2 |
|
2064 TReal tolerableInaccuracy = ( 0.07 * aRadius ) + 22.2; |
|
2065 return ( tolerableInaccuracy + aRadius ); |
|
2066 } |
|
2067 |
|
2068 // ----------------------------------------------------------------------------- |
|
2069 // CLbtCoOrdinateSupervisor::HandleCellChangeEvent |
|
2070 // |
|
2071 // ----------------------------------------------------------------------------- |
|
2072 // |
|
2073 void CLbtCoOrdinateSupervisor::HandleCellChangeEvent( |
|
2074 const TInt aStatus, |
|
2075 const RMobilePhone::TMobilePhoneNetworkInfoV1& aNwInfo, |
|
2076 const RMobilePhone::TMobilePhoneLocationAreaV1& aLocArea) |
|
2077 { |
|
2078 FUNC_ENTER("CLbtCoOrdinateSupervisor::HandleCellChangeEvent"); |
|
2079 if( KErrNone == aStatus ) |
|
2080 { |
|
2081 // validate network info |
|
2082 if (aNwInfo.iMode == RMobilePhone::ENetworkModeGsm || |
|
2083 aNwInfo.iMode == RMobilePhone::ENetworkModeWcdma) |
|
2084 { |
|
2085 TLex lex( aNwInfo.iCountryCode ); |
|
2086 TInt countryCode,networkCode; |
|
2087 lex.Val( countryCode ); |
|
2088 if( countryCode ) |
|
2089 { |
|
2090 lex.Assign( aNwInfo.iNetworkId ); |
|
2091 lex.Val( networkCode ); |
|
2092 if( networkCode ) |
|
2093 { |
|
2094 if( aLocArea.iLocationAreaCode && aLocArea.iCellId ) |
|
2095 { |
|
2096 iLastCellRequestStatus = KErrNone; |
|
2097 iNwInfo = aNwInfo; |
|
2098 iLocArea = aLocArea; |
|
2099 } |
|
2100 } |
|
2101 } |
|
2102 } |
|
2103 } |
|
2104 else |
|
2105 { |
|
2106 iLastCellRequestStatus = aStatus; |
|
2107 } |
|
2108 } |
|
2109 |
|
2110 // ----------------------------------------------------------------------------- |
|
2111 // CLbtCoOrdinateSupervisor::HandlePsyChangeEvent |
|
2112 // |
|
2113 // ----------------------------------------------------------------------------- |
|
2114 // |
|
2115 void CLbtCoOrdinateSupervisor::HandlePsyChangeEvent( TPositionModuleId aModuleId ) |
|
2116 { |
|
2117 LOG("CLbtCoOrdinateSupervisor::HandlePsyChangeEvent"); |
|
2118 if( aModuleId == iSettings.iPositioningTechnology ) |
|
2119 { |
|
2120 LOG("aModuleId == iSettings.iPositioningTechnology"); |
|
2121 iModuleId = aModuleId; |
|
2122 delete iPsyChangeListner; |
|
2123 iPsyChangeListner = NULL; |
|
2124 } |
|
2125 else |
|
2126 { |
|
2127 LOG("aModuleId != iSettings.iPositioningTechnology"); |
|
2128 // We will use defualt proxy |
|
2129 iModuleId = TUid::Uid(0xFFFFFFFF); |
|
2130 iPsyChangeListner->StartToListen( iSettings.iPositioningTechnology ); |
|
2131 } |
|
2132 |
|
2133 // If coordinate supervisor AO is not active,request terminal position |
|
2134 if( !IsActive() ) |
|
2135 { |
|
2136 RequestTerminalPosition( iSettings.iLocationRequestTimeout,EProperFix ); |
|
2137 } |
|
2138 } |
|
2139 // end of file |