|
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 TPosition currentPosition; |
|
442 iPosInfo.GetPosition( currentPosition ); |
|
443 LOG("Received KPositionQualityLoss"); |
|
444 LOG1("Lat:%f",currentPosition.Latitude()); |
|
445 LOG1("Long:%f",currentPosition.Longitude()); |
|
446 LOG1("HA:%f",currentPosition.HorizontalAccuracy()); |
|
447 } |
|
448 |
|
449 iStatusManager->ReportLocationAcquisitionStatus( KErrNone ); |
|
450 // The fix was taken to fire nearest triggers then reset the flag |
|
451 // to EFalse since the fix was successful and the nearest triggers will be |
|
452 // evaluated and will be fired |
|
453 if(iFixForFiringCloseTriggers) |
|
454 { |
|
455 iFixForFiringCloseTriggers = EFalse; |
|
456 } |
|
457 |
|
458 TPosition currentPosition, prevPosition; |
|
459 iPosInfo.GetPosition( currentPosition ); |
|
460 iPrevPosInfo.GetPosition( prevPosition ); |
|
461 |
|
462 if( Math::IsNaN( currentPosition.Latitude() ) || |
|
463 Math::IsNaN( currentPosition.Longitude() ) ) |
|
464 { |
|
465 LOG("ERROR:Lat/Long is Nan. Sleep now"); |
|
466 iState = ESleep; |
|
467 iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue ); |
|
468 SetActive(); |
|
469 |
|
470 if( KErrAccessDenied == iStatus.Int() ) |
|
471 { |
|
472 iAcquisitionStatus = ELocationAcquisitionPrivacyReject; |
|
473 } |
|
474 else |
|
475 { |
|
476 iAcquisitionStatus = ELocationAcquisitionFailure; |
|
477 } |
|
478 return; |
|
479 } |
|
480 |
|
481 // Record the time at which we got the fix |
|
482 iLastFixTime.UniversalTime(); |
|
483 |
|
484 // Take note of reference time that would be used during estimation of |
|
485 // sleep interval |
|
486 iAcquisitionStatus = ELocationAcquisitionActive; |
|
487 |
|
488 iLocReqCount++; |
|
489 iLocationRequestor->GetModuleInfo( iPosInfo.ModuleId() ); |
|
490 |
|
491 if( iLocArea.iCellId && iLastCellRequestStatus == KErrNone ) |
|
492 { |
|
493 LOG("Writing position to DB"); |
|
494 LOG1("Cell Id = %d", iLocArea.iCellId ); |
|
495 LOG1("LAC = %d", iLocArea.iLocationAreaCode ); |
|
496 // Add current cell id position to cell-id database |
|
497 TInt countryCode,networkCode; |
|
498 |
|
499 TLex lex( iNwInfo.iCountryCode ); |
|
500 lex.Val( countryCode ); |
|
501 |
|
502 lex.Assign( iNwInfo.iNetworkId ); |
|
503 lex.Val( networkCode ); |
|
504 |
|
505 TPosition cellPosition; |
|
506 iPosInfo.GetPosition( cellPosition ); |
|
507 if( iLastLocationFixType == EProperFix ) |
|
508 { |
|
509 cellPosition.SetHorizontalAccuracy( 3000 ); |
|
510 } |
|
511 |
|
512 iCellIdDatabase->InsertCidLocation( countryCode, |
|
513 networkCode, |
|
514 iLocArea.iLocationAreaCode, |
|
515 iLocArea.iCellId, |
|
516 cellPosition ); |
|
517 } |
|
518 |
|
519 // Check if there is no movement from last location fix. If true then |
|
520 // re-evaluate sleep interval |
|
521 TReal32 dist; |
|
522 currentPosition.Distance( prevPosition, dist ); |
|
523 if( dist == 0 ) |
|
524 { |
|
525 iState = EUpdateIntervalEstimation; |
|
526 SetEvent(); |
|
527 } |
|
528 |
|
529 LOG1("Lat:%f",currentPosition.Latitude()); |
|
530 LOG1("Long:%f",currentPosition.Longitude()); |
|
531 LOG1("HA:%f",currentPosition.HorizontalAccuracy()); |
|
532 |
|
533 // Switch to idle state as refresh is an async operation. Set projected |
|
534 // state to trigger evaluation which will commence once the refresh |
|
535 // operation is complete |
|
536 iState = ETriggerEvaluation; |
|
537 SetEvent(); |
|
538 |
|
539 } |
|
540 |
|
541 |
|
542 // ----------------------------------------------------------------------------- |
|
543 // CLbtCoOrdinateSupervisor::EvaluateTriggersL |
|
544 // Evaluates triggers based on the location information obtained |
|
545 // ----------------------------------------------------------------------------- |
|
546 // |
|
547 void CLbtCoOrdinateSupervisor::EvaluateTriggersL() |
|
548 { |
|
549 FUNC_ENTER("CLbtCoOrdinateSupervisor::EvaluateTriggersL"); |
|
550 |
|
551 // Reset nearest trigger array |
|
552 iNearestTriggers.Reset(); |
|
553 |
|
554 // TODO: In case of updates to trigger information do not change state |
|
555 // else change state to EUpdateIntervalEstimation |
|
556 CLbtContainerTriggerEntry* conTrigger; |
|
557 |
|
558 // ResetViewIterator will switch state to Idle if there are no triggers in |
|
559 // the system |
|
560 if( KErrNone != ResetViewIterator() ) |
|
561 { |
|
562 return; |
|
563 } |
|
564 |
|
565 while( iViewIterator.NextL( conTrigger ) ) |
|
566 { |
|
567 if( conTrigger ) |
|
568 { |
|
569 CLbtTriggerEntry* trigger = conTrigger->TriggerEntry(); |
|
570 if( CLbtTriggerConditionBase::ETriggerConditionArea == |
|
571 trigger->GetCondition()->Type() ) |
|
572 { |
|
573 // Area type trigger |
|
574 CLbtTriggerConditionArea* triggerConArea = |
|
575 static_cast< CLbtTriggerConditionArea* > |
|
576 ( trigger->GetCondition() ); |
|
577 |
|
578 switch( triggerConArea->TriggerArea()->Type() ) |
|
579 { |
|
580 // Circular area |
|
581 case CLbtGeoAreaBase::ECircle: |
|
582 { |
|
583 if( iLastLocationFixType == EProperFix ) |
|
584 { |
|
585 EvalCircularTriggerL( conTrigger ); |
|
586 } |
|
587 else if( iLastLocationFixType == EFixFromDb || iLastLocationFixType == EFixFromNpp ) |
|
588 { |
|
589 if( EvalCircularTriggerBasedOnCellPositionL( conTrigger ) ) |
|
590 { |
|
591 if( iLastLocationFixType == EFixFromNpp ) |
|
592 { |
|
593 // Fix is taken from NPP only when Proper Fix fails. Now we should |
|
594 // sleep for location acquisition failure time our period since there is no point |
|
595 // in attempting another proper fix |
|
596 iState = ESleep; |
|
597 iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue ); |
|
598 SetActive(); |
|
599 |
|
600 if( KErrAccessDenied == iStatus.Int() ) |
|
601 { |
|
602 iAcquisitionStatus = ELocationAcquisitionPrivacyReject; |
|
603 } |
|
604 else |
|
605 { |
|
606 iAcquisitionStatus = ELocationAcquisitionFailure; |
|
607 } |
|
608 } |
|
609 else |
|
610 { |
|
611 RequestTerminalPosition( iSettings.iLocationRequestTimeout,EProperFix ); |
|
612 } |
|
613 return; |
|
614 } |
|
615 } |
|
616 break; |
|
617 } |
|
618 default: |
|
619 break; |
|
620 } |
|
621 } |
|
622 } |
|
623 } |
|
624 |
|
625 // Update supervision dynamic info to the strategy class |
|
626 TLbtStrategySupervisionDynamicInfo supervisionDynamicInfo; |
|
627 if( iNearestTriggers.Count() ) |
|
628 { |
|
629 supervisionDynamicInfo.iDistanceToNearestTrigger = iNearestTriggers[0].distance; |
|
630 supervisionDynamicInfo.iNearestTriggerId = iNearestTriggers[0].id; |
|
631 } |
|
632 supervisionDynamicInfo.iLatestAcquiredPosInfo = iPosInfo; |
|
633 supervisionDynamicInfo.iLocationAcquisitionStatus = iAcquisitionStatus; |
|
634 |
|
635 |
|
636 iEngObserver->ReportTriggeringSupervisionStatus( supervisionDynamicInfo ); |
|
637 |
|
638 iState = EUpdateIntervalEstimation; |
|
639 SetEvent(); |
|
640 } |
|
641 |
|
642 |
|
643 // ----------------------------------------------------------------------------- |
|
644 // CLbtCoOrdinateSupervisor::EvaluateTriggers |
|
645 // Evaluates triggers based on the location information obtained |
|
646 // ----------------------------------------------------------------------------- |
|
647 // |
|
648 TBool CLbtCoOrdinateSupervisor::EvaluateModifiedTriggersL() |
|
649 { |
|
650 FUNC_ENTER("CLbtCoOrdinateSupervisor::EvaluateModifiedTriggersL"); |
|
651 |
|
652 // Retrieve modified trigger list from trigger view to be supervised |
|
653 RArray< TLbtTriggerId > modifiedTriggers; |
|
654 iView->GetModifiedTriggers( modifiedTriggers ); |
|
655 CleanupClosePushL( modifiedTriggers ); |
|
656 if( modifiedTriggers.Count() ) |
|
657 { |
|
658 // TODO: Need to check for the deletion of |
|
659 // Create an iterator to parse through the modified trigger list |
|
660 CLbtTriggerView::TTriggerViewIter iter = iView->Begin( &modifiedTriggers, CLbtGeoAreaBase::ECircle ); |
|
661 |
|
662 CLbtContainerTriggerEntry* conTrigger; |
|
663 while( iter.NextL( conTrigger ) ) |
|
664 { |
|
665 if( conTrigger ) |
|
666 { |
|
667 CLbtTriggerEntry* trigger = conTrigger->TriggerEntry(); |
|
668 if( CLbtTriggerConditionBase::ETriggerConditionArea == |
|
669 trigger->GetCondition()->Type() ) |
|
670 { |
|
671 // Area type trigger |
|
672 CLbtTriggerConditionArea* triggerConArea = |
|
673 static_cast< CLbtTriggerConditionArea* > |
|
674 ( trigger->GetCondition() ); |
|
675 |
|
676 switch( triggerConArea->TriggerArea()->Type() ) |
|
677 { |
|
678 // Circular area |
|
679 case CLbtGeoAreaBase::ECircle: |
|
680 if( iLastLocationFixType == EProperFix ) |
|
681 { |
|
682 EvalCircularTriggerL( conTrigger ); |
|
683 } |
|
684 else if( iLastLocationFixType == EFixFromDb || iLastLocationFixType == EFixFromNpp ) |
|
685 { |
|
686 if( EvalCircularTriggerBasedOnCellPositionL( conTrigger ) ) |
|
687 { |
|
688 CleanupStack::PopAndDestroy(); // modifiedTriggers |
|
689 return ETrue; |
|
690 } |
|
691 } |
|
692 break; |
|
693 |
|
694 default: |
|
695 break; |
|
696 } |
|
697 } |
|
698 } |
|
699 } |
|
700 } |
|
701 |
|
702 CleanupStack::PopAndDestroy(); // modifiedTriggers |
|
703 return EFalse; |
|
704 } |
|
705 |
|
706 |
|
707 // ----------------------------------------------------------------------------- |
|
708 // CLbtCoOrdinateSupervisor::EvalCircularTrigger |
|
709 // Evaluates triggers with circular area definition |
|
710 // ----------------------------------------------------------------------------- |
|
711 // |
|
712 void CLbtCoOrdinateSupervisor::EvalCircularTriggerL( |
|
713 CLbtContainerTriggerEntry* aTrigger ) |
|
714 { |
|
715 FUNC_ENTER("CLbtCoOrdinateSupervisor::EvalCircularTrigger"); |
|
716 |
|
717 |
|
718 // Extract strategy data |
|
719 TStrategyData strategyData = aTrigger->StrategyData(); |
|
720 |
|
721 TInt remRearmTime = 0; |
|
722 TReal distanceToLatestLocation = 0.0; |
|
723 TBool hasRearmTimeExpired = ETrue; |
|
724 |
|
725 LOGSTRING("Trigger: \"%S\" ", &(aTrigger->TriggerEntry()->Name())); |
|
726 |
|
727 if( strategyData.iFireTime ) |
|
728 { |
|
729 TTime triggerFiredTime( strategyData.iFireTime ); |
|
730 |
|
731 TTime currentTime; |
|
732 currentTime.UniversalTime(); |
|
733 |
|
734 TTimeIntervalSeconds interval; |
|
735 currentTime.SecondsFrom( triggerFiredTime, interval ); |
|
736 |
|
737 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm() - interval.Int(); |
|
738 |
|
739 |
|
740 if( remRearmTime <= 0 ) |
|
741 { |
|
742 remRearmTime = 0; |
|
743 strategyData.iFireTime = 0; |
|
744 } |
|
745 else |
|
746 { |
|
747 LOG("Rearm Time has not expired"); |
|
748 hasRearmTimeExpired = EFalse; |
|
749 } |
|
750 } |
|
751 |
|
752 CLbtTriggerConditionArea* trgCondition = |
|
753 static_cast< CLbtTriggerConditionArea* > |
|
754 ( ( aTrigger->TriggerEntry() )->GetCondition() ); |
|
755 |
|
756 CLbtGeoCircle* circularArea = static_cast< CLbtGeoCircle* > |
|
757 ( trgCondition->TriggerArea() ); |
|
758 |
|
759 // Calculate distance of trigger from current location |
|
760 TReal32 distanceToCenter; |
|
761 TPosition currentPosition; |
|
762 iPosInfo.GetPosition( currentPosition ); |
|
763 TInt err = currentPosition.Distance( circularArea->Center(), |
|
764 distanceToCenter ); |
|
765 if( KErrNone != err ) |
|
766 { |
|
767 ERROR("Error in calculating distance:%d",err); |
|
768 LOG1("Current Lat:%f",currentPosition.Latitude()); |
|
769 LOG1("Current Long:%f",currentPosition.Longitude()); |
|
770 LOG1("Trigger Lat:%f",circularArea->Center().Latitude()); |
|
771 LOG1("Trigger Long:%f",circularArea->Center().Longitude()); |
|
772 return; |
|
773 } |
|
774 |
|
775 // Determine trigger radius and hysteresis radius to be used for supervision |
|
776 // based on the accuracy of location fix |
|
777 TTriggerArea triggerArea; |
|
778 TReal positionAccuracy = currentPosition.HorizontalAccuracy(); |
|
779 triggerArea = EstimateTriggerRadii( circularArea->Radius(), |
|
780 aTrigger->ExtendedTriggerInfo()->HysteresisRadius(), |
|
781 positionAccuracy ); |
|
782 |
|
783 // ENTRY Trigger |
|
784 // Determine current position of terminal relative to the trigger area and |
|
785 // set trigger fire status accordingly |
|
786 if( CLbtTriggerConditionArea::EFireOnEnter == trgCondition->Direction() ) |
|
787 { |
|
788 TLbtTriggerDataMask dataMask = 0; |
|
789 |
|
790 TReal tolerableRadius = CalculateTolerableRadius( triggerArea.triggerRadius ); |
|
791 // Terminal is inside trigger area |
|
792 if( ( distanceToCenter < tolerableRadius ) && |
|
793 ( ( distanceToCenter + positionAccuracy ) <= triggerArea.hysteresisRadius ) ) |
|
794 { |
|
795 LOG("Inside triggerin area"); |
|
796 // If trigger in active state then fire trigger and set state to |
|
797 // inactive. If trigger is inactive nothing is to be done other |
|
798 // than calculating its distance from the hysteresis boundary |
|
799 if( EActive == strategyData.iActivityStatus ) |
|
800 { |
|
801 LOG("Active trigger"); |
|
802 // Check FireOnCreation flag here. If EFalse then dont |
|
803 // fire the trigger. Instead only change the activity |
|
804 // status. |
|
805 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() && |
|
806 hasRearmTimeExpired ) |
|
807 { |
|
808 // Set trigger state to fired |
|
809 aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue ); |
|
810 TLbtTriggerFireInfo triggerFireInfo; |
|
811 TPositionInfo positionInfo; |
|
812 triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id(); |
|
813 triggerFireInfo.iFiredPositionInfo = iPosInfo; |
|
814 |
|
815 aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo ); |
|
816 |
|
817 // Time at which trigger fired |
|
818 TTime triggerFiredTime; |
|
819 triggerFiredTime.UniversalTime(); |
|
820 LOG("TRIGGER FIRED"); |
|
821 |
|
822 strategyData.iFireTime = triggerFiredTime.Int64(); |
|
823 |
|
824 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm(); |
|
825 dataMask |= |
|
826 CLbtContainerTriggerEntry::EContainerAttributeIsFired | |
|
827 CLbtContainerTriggerEntry::EContainerAttributeFireInfo ; |
|
828 } |
|
829 |
|
830 // Set trigger to inactive state |
|
831 strategyData.iActivityStatus = EInactive; |
|
832 } |
|
833 |
|
834 // Calculate distance to current location and update trigger's |
|
835 // dynamic info. This distance is (rH - D) where D is the distance |
|
836 // between the two centers and rH is the radius of the hysteresis |
|
837 // circle. Here the radius of hysteresis boundary is considered for |
|
838 // distance calculation as this trigger would undergo a state |
|
839 // change only when it crosses the hysteresis area |
|
840 distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter ); |
|
841 } |
|
842 |
|
843 // Terminal is outside hysteresis area |
|
844 else if( distanceToCenter > ( triggerArea.hysteresisRadius + positionAccuracy ) ) |
|
845 { |
|
846 if( EInactive == strategyData.iActivityStatus ) |
|
847 { |
|
848 // Reset trigger state to valid |
|
849 strategyData.iActivityStatus = EActive; |
|
850 LOG("Trigger activated"); |
|
851 } |
|
852 |
|
853 // Calculate distance of trigger to current location and update |
|
854 // trigger's dynamic info. This distance is (D - rT) where D is |
|
855 // the distance between two centers and rT is the radius of trigger. |
|
856 // State change will occur only when the terminal moves beyond the |
|
857 // boundary of the trigger |
|
858 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius ); |
|
859 } |
|
860 |
|
861 // Terminal is inside hysteresis area. |
|
862 else |
|
863 { |
|
864 // Trigger does not undergo any state change in this region. Theres |
|
865 // only distance to be determined here |
|
866 if( EActive == strategyData.iActivityStatus ) |
|
867 { |
|
868 // Terminal was outside hysteresis area earlier. Distance is |
|
869 // therefore (D - rT) |
|
870 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius ); |
|
871 } |
|
872 else |
|
873 { |
|
874 // Terminal was inside trigger area earlier. Distance is |
|
875 // therefore (rH - D) |
|
876 distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter ); |
|
877 } |
|
878 } |
|
879 |
|
880 // Set FireOnCreation flag to ETrue here if its not already |
|
881 // ETrue. This is done to ensure that the trigger is fired |
|
882 // in the subsequent iterations if the triggering conditions |
|
883 // are satisfied. |
|
884 if( !aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() ) |
|
885 { |
|
886 aTrigger->ExtendedTriggerInfo()->SetTriggerFireOnCreation( ETrue ); |
|
887 dataMask |= CLbtContainerTriggerEntry::EContainerAttributeIsTriggerFireOnCreation; |
|
888 } |
|
889 |
|
890 if( dataMask ) |
|
891 { |
|
892 iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, aTrigger, dataMask ); |
|
893 } |
|
894 } |
|
895 |
|
896 // EXIT Trigger |
|
897 else |
|
898 { |
|
899 TLbtTriggerDataMask dataMask = 0; |
|
900 // Retrieve boundary information of trigger |
|
901 TTriggerBoundary boundary = EUndefined; |
|
902 |
|
903 // Retrieve boundary information of trigger |
|
904 ( strategyData.iBoundaryCondition >= 0 && strategyData.iBoundaryCondition <= 2 )?boundary = |
|
905 TTriggerBoundary( strategyData.iBoundaryCondition ):boundary; |
|
906 |
|
907 TReal tolerableRadius = CalculateTolerableRadius( triggerArea.triggerRadius ); |
|
908 |
|
909 // Terminal is inside trigger area |
|
910 if( ( distanceToCenter < tolerableRadius ) && |
|
911 ( ( distanceToCenter + positionAccuracy ) <= triggerArea.hysteresisRadius ) ) |
|
912 { |
|
913 // Check boundary condition to determine if the terminal has moved |
|
914 // inside the trigger area without having gone beyond the area of |
|
915 // hysteresis. In this case the trigger shall not be set as active |
|
916 if( EOutside != boundary && |
|
917 EInactive == strategyData.iActivityStatus ) |
|
918 { |
|
919 // Set trigger state to active |
|
920 strategyData.iActivityStatus = EActive; |
|
921 } |
|
922 |
|
923 // Set boundary as Outside |
|
924 strategyData.iBoundaryCondition = TInt( EOutside ); |
|
925 |
|
926 if( EActive == strategyData.iActivityStatus ) |
|
927 { |
|
928 // Set Distance to the border of trigger area. This distance is |
|
929 // (rT - D). |
|
930 distanceToLatestLocation = Abs( triggerArea.triggerRadius - distanceToCenter ); |
|
931 } |
|
932 else |
|
933 { |
|
934 // Set distance to border of hysteresis area. This distance is |
|
935 // (rH - D) where rH is the radius of hysteresis and D is the |
|
936 // distance between the center of trigger and the center of |
|
937 // location |
|
938 distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter ); |
|
939 } |
|
940 } |
|
941 |
|
942 // Terminal is outside hysteresis area |
|
943 else if( ( distanceToCenter > triggerArea.hysteresisRadius ) && |
|
944 ( distanceToCenter > ( triggerArea.triggerRadius + positionAccuracy ) ) ) |
|
945 { |
|
946 if( EActive == strategyData.iActivityStatus ) |
|
947 { |
|
948 // Check FireOnCreation flag here. If EFalse then dont |
|
949 // fire the trigger. Instead only change the activity |
|
950 // status. |
|
951 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() && |
|
952 hasRearmTimeExpired ) |
|
953 { |
|
954 // Set trigger state to fired |
|
955 aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue ); |
|
956 |
|
957 TLbtTriggerFireInfo triggerFireInfo; |
|
958 TPositionInfo positionInfo; |
|
959 triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id(); |
|
960 triggerFireInfo.iFiredPositionInfo = iPosInfo; |
|
961 |
|
962 aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo ); |
|
963 |
|
964 // Time at which trigger fired |
|
965 TTime triggerFiredTime; |
|
966 triggerFiredTime.UniversalTime(); |
|
967 strategyData.iFireTime = triggerFiredTime.Int64(); |
|
968 LOG("TRIGGER FIRED"); |
|
969 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm(); |
|
970 dataMask |= |
|
971 CLbtContainerTriggerEntry::EContainerAttributeIsFired | |
|
972 CLbtContainerTriggerEntry::EContainerAttributeFireInfo; |
|
973 } |
|
974 |
|
975 // Set the trigger state to inactive |
|
976 strategyData.iActivityStatus = EInactive; |
|
977 |
|
978 } |
|
979 |
|
980 // Set boundary as Inside |
|
981 strategyData.iBoundaryCondition = TInt( EInside ); |
|
982 |
|
983 // Calculate distance to border of trigger area. This distance |
|
984 // is (D - rT) |
|
985 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius ); |
|
986 } |
|
987 |
|
988 // Terminal is inside hysteresis area |
|
989 else |
|
990 { |
|
991 if( EOutside == boundary && EActive == strategyData.iActivityStatus ) |
|
992 { |
|
993 // Check FireOnCreation flag here. If EFalse then dont |
|
994 // fire the trigger. Instead only change the activity |
|
995 // status. |
|
996 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() ) |
|
997 { |
|
998 // Set trigger state to fired |
|
999 aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue ); |
|
1000 TLbtTriggerFireInfo triggerFireInfo; |
|
1001 TPositionInfo positionInfo; |
|
1002 triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id(); |
|
1003 triggerFireInfo.iFiredPositionInfo = iPosInfo; |
|
1004 |
|
1005 aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo ); |
|
1006 |
|
1007 // Time at which trigger fired |
|
1008 TTime triggerFiredTime; |
|
1009 triggerFiredTime.UniversalTime(); |
|
1010 |
|
1011 strategyData.iFireTime = triggerFiredTime.Int64(); |
|
1012 strategyData.iBoundaryCondition = TInt( EOutside ); |
|
1013 |
|
1014 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm(); |
|
1015 dataMask |= |
|
1016 CLbtContainerTriggerEntry::EContainerAttributeIsFired | |
|
1017 CLbtContainerTriggerEntry::EContainerAttributeFireInfo; |
|
1018 } |
|
1019 |
|
1020 // Set the trigger state to inactive |
|
1021 strategyData.iActivityStatus = EInactive; |
|
1022 } |
|
1023 |
|
1024 if( EOutside != boundary ) |
|
1025 { |
|
1026 // Set the trigger state to inactive. This is done here because |
|
1027 // if a trigger was newly created (state is active) and it is |
|
1028 // found to be within hysteresis area, then the activity status |
|
1029 // needs to be set to inactive to enable the trigger to be |
|
1030 // handled appropriately when terminal moves inside trigger |
|
1031 // area. |
|
1032 strategyData.iActivityStatus = EInactive; |
|
1033 // Calclulate distance to border of trigger area. This |
|
1034 // distance is (D - rT) |
|
1035 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius ); |
|
1036 } |
|
1037 else |
|
1038 { |
|
1039 // Calculate distance to the boundary of hysteresis. This |
|
1040 // distance is (rH - D) |
|
1041 distanceToLatestLocation = |
|
1042 Abs( triggerArea.hysteresisRadius - distanceToCenter ); |
|
1043 } |
|
1044 } |
|
1045 |
|
1046 // Set FireOnCreation flag to ETrue here if its not already |
|
1047 // ETrue. This is done to ensure that the trigger is fired |
|
1048 // in the subsequent iterations if the triggering conditions |
|
1049 // are satisfied. |
|
1050 if( !aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() ) |
|
1051 { |
|
1052 aTrigger->ExtendedTriggerInfo()->SetTriggerFireOnCreation( ETrue ); |
|
1053 dataMask |= CLbtContainerTriggerEntry::EContainerAttributeIsTriggerFireOnCreation; |
|
1054 } |
|
1055 |
|
1056 if( dataMask ) |
|
1057 { |
|
1058 iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, aTrigger, dataMask ); |
|
1059 } |
|
1060 } |
|
1061 aTrigger->SetStrategyData( strategyData ); |
|
1062 UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation , remRearmTime ); |
|
1063 LOG1("DistToTrig:%f",distanceToLatestLocation ); |
|
1064 } |
|
1065 |
|
1066 |
|
1067 // ----------------------------------------------------------------------------- |
|
1068 // CLbtCoOrdinateSupervisor::EvalCircularTriggerBasedOnCellPosition |
|
1069 // Evaluates triggers with circular area definition |
|
1070 // ----------------------------------------------------------------------------- |
|
1071 // |
|
1072 TBool CLbtCoOrdinateSupervisor::EvalCircularTriggerBasedOnCellPositionL( |
|
1073 CLbtContainerTriggerEntry* aTrigger ) |
|
1074 { |
|
1075 TTime currentTime; |
|
1076 currentTime.UniversalTime(); |
|
1077 |
|
1078 CLbtTriggerConditionArea* trgCondition = |
|
1079 static_cast< CLbtTriggerConditionArea* > |
|
1080 ( ( aTrigger->TriggerEntry() )->GetCondition() ); |
|
1081 |
|
1082 // Extract strategy data |
|
1083 TStrategyData strategyData = aTrigger->StrategyData(); |
|
1084 |
|
1085 TInt remRearmTime = 0; |
|
1086 TReal distanceToLatestLocation = 0.0; |
|
1087 |
|
1088 if( strategyData.iFireTime ) |
|
1089 { |
|
1090 TTime triggerFiredTime( strategyData.iFireTime ); |
|
1091 |
|
1092 TTimeIntervalSeconds interval; |
|
1093 currentTime.SecondsFrom( triggerFiredTime, interval ); |
|
1094 |
|
1095 remRearmTime = aTrigger->TriggerEntry()->TimeToRearm() - interval.Int(); |
|
1096 |
|
1097 if( remRearmTime <= 0 ) |
|
1098 { |
|
1099 remRearmTime = 0; |
|
1100 strategyData.iFireTime = 0; |
|
1101 aTrigger->SetStrategyData( strategyData ); |
|
1102 } |
|
1103 } |
|
1104 |
|
1105 |
|
1106 TPosition currentPosition; |
|
1107 iPosInfo.GetPosition( currentPosition ); |
|
1108 TReal positionAccuracy = currentPosition.HorizontalAccuracy(); |
|
1109 |
|
1110 CLbtGeoCircle* circularArea = static_cast< CLbtGeoCircle* > |
|
1111 ( trgCondition->TriggerArea() ); |
|
1112 |
|
1113 TReal32 distanceToCenter; |
|
1114 TInt err = currentPosition.Distance( circularArea->Center(), |
|
1115 distanceToCenter ); |
|
1116 if( err!=KErrNone ) |
|
1117 { |
|
1118 return ETrue; |
|
1119 } |
|
1120 |
|
1121 // If the trigger is entry type,we calculate distance to the hysterisis radius |
|
1122 if( CLbtTriggerConditionArea::EFireOnEnter == trgCondition->Direction() ) |
|
1123 { |
|
1124 distanceToLatestLocation = distanceToCenter - |
|
1125 ( positionAccuracy+aTrigger->ExtendedTriggerInfo()->HysteresisRadius()); |
|
1126 |
|
1127 if( distanceToLatestLocation < 0 && (remRearmTime == 0) ) |
|
1128 { |
|
1129 // Request fix using any of the available psy |
|
1130 LOG("Request Proper Fix"); |
|
1131 return ETrue; |
|
1132 } |
|
1133 |
|
1134 // Activate the trigger if the trigger is outside Hysteresis area |
|
1135 if( EInactive == strategyData.iActivityStatus && distanceToLatestLocation > 0 ) |
|
1136 { |
|
1137 // Activate the trigger |
|
1138 strategyData.iActivityStatus = EActive; |
|
1139 aTrigger->SetStrategyData( strategyData ); |
|
1140 LOG("Trigger activated based on NPP fix"); |
|
1141 } |
|
1142 UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation, remRearmTime ); |
|
1143 } |
|
1144 // If the trigger is exit type,we calculate distance to the radius |
|
1145 else if( CLbtTriggerConditionArea::EFireOnExit == trgCondition->Direction() ) |
|
1146 { |
|
1147 distanceToLatestLocation = distanceToCenter - |
|
1148 ( positionAccuracy+circularArea->Radius() ); |
|
1149 |
|
1150 if( distanceToLatestLocation < 0 && (remRearmTime == 0) ) |
|
1151 { |
|
1152 // Request fix using any of the available psy |
|
1153 LOG("Request Proper Fix"); |
|
1154 return ETrue; |
|
1155 } |
|
1156 UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation,remRearmTime ); |
|
1157 } |
|
1158 return EFalse; |
|
1159 } |
|
1160 |
|
1161 // ----------------------------------------------------------------------------- |
|
1162 // CLbtCoOrdinateSupervisor::EstimateSleepInterval |
|
1163 // Calculates the sleep interval |
|
1164 // ----------------------------------------------------------------------------- |
|
1165 // |
|
1166 void CLbtCoOrdinateSupervisor::EstimateSleepInterval() |
|
1167 { |
|
1168 FUNC_ENTER("CLbtCoOrdinateSupervisor::EstimateSleepInterval"); |
|
1169 |
|
1170 TReal maxUserSpeed = iSettings.iMaximumUserSpeed; |
|
1171 |
|
1172 TReal actualEstimatedSpeed = KMinProjSpeed; |
|
1173 // Flag to determine if the nearest trigger is an inactive trigger |
|
1174 TBool nearestTriggerInactive = EFalse; |
|
1175 |
|
1176 // This is first time when there are no previously observed values |
|
1177 if( iLocReqCount == 1 ) |
|
1178 { |
|
1179 // First iteration use the minimum update interval |
|
1180 if( iNearestTriggers.Count() ) |
|
1181 { |
|
1182 iSleepInterval = iNearestTriggers[0].distance / maxUserSpeed; |
|
1183 } |
|
1184 else |
|
1185 { |
|
1186 iSleepInterval = iSettings.iMinimumLocationUpdateInterval; |
|
1187 } |
|
1188 } |
|
1189 else |
|
1190 { |
|
1191 iEstimatedUserSpeed = 0.0; |
|
1192 if( (iLastLocationFixType == EFixFromDb) || |
|
1193 (iLastLocationFixType == EFixFromNpp) ) |
|
1194 { |
|
1195 iEstimatedUserSpeed = (maxUserSpeed + KMinProjSpeed)/2; |
|
1196 } |
|
1197 else if( iLastLocationFixType == EProperFix ) |
|
1198 { |
|
1199 // determine average speed from previous location request which is the |
|
1200 // observed speed |
|
1201 TPosition currentPosition, prevPosition; |
|
1202 iPosInfo.GetPosition( currentPosition ); |
|
1203 iPrevPosInfo.GetPosition( prevPosition ); |
|
1204 |
|
1205 TReal32 avgSpeed = 0.0; |
|
1206 |
|
1207 currentPosition.Speed( prevPosition, avgSpeed ); |
|
1208 TObservedValues obsValue; |
|
1209 obsValue.speed = avgSpeed; |
|
1210 obsValue.time = currentPosition.Time(); |
|
1211 |
|
1212 if( iNObservedValues.Count() == maxObsValues ) |
|
1213 { |
|
1214 iNObservedValues.Remove( 0 ); |
|
1215 } |
|
1216 iNObservedValues.Append( obsValue ); |
|
1217 |
|
1218 TReal num = 0.0; |
|
1219 TReal den = 0.0; |
|
1220 TReal obsSpeed = 0.0; |
|
1221 TReal obsTime = 0.0; |
|
1222 TTime currentTime; |
|
1223 |
|
1224 // Determine average of previously obtained observed speed, time values. |
|
1225 // Use the current time value obtained from the approximation of speed. |
|
1226 currentTime.UniversalTime(); |
|
1227 |
|
1228 for( TInt i = 0; i < iNObservedValues.Count(); i++ ) |
|
1229 { |
|
1230 obsSpeed = maxUserSpeed - ( iNObservedValues[i] ).speed; |
|
1231 TTimeIntervalSeconds timediff; |
|
1232 currentTime.SecondsFrom( ( iNObservedValues[i] ).time, timediff ); |
|
1233 obsTime = timediff.Int() / constantTime; |
|
1234 TReal timeExp = 0.0; |
|
1235 Math::Exp( timeExp, (-1 * obsTime ) ); |
|
1236 |
|
1237 num += obsSpeed * timeExp * timeExp; |
|
1238 den += timeExp; |
|
1239 } |
|
1240 |
|
1241 iEstimatedUserSpeed = maxUserSpeed - ( num / den ); |
|
1242 |
|
1243 if( Math::IsNaN(iEstimatedUserSpeed) ) |
|
1244 { |
|
1245 iEstimatedUserSpeed = maxUserSpeed; |
|
1246 } |
|
1247 |
|
1248 actualEstimatedSpeed = iEstimatedUserSpeed; |
|
1249 LOG1("Actual estimated speed:%f",actualEstimatedSpeed); |
|
1250 |
|
1251 if(iEstimatedUserSpeed < KMinProjSpeed) |
|
1252 { |
|
1253 iEstimatedUserSpeed = KMinProjSpeed; |
|
1254 } |
|
1255 // There are some cases estimate user speed goes to infinty. |
|
1256 else if( iEstimatedUserSpeed > maxUserSpeed ) |
|
1257 { |
|
1258 iEstimatedUserSpeed = maxUserSpeed; |
|
1259 } |
|
1260 } |
|
1261 |
|
1262 /** |
|
1263 * Find the position of the nearest trigger which: - |
|
1264 * |
|
1265 * a) Is Active |
|
1266 * b) Its rearm time has expired |
|
1267 */ |
|
1268 TInt position = -1; |
|
1269 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1270 { |
|
1271 iNearestTriggers[i].minTimeRequired = iNearestTriggers[i].distance / iEstimatedUserSpeed; |
|
1272 |
|
1273 if( iNearestTriggers[i].remRearmTime == 0 ) |
|
1274 { |
|
1275 // It is enough for us to know the approx time required to reach nearest trigger whose |
|
1276 // rearm time is not zero( nearest which is not fired ) |
|
1277 position = i; |
|
1278 break; |
|
1279 } |
|
1280 } |
|
1281 |
|
1282 /** |
|
1283 * Determine the sleep interval considering the rearm time of all the fired triggers. |
|
1284 * Sleep interval should be min[max[rearm time,minimum time to reach trigger]]. Flag needed |
|
1285 * for determining if movement detection is needed. Movement detector will be used if |
|
1286 * position acquisition should be made to re-activate the trigger. |
|
1287 */ |
|
1288 iSleepInterval = 0; |
|
1289 TLbtTriggerId nearestTriggerId = 0; |
|
1290 |
|
1291 // Sleep interval should be min[max[rearm time,minimum time to reach trigger]] |
|
1292 if( position >= 0 ) |
|
1293 { |
|
1294 for( TInt i=0;i<=position;i++ ) |
|
1295 { |
|
1296 // Sleep interval for a trigger is the maximum of time to trigger and rearm time |
|
1297 TInt maxSleepTimeForTrigger; |
|
1298 if( iNearestTriggers[i].remRearmTime < iNearestTriggers[i].minTimeRequired ) |
|
1299 { |
|
1300 maxSleepTimeForTrigger = iNearestTriggers[i].minTimeRequired; |
|
1301 } |
|
1302 else |
|
1303 { |
|
1304 maxSleepTimeForTrigger = iNearestTriggers[i].remRearmTime; |
|
1305 } |
|
1306 |
|
1307 // Sleep interval for system is minimum sleep interval of all triggers |
|
1308 if( ( !iSleepInterval.Int() && maxSleepTimeForTrigger ) || |
|
1309 iSleepInterval.Int() > maxSleepTimeForTrigger ) |
|
1310 { |
|
1311 iSleepInterval = maxSleepTimeForTrigger; |
|
1312 nearestTriggerId = iNearestTriggers[i].id; |
|
1313 } |
|
1314 } |
|
1315 } |
|
1316 // Case where all the triggers are waiting for rearm time to elapse |
|
1317 else |
|
1318 { |
|
1319 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1320 { |
|
1321 if( !iSleepInterval.Int() || |
|
1322 ( iSleepInterval.Int() > iNearestTriggers[i].remRearmTime )) |
|
1323 { |
|
1324 iSleepInterval = iNearestTriggers[i].remRearmTime; |
|
1325 } |
|
1326 } |
|
1327 } |
|
1328 |
|
1329 LOG1("Estimated speed:%f",iEstimatedUserSpeed); |
|
1330 |
|
1331 |
|
1332 if( nearestTriggerId ) |
|
1333 { |
|
1334 // Update the nearestTriggerInactive flag |
|
1335 CLbtContainerTriggerEntry* trigEntry = NULL; |
|
1336 TBool found = iView->GetTriggerByID( nearestTriggerId, trigEntry ); |
|
1337 |
|
1338 if( found && (trigEntry != NULL) ) |
|
1339 { |
|
1340 TStrategyData strategyData = trigEntry->StrategyData(); |
|
1341 |
|
1342 if( strategyData.iActivityStatus == EInactive ) |
|
1343 { |
|
1344 // Inside triggering area |
|
1345 nearestTriggerInactive = ETrue; |
|
1346 } |
|
1347 else |
|
1348 { |
|
1349 // Outside triggering area |
|
1350 nearestTriggerInactive = EFalse; |
|
1351 } |
|
1352 } |
|
1353 } |
|
1354 |
|
1355 // Reduce the time taken from last position fix |
|
1356 if( iLastLocationFixType == EProperFix ) |
|
1357 { |
|
1358 TTime currentTime; |
|
1359 currentTime.UniversalTime(); |
|
1360 TTimeIntervalSeconds seconds; |
|
1361 currentTime.SecondsFrom(iLastFixTime, seconds); |
|
1362 iProcessingInterval = seconds.Int(); |
|
1363 iSleepInterval = iSleepInterval.Int() - iProcessingInterval; |
|
1364 } |
|
1365 } |
|
1366 |
|
1367 // If sleep interval is less than KMinSleepInterval and the UE is travelling in |
|
1368 // high speed then request terminal position immediately |
|
1369 if( !nearestTriggerInactive && |
|
1370 ( iSleepInterval.Int() <= KMinSleepInterval ) && |
|
1371 ( iLastLocationFixType == EProperFix ) ) |
|
1372 { |
|
1373 LOG1("Requesting time out %d", iSleepInterval.Int()); |
|
1374 iFixForFiringCloseTriggers = ETrue; |
|
1375 // Here we need fix with in the estimated time to reach trigger.Hence setting timeout value to |
|
1376 // estimated sleep interval |
|
1377 RequestTerminalPosition( (KMinSleepInterval * KMicroMultiplier),EProperFix ); |
|
1378 return; |
|
1379 } |
|
1380 |
|
1381 iState = ESleep; |
|
1382 TBool useMvmtDet = ETrue; |
|
1383 if( iLastLocationFixType != EProperFix ) |
|
1384 { |
|
1385 useMvmtDet = ETrue; |
|
1386 } |
|
1387 else if( nearestTriggerInactive ) |
|
1388 { |
|
1389 useMvmtDet = ETrue; |
|
1390 } |
|
1391 else if( iSleepInterval.Int() < 20 ) |
|
1392 { |
|
1393 useMvmtDet = EFalse; |
|
1394 } |
|
1395 else if( actualEstimatedSpeed > KMaxSpeedToUseMvmtDet ) |
|
1396 { |
|
1397 useMvmtDet = EFalse; |
|
1398 } |
|
1399 LOG1("useMvmtDet = %d", useMvmtDet); |
|
1400 iTimer->Set( iStatus, iSleepInterval, useMvmtDet ); |
|
1401 SetActive(); |
|
1402 } |
|
1403 |
|
1404 |
|
1405 // ----------------------------------------------------------------------------- |
|
1406 // CLbtCoOrdinateSupervisor::ProcessInterrupt |
|
1407 // Evaluates the cause of a timer interrupt and determines the necessary |
|
1408 // actions to be performed |
|
1409 // ----------------------------------------------------------------------------- |
|
1410 // |
|
1411 void CLbtCoOrdinateSupervisor::ProcessInterrupt() |
|
1412 { |
|
1413 FUNC_ENTER("CLbtCoOrdinateSupervisor::ProcessInterrupt"); |
|
1414 |
|
1415 // This is when errors occur while acquiring terminal position |
|
1416 if( !iStatusManager->LocationAcqSuccess() ) |
|
1417 { |
|
1418 // Check sleep interval and determine if sleep mode can continue else |
|
1419 // retry acquiring terminal position. This happens when there are |
|
1420 // changes to triggers in the sleep mode during which the sleep is |
|
1421 // cancelled and trigger view is refreshed. Once the refresh operation |
|
1422 // is completed, this method is invoked. |
|
1423 TTimeIntervalSeconds interval; |
|
1424 if( iTimer->RemainingSleepInterval( interval ) ) |
|
1425 { |
|
1426 iState = ESleep; |
|
1427 if( interval.Int() < 5 ) |
|
1428 { |
|
1429 iTimer->ResetInterval( iStatus, interval,EFalse ); |
|
1430 } |
|
1431 else |
|
1432 { |
|
1433 iTimer->ResetInterval( iStatus, interval,ETrue ); |
|
1434 } |
|
1435 SetActive(); |
|
1436 } |
|
1437 else |
|
1438 { |
|
1439 // If the last location acqusition has failed and the location information for the current cell |
|
1440 // is unavailable then request location from NPP PSY else request from DB itself |
|
1441 if( (iLastCellRequestStatus == KErrNone) && |
|
1442 iLocArea.iCellId ) |
|
1443 { |
|
1444 // Cell information is available |
|
1445 if( !(KErrNone == GetCellIdPosition( iPosInfo ) ) ) |
|
1446 { |
|
1447 RequestTerminalPosition( iSettings.iLocationRequestTimeout, EProperFix ); |
|
1448 } |
|
1449 else |
|
1450 { |
|
1451 RequestTerminalPosition( iSettings.iLocationRequestTimeout, EFixFromDb ); |
|
1452 } |
|
1453 } |
|
1454 else |
|
1455 { |
|
1456 // Current cell information un-available. Make proper fix |
|
1457 RequestTerminalPosition( iSettings.iLocationRequestTimeout, EProperFix ); |
|
1458 } |
|
1459 } |
|
1460 } |
|
1461 |
|
1462 |
|
1463 // This is when sleep mode is interrupted due to notifications from |
|
1464 // container for addition/modification/deletion of triggers in the system |
|
1465 else if( iTimer->SleepIntervalInterrupted() ) |
|
1466 { |
|
1467 TLbtTriggerId nearestTrigger = 0; |
|
1468 if( iNearestTriggers.Count() ) |
|
1469 { |
|
1470 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1471 { |
|
1472 if( iNearestTriggers[i].remRearmTime == 0 ) |
|
1473 { |
|
1474 nearestTrigger = iNearestTriggers[i].id; |
|
1475 break; |
|
1476 } |
|
1477 } |
|
1478 } |
|
1479 iView->DetermineNearestTriggerChanges( &iNearestTriggers ); |
|
1480 |
|
1481 if( iNearestTriggers.Count() == 0 ) |
|
1482 { |
|
1483 // This means the nearest 5 triggers have been changed. Reset |
|
1484 // iterator re-evaluate all triggers in the system. |
|
1485 if( KErrNone != ResetViewIterator() ) |
|
1486 { |
|
1487 return; |
|
1488 } |
|
1489 iState = ETriggerEvaluation; |
|
1490 SetEvent(); |
|
1491 } |
|
1492 else |
|
1493 { |
|
1494 TBool makeLocReq = EFalse; |
|
1495 TRAPD( err, makeLocReq = EvaluateModifiedTriggersL( ) ); |
|
1496 |
|
1497 if( KErrNone != err ) |
|
1498 { |
|
1499 ERROR("EvaluateTriggersL leaving with %d", err); |
|
1500 Term(); |
|
1501 return; |
|
1502 } |
|
1503 |
|
1504 if( makeLocReq ) |
|
1505 { |
|
1506 // Location request is needed based on evaluating |
|
1507 // modified triggers |
|
1508 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
1509 return; |
|
1510 } |
|
1511 |
|
1512 // Check if nearest trigger has changed |
|
1513 TLbtTriggerId nearestTriggerAfterEvaluation = 0; |
|
1514 if( iNearestTriggers.Count() ) |
|
1515 { |
|
1516 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1517 { |
|
1518 if( iNearestTriggers[i].remRearmTime == 0 ) |
|
1519 { |
|
1520 nearestTriggerAfterEvaluation = iNearestTriggers[i].id; |
|
1521 break; |
|
1522 } |
|
1523 } |
|
1524 } |
|
1525 // This is check is required when all triggers in the system has fired |
|
1526 // and new trigger has been added. |
|
1527 if( (nearestTriggerAfterEvaluation) && |
|
1528 (nearestTrigger != nearestTriggerAfterEvaluation) ) |
|
1529 { |
|
1530 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
1531 } |
|
1532 else |
|
1533 { |
|
1534 // Check if there be any remaining sleep interval. If true, |
|
1535 // then switch to sleep mode for the remaining time period. |
|
1536 // Else switch to acquiring location information. |
|
1537 TTimeIntervalSeconds remainingInterval; |
|
1538 if( iTimer->RemainingSleepInterval( remainingInterval ) ) |
|
1539 { |
|
1540 iState = ESleep; |
|
1541 if( remainingInterval.Int() < 5 ) |
|
1542 { |
|
1543 iTimer->ResetInterval( iStatus, remainingInterval,EFalse ); |
|
1544 } |
|
1545 else |
|
1546 { |
|
1547 iTimer->ResetInterval( iStatus, remainingInterval,ETrue ); |
|
1548 } |
|
1549 SetActive(); |
|
1550 } |
|
1551 else |
|
1552 { |
|
1553 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
1554 } |
|
1555 } |
|
1556 } |
|
1557 } |
|
1558 else if( KErrNone == iStatus.Int() || KErrAbort == iStatus.Int() ) |
|
1559 { |
|
1560 RequestTerminalPosition( iSettings.iLocationRequestTimeout ); |
|
1561 } |
|
1562 else |
|
1563 { |
|
1564 LOG1("Error in timer:%d",iStatus.Int()); |
|
1565 } |
|
1566 } |
|
1567 |
|
1568 |
|
1569 // ----------------------------------------------------------------------------- |
|
1570 // CLbtCoOrdinateSupervisor::RequestTerminalPosition |
|
1571 // Issues an asynchronous request to determine terminal's position |
|
1572 // ----------------------------------------------------------------------------- |
|
1573 // |
|
1574 void CLbtCoOrdinateSupervisor::RequestTerminalPosition( TInt aLocationRequestTimeout, |
|
1575 TLocationFixType aFixLocationFixType ) |
|
1576 { |
|
1577 FUNC_ENTER("CLbtCoOrdinateSupervisor::RequestTerminalPosition"); |
|
1578 iPrevPosInfo = iPosInfo; |
|
1579 LOG1("aFixLocationFixType = %d", aFixLocationFixType); |
|
1580 LOG1("Cell Id = %d", iLocArea.iCellId); |
|
1581 |
|
1582 if( (aFixLocationFixType == EFixFromDb) && |
|
1583 (iLastCellRequestStatus == KErrNone) && |
|
1584 iLocArea.iCellId ) |
|
1585 { |
|
1586 LOG("Taking fix from DB"); |
|
1587 TInt error = GetCellIdPosition( iPosInfo ); |
|
1588 if( KErrNone == error) |
|
1589 { |
|
1590 LOG("Fix From DB"); |
|
1591 TPosition position; |
|
1592 iPosInfo.GetPosition(position); |
|
1593 LOG1("Lat:%f", position.Latitude()); |
|
1594 LOG1("Long:%f", position.Longitude()); |
|
1595 LOG1("HA:%f", position.HorizontalAccuracy()); |
|
1596 iLastLocationFixType = EFixFromDb; |
|
1597 iState = ETriggerEvaluation; |
|
1598 SetEvent(); |
|
1599 return; |
|
1600 } |
|
1601 else |
|
1602 { |
|
1603 LOG1("Failed to get Fix From DB with %d", error); |
|
1604 } |
|
1605 } |
|
1606 else if( aFixLocationFixType == EFixFromNpp ) |
|
1607 { |
|
1608 iLastLocationFixType = EFixFromNpp; |
|
1609 iLocationRequestor->CurrentLocationFromNpp( iPosInfo, iStatus, |
|
1610 TTimeIntervalMicroSeconds( aLocationRequestTimeout ) ); |
|
1611 iState = ELocationAcquisition; |
|
1612 SetActive(); |
|
1613 return; |
|
1614 } |
|
1615 |
|
1616 iLastLocationFixType = EProperFix; |
|
1617 iLocationRequestor->CurrentLocation( iPosInfo, iStatus, |
|
1618 iModuleId, |
|
1619 TTimeIntervalMicroSeconds( aLocationRequestTimeout ) ); |
|
1620 iState = ELocationAcquisition; |
|
1621 SetActive(); |
|
1622 } |
|
1623 |
|
1624 |
|
1625 // ----------------------------------------------------------------------------- |
|
1626 // CLbtCoOrdinateSupervisor::GetCellIdPosition |
|
1627 // Get the position corresponding to current cell id |
|
1628 // ----------------------------------------------------------------------------- |
|
1629 // |
|
1630 TInt CLbtCoOrdinateSupervisor::GetCellIdPosition( TPositionInfo& aPositionInfo ) |
|
1631 { |
|
1632 FUNC_ENTER("CLbtCoOrdinateSupervisor::GetCellIdPosition"); |
|
1633 TInt countryCode,networkCode; |
|
1634 |
|
1635 TLex lex( iNwInfo.iCountryCode ); |
|
1636 lex.Val( countryCode ); |
|
1637 |
|
1638 lex.Assign( iNwInfo.iNetworkId ); |
|
1639 lex.Val( networkCode ); |
|
1640 |
|
1641 TPosition position; |
|
1642 TInt error = iCellIdDatabase->GetLocationForCid( countryCode,networkCode,iLocArea.iLocationAreaCode, |
|
1643 iLocArea.iCellId,position ); |
|
1644 if( error == KErrNone ) |
|
1645 { |
|
1646 aPositionInfo.SetPosition( position ); |
|
1647 } |
|
1648 return error; |
|
1649 } |
|
1650 |
|
1651 |
|
1652 // ----------------------------------------------------------------------------- |
|
1653 // CLbtCoOrdinateSupervisor::UpdateNearestTriggers |
|
1654 // Updates the record of nearest triggers |
|
1655 // ----------------------------------------------------------------------------- |
|
1656 // |
|
1657 void CLbtCoOrdinateSupervisor::UpdateNearestTriggers( TLbtTriggerId aID, TReal aDistance , TInt aRemRearmTime ) |
|
1658 { |
|
1659 FUNC_ENTER("CLbtCoOrdinateSupervisor::UpdateNearestTriggers"); |
|
1660 TNearestTrigger nTrigger; |
|
1661 nTrigger.distance = aDistance; |
|
1662 nTrigger.id = aID; |
|
1663 nTrigger.remRearmTime = aRemRearmTime; |
|
1664 |
|
1665 TLinearOrder< TNearestTrigger > byDistance( CompareByDistance ); |
|
1666 iNearestTriggers.InsertInOrderAllowRepeats( nTrigger, byDistance ); |
|
1667 } |
|
1668 |
|
1669 |
|
1670 // ----------------------------------------------------------------------------- |
|
1671 // CLbtCoOrdinateSupervisor::EstimateTriggerRadii |
|
1672 // Calculcates the trigger radius and the radius of the hysteresis circle |
|
1673 // ----------------------------------------------------------------------------- |
|
1674 // |
|
1675 CLbtCoOrdinateSupervisor::TTriggerArea CLbtCoOrdinateSupervisor::EstimateTriggerRadii( |
|
1676 TReal aTriggerRadius, TReal aHysteresisRadius, |
|
1677 TReal aPositionAccuracy ) |
|
1678 { |
|
1679 TTriggerArea trgArea; |
|
1680 TReal ratioOfCircularAreas = aPositionAccuracy / aTriggerRadius; |
|
1681 |
|
1682 if( ratioOfCircularAreas >= KCofftOfHighEdgeLimit ) |
|
1683 { |
|
1684 trgArea.triggerRadius = aTriggerRadius; |
|
1685 trgArea.hysteresisRadius = aHysteresisRadius; |
|
1686 } |
|
1687 else |
|
1688 { |
|
1689 // Update radiusOfTrigger and radiusOfHysteresis accordingly |
|
1690 trgArea.triggerRadius = aTriggerRadius +( KAccuracyMultiplier * aPositionAccuracy ); |
|
1691 trgArea.hysteresisRadius = Hysteresis( trgArea.triggerRadius ); |
|
1692 } |
|
1693 |
|
1694 return trgArea; |
|
1695 } |
|
1696 |
|
1697 |
|
1698 // ----------------------------------------------------------------------------- |
|
1699 // CLbtCoOrdinateSupervisor::Hysteresis |
|
1700 // Calculates the hysteresis radius |
|
1701 // ----------------------------------------------------------------------------- |
|
1702 // |
|
1703 TReal CLbtCoOrdinateSupervisor::Hysteresis( TReal aTriggerRadius ) |
|
1704 { |
|
1705 TReal hysteresis; |
|
1706 if( aTriggerRadius > KTriggerRadiusCutoff ) |
|
1707 { |
|
1708 TReal logRadius; |
|
1709 Math::Ln( logRadius, aTriggerRadius / 10 ); |
|
1710 hysteresis = aTriggerRadius / logRadius; |
|
1711 } |
|
1712 else |
|
1713 { |
|
1714 hysteresis = aTriggerRadius / 4; |
|
1715 } |
|
1716 |
|
1717 return hysteresis + aTriggerRadius; |
|
1718 } |
|
1719 |
|
1720 |
|
1721 // ----------------------------------------------------------------------------- |
|
1722 // CLbtCoOrdinateSupervisor::DetermineNearestDistances |
|
1723 // Algorithm to determine the shortest distance |
|
1724 // ----------------------------------------------------------------------------- |
|
1725 // |
|
1726 TInt CLbtCoOrdinateSupervisor::CompareByDistance( const TNearestTrigger& src, |
|
1727 const TNearestTrigger& dst ) |
|
1728 { |
|
1729 if( src.distance > dst.distance ) |
|
1730 { |
|
1731 return 1; |
|
1732 } |
|
1733 else if( src.distance < dst.distance ) |
|
1734 { |
|
1735 return -1; |
|
1736 } |
|
1737 return 0; |
|
1738 } |
|
1739 |
|
1740 |
|
1741 // ----------------------------------------------------------------------------- |
|
1742 // CLbtCoOrdinateSupervisor::CompareByID |
|
1743 // Determine equality of nearest triggers by id |
|
1744 // ----------------------------------------------------------------------------- |
|
1745 // |
|
1746 TBool CLbtCoOrdinateSupervisor::CompareByID( const TNearestTrigger& src, |
|
1747 const TNearestTrigger& dst ) |
|
1748 { |
|
1749 if( src.id > dst.id ) |
|
1750 { |
|
1751 return ETrue; |
|
1752 } |
|
1753 return EFalse; |
|
1754 } |
|
1755 |
|
1756 |
|
1757 // ----------------------------------------------------------------------------- |
|
1758 // CLbtCoOrdinateSupervisor::ResetViewIterator |
|
1759 // Resets trigger view iterator. |
|
1760 // ----------------------------------------------------------------------------- |
|
1761 // |
|
1762 TInt CLbtCoOrdinateSupervisor::ResetViewIterator() |
|
1763 { |
|
1764 FUNC_ENTER("CLbtCoOrdinateSupervisor::ResetViewIterator"); |
|
1765 TInt err = iViewIterator.Reset(); |
|
1766 if( KErrNone != err ) |
|
1767 { |
|
1768 if( KErrNotFound == err ) |
|
1769 { |
|
1770 // determine update interval |
|
1771 iState = iProjectedState = EIdle; |
|
1772 } |
|
1773 else |
|
1774 { |
|
1775 // TODO: Report error to server. This can be done only after |
|
1776 // introducing new state to strategy dynamic info. |
|
1777 Term(); |
|
1778 } |
|
1779 return err; |
|
1780 } |
|
1781 |
|
1782 return KErrNone; |
|
1783 } |
|
1784 |
|
1785 |
|
1786 // ----------------------------------------------------------------------------- |
|
1787 // CLbtCoOrdinateSupervisor::RunL |
|
1788 // Inherited from CActive - called when the request issued is completed. |
|
1789 // ----------------------------------------------------------------------------- |
|
1790 // |
|
1791 void CLbtCoOrdinateSupervisor::RunL() |
|
1792 { |
|
1793 FUNC_ENTER("CLbtCoOrdinateSupervisor::RunL"); |
|
1794 switch ( iState ) |
|
1795 { |
|
1796 case ELocationAcquisition: |
|
1797 GetPositionInfoL(); |
|
1798 break; |
|
1799 |
|
1800 case ETriggerEvaluation: |
|
1801 EvaluateTriggersL(); |
|
1802 break; |
|
1803 |
|
1804 case EUpdateIntervalEstimation: |
|
1805 EstimateSleepInterval(); |
|
1806 break; |
|
1807 |
|
1808 case ESleep: |
|
1809 LOG("Wakeup"); |
|
1810 ProcessInterrupt(); |
|
1811 break; |
|
1812 |
|
1813 default: |
|
1814 break; |
|
1815 } |
|
1816 } |
|
1817 |
|
1818 |
|
1819 // ----------------------------------------------------------------------------- |
|
1820 // CLbtCoOrdinateSupervisor::DoCancel |
|
1821 // Inherited from CActive - called to cancel outanding events. |
|
1822 // ----------------------------------------------------------------------------- |
|
1823 // |
|
1824 void CLbtCoOrdinateSupervisor::DoCancel() |
|
1825 { |
|
1826 FUNC_ENTER("CLbtCoOrdinateSupervisor::DoCancel"); |
|
1827 iFixForFiringCloseTriggers = EFalse; |
|
1828 } |
|
1829 |
|
1830 |
|
1831 // ----------------------------------------------------------------------------- |
|
1832 // CLbtCoOrdinateSupervisor::RunError |
|
1833 // Handles the event of leave from the request completion event handler RunL() |
|
1834 // ----------------------------------------------------------------------------- |
|
1835 // |
|
1836 TInt CLbtCoOrdinateSupervisor::RunError( TInt /*aError*/ ) |
|
1837 { |
|
1838 FUNC_ENTER("CLbtCoOrdinateSupervisor::RunError"); |
|
1839 Term(); |
|
1840 return KErrNone; |
|
1841 } |
|
1842 |
|
1843 |
|
1844 // ----------------------------------------------------------------------------- |
|
1845 // CLbtCoOrdinateSupervisor::CLbtCoOrdinateSupervisor |
|
1846 // C++ default constructor. |
|
1847 // ----------------------------------------------------------------------------- |
|
1848 // |
|
1849 CLbtCoOrdinateSupervisor::CLbtCoOrdinateSupervisor() : |
|
1850 CActive( EPriorityHigh ) |
|
1851 { |
|
1852 CActiveScheduler::Add( this ); |
|
1853 } |
|
1854 |
|
1855 |
|
1856 // ----------------------------------------------------------------------------- |
|
1857 // CLbtCoOrdinateSupervisor::ConstructL |
|
1858 // Symbian 2nd phase constructor. |
|
1859 // ----------------------------------------------------------------------------- |
|
1860 // |
|
1861 void CLbtCoOrdinateSupervisor::ConstructL( TAny* /*aConstructionParameters*/, |
|
1862 CLbtTriggerView* aView, |
|
1863 MLbtStrategyEngineObsrvr* aObserver, |
|
1864 CLbtCellChangeHandler* aCellChangeHandler ) |
|
1865 { |
|
1866 iEngObserver = aObserver; |
|
1867 iState = iProjectedState = EIdle; |
|
1868 iEngObserver->RetrieveTriggeringSettings( iSettings ); |
|
1869 iCellChangeHandler = aCellChangeHandler; |
|
1870 |
|
1871 iModuleId = iSettings.iPositioningTechnology; |
|
1872 |
|
1873 iLocationRequestor = CLbtLocationRequestor::NewL(); |
|
1874 |
|
1875 iStatusManager = CLbtStatusManager::NewL(); |
|
1876 iTimer = CLbtStrategyTimer::NewL(); |
|
1877 iView = aView; |
|
1878 |
|
1879 iViewIterator = iView->BeginL( CLbtGeoAreaBase::ECircle ); |
|
1880 iCellIdDatabase = CLbtCellIdDatabase::NewL(); |
|
1881 iLastCellRequestStatus = KErrUnknown; |
|
1882 iLastLocationFixType = EFixUnknown; |
|
1883 iPsyChangeListner = NULL; |
|
1884 iFixForFiringCloseTriggers = EFalse; |
|
1885 } |
|
1886 |
|
1887 |
|
1888 // ----------------------------------------------------------------------------- |
|
1889 // CLbtCoOrdinateSupervisor::SetEvent |
|
1890 // Completes the iRequestStatus with KErrNone. |
|
1891 // ----------------------------------------------------------------------------- |
|
1892 // |
|
1893 void CLbtCoOrdinateSupervisor::SetEvent() |
|
1894 { |
|
1895 if ( !IsActive() ) |
|
1896 { |
|
1897 TRequestStatus* lStatus = &iStatus; |
|
1898 User::RequestComplete( lStatus, KErrNone ); |
|
1899 SetActive(); |
|
1900 } |
|
1901 } |
|
1902 |
|
1903 |
|
1904 // ----------------------------------------------------------------------------- |
|
1905 // CLbtCoOrdinateSupervisor::Term |
|
1906 // |
|
1907 // ----------------------------------------------------------------------------- |
|
1908 // |
|
1909 void CLbtCoOrdinateSupervisor::Term() |
|
1910 { |
|
1911 FUNC_ENTER("CLbtCoOrdinateSupervisor::Term"); |
|
1912 |
|
1913 iSupervisionInitiated = EFalse; |
|
1914 |
|
1915 iView->Cancel(); |
|
1916 switch( iState ) |
|
1917 { |
|
1918 case ELocationAcquisition: |
|
1919 if( iLastLocationFixType == EProperFix ) |
|
1920 { |
|
1921 iLocationRequestor->Cancel(); |
|
1922 } |
|
1923 else |
|
1924 { |
|
1925 iLocationRequestor->CancelFixFromNpp(); |
|
1926 } |
|
1927 break; |
|
1928 |
|
1929 case ESleep: |
|
1930 iTimer->Cancel(); |
|
1931 break; |
|
1932 |
|
1933 default: |
|
1934 Cancel(); |
|
1935 break; |
|
1936 } |
|
1937 |
|
1938 iState = iProjectedState = EIdle; |
|
1939 iLastLocationFixType = EFixUnknown; |
|
1940 iFixForFiringCloseTriggers = EFalse; |
|
1941 } |
|
1942 |
|
1943 // ----------------------------------------------------------------------------- |
|
1944 // CLbtCoOrdinateSupervisor::FireClosestTriggers |
|
1945 // |
|
1946 // ----------------------------------------------------------------------------- |
|
1947 // |
|
1948 void CLbtCoOrdinateSupervisor::FireClosestTriggers() |
|
1949 { |
|
1950 FUNC_ENTER("CLbtCoOrdinateSupervisor::FireClosestTriggers"); |
|
1951 LOG1("NT Count = %d", iNearestTriggers.Count()); |
|
1952 for( TInt i=0;i<iNearestTriggers.Count();i++ ) |
|
1953 { |
|
1954 if(iNearestTriggers[i].remRearmTime != 0) |
|
1955 { |
|
1956 continue; |
|
1957 } |
|
1958 |
|
1959 TInt timeToTrigger = (iNearestTriggers[i].distance / iEstimatedUserSpeed); |
|
1960 |
|
1961 TInt estimatedInterval = timeToTrigger - iProcessingInterval; |
|
1962 |
|
1963 LOG1("estimatedInterval = %d", estimatedInterval); |
|
1964 |
|
1965 if( estimatedInterval <= KMinSleepInterval ) |
|
1966 { |
|
1967 LOG("NEED TO FIRE"); |
|
1968 CLbtContainerTriggerEntry* trigger; |
|
1969 if( iView->GetTriggerByID( iNearestTriggers[i].id,trigger ) ) |
|
1970 { |
|
1971 LOGSTRING("Trigger: \"%S\" ", &(trigger->TriggerEntry()->Name())); |
|
1972 // check the activity status |
|
1973 TStrategyData strategyData = trigger->StrategyData(); |
|
1974 if( strategyData.iActivityStatus == EActive ) |
|
1975 { |
|
1976 // Fire the trigger |
|
1977 TLbtTriggerDataMask dataMask = 0; |
|
1978 |
|
1979 // Set trigger state to fired |
|
1980 trigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue ); |
|
1981 TLbtTriggerFireInfo triggerFireInfo; |
|
1982 TPositionInfo positionInfo; |
|
1983 triggerFireInfo.iTriggerId = trigger->TriggerEntry()->Id(); |
|
1984 triggerFireInfo.iFiredPositionInfo = iPrevPosInfo; |
|
1985 |
|
1986 trigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo ); |
|
1987 |
|
1988 // Time at which trigger fired |
|
1989 TTime triggerFiredTime; |
|
1990 triggerFiredTime.UniversalTime(); |
|
1991 LOG("NEAREST TRIGGER FIRED"); |
|
1992 |
|
1993 strategyData.iFireTime = triggerFiredTime.Int64(); |
|
1994 // Set trigger to inactive state |
|
1995 strategyData.iActivityStatus = EInactive; |
|
1996 |
|
1997 dataMask |= |
|
1998 CLbtContainerTriggerEntry::EContainerAttributeIsFired | |
|
1999 CLbtContainerTriggerEntry::EContainerAttributeFireInfo ; |
|
2000 |
|
2001 iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, trigger, dataMask ); |
|
2002 trigger->SetStrategyData( strategyData ); |
|
2003 } |
|
2004 } |
|
2005 else |
|
2006 { |
|
2007 LOG("TRIGGER NOT FOUND ??"); |
|
2008 } |
|
2009 } |
|
2010 else |
|
2011 { |
|
2012 LOG("ELSE"); |
|
2013 // Since the array is in the ascending order of distance( which is directly proportional to time ), |
|
2014 // we can need not search rest of the array. |
|
2015 break; |
|
2016 } |
|
2017 } |
|
2018 } |
|
2019 |
|
2020 // ----------------------------------------------------------------------------- |
|
2021 // CLbtCoOrdinateSupervisor::CalculateTolerableRadius |
|
2022 // |
|
2023 // ----------------------------------------------------------------------------- |
|
2024 // |
|
2025 TReal CLbtCoOrdinateSupervisor::CalculateTolerableRadius( TReal aRadius ) |
|
2026 { |
|
2027 // Tolerance can be calculated using the straight line equation. Slope of straight line is 0.07 and |
|
2028 // intercept is 22.2 |
|
2029 TReal tolerableInaccuracy = ( 0.07 * aRadius ) + 22.2; |
|
2030 return ( tolerableInaccuracy + aRadius ); |
|
2031 } |
|
2032 |
|
2033 // ----------------------------------------------------------------------------- |
|
2034 // CLbtCoOrdinateSupervisor::HandleCellChangeEvent |
|
2035 // |
|
2036 // ----------------------------------------------------------------------------- |
|
2037 // |
|
2038 void CLbtCoOrdinateSupervisor::HandleCellChangeEvent( |
|
2039 const TInt aStatus, |
|
2040 const RMobilePhone::TMobilePhoneNetworkInfoV1& aNwInfo, |
|
2041 const RMobilePhone::TMobilePhoneLocationAreaV1& aLocArea) |
|
2042 { |
|
2043 FUNC_ENTER("CLbtCoOrdinateSupervisor::HandleCellChangeEvent"); |
|
2044 if( KErrNone == aStatus ) |
|
2045 { |
|
2046 // validate network info |
|
2047 if (aNwInfo.iMode == RMobilePhone::ENetworkModeGsm || |
|
2048 aNwInfo.iMode == RMobilePhone::ENetworkModeWcdma) |
|
2049 { |
|
2050 TLex lex( aNwInfo.iCountryCode ); |
|
2051 TInt countryCode,networkCode; |
|
2052 lex.Val( countryCode ); |
|
2053 if( countryCode ) |
|
2054 { |
|
2055 lex.Assign( aNwInfo.iNetworkId ); |
|
2056 lex.Val( networkCode ); |
|
2057 if( networkCode ) |
|
2058 { |
|
2059 if( aLocArea.iLocationAreaCode && aLocArea.iCellId ) |
|
2060 { |
|
2061 iLastCellRequestStatus = KErrNone; |
|
2062 iNwInfo = aNwInfo; |
|
2063 iLocArea = aLocArea; |
|
2064 } |
|
2065 } |
|
2066 } |
|
2067 } |
|
2068 } |
|
2069 else |
|
2070 { |
|
2071 iLastCellRequestStatus = aStatus; |
|
2072 } |
|
2073 } |
|
2074 |
|
2075 // ----------------------------------------------------------------------------- |
|
2076 // CLbtCoOrdinateSupervisor::HandlePsyChangeEvent |
|
2077 // |
|
2078 // ----------------------------------------------------------------------------- |
|
2079 // |
|
2080 void CLbtCoOrdinateSupervisor::HandlePsyChangeEvent( TPositionModuleId aModuleId ) |
|
2081 { |
|
2082 LOG("CLbtCoOrdinateSupervisor::HandlePsyChangeEvent"); |
|
2083 if( aModuleId == iSettings.iPositioningTechnology ) |
|
2084 { |
|
2085 LOG("aModuleId == iSettings.iPositioningTechnology"); |
|
2086 iModuleId = aModuleId; |
|
2087 delete iPsyChangeListner; |
|
2088 iPsyChangeListner = NULL; |
|
2089 } |
|
2090 else |
|
2091 { |
|
2092 LOG("aModuleId != iSettings.iPositioningTechnology"); |
|
2093 // We will use defualt proxy |
|
2094 iModuleId = TUid::Uid(0xFFFFFFFF); |
|
2095 iPsyChangeListner->StartToListen( iSettings.iPositioningTechnology ); |
|
2096 } |
|
2097 |
|
2098 // If coordinate supervisor AO is not active,request terminal position |
|
2099 if( !IsActive() ) |
|
2100 { |
|
2101 RequestTerminalPosition( iSettings.iLocationRequestTimeout,EProperFix ); |
|
2102 } |
|
2103 } |
|
2104 // end of file |