コード例 #1
0
        public async Task <GeofenceRequest[]> GetTriggered(string userId, Location newLocation)
        {
            var gfs = (await _locationStore.GetActiveGeofenceRequests(userId, newLocation.Timestamp))
                      .Select(async(gf) =>
            {
                var triggered = false;
                var distance  = Geolocation.GeoCalculator.GetDistance(gf.Lat,
                                                                      gf.Lng,
                                                                      newLocation.Latitude,
                                                                      newLocation.Longitude, 5, Geolocation.DistanceUnit.Meters);
                if (gf.Exit)
                {
                    if (distance >= gf.Radius)
                    {
                        await _logger.LogForFocusItem(userId, gf.FocusItemId, $"Geofence {gf.Id}/Exit triggered");
                        triggered = true;
                    }
                }
                else
                {
                    if (distance <= gf.Radius)
                    {
                        await _logger.LogForFocusItem(userId, gf.FocusItemId, $"Geofence {gf.Id}/Enter triggered");
                        triggered = true;
                    }
                }
                return(new { gf, triggered });
            });

            return((await Task.WhenAll(gfs)).Where(v => v.triggered).Select(v => v.gf).ToArray());
        }
コード例 #2
0
        private async Task NotifyOrInstall(string userId, FocusItemWithExternalData item)
        {
            var timeToDeparture = item.IndicateTime - DateTimeOffset.Now;

            if (timeToDeparture < FocusConstants.NotifyTime.Add(FocusConstants.ButlerInaccuracy))
            {
                var notifySemaphore = _notifySempahores.GetOrAdd(userId, s => new SemaphoreSlim(1));
                await notifySemaphore.WaitAsync();

                try
                {
                    if (!await _focusStore.FocusItemNotifiedAsync(item.Id))
                    {
                        try
                        {
                            await _digitPushServiceClient[userId].Push.Create(new DigitPushService.Models.PushRequest()
                            {
                                ChannelOptions = new Dictionary <string, string>()
                                {
                                    { "digit.notify", null }
                                },
                                Payload = JsonConvert.SerializeObject(new
                                {
                                    notification = new
                                    {
                                        tag   = item.Id,
                                        title = item.CalendarEvent == null ? "Losgehen" : $"Losgehen zu {item.CalendarEvent.Subject}",
                                        body  = NotificationBody(item)
                                    }
                                })
                            });
                        }
                        catch (Exception e)
                        {
                            await _logger.LogForFocusItem(userId, item.Id, $"Could notify user ({e.Message}).", logLevel : LogLevel.Error);
                        }
                        await _focusStore.SetFocusItemNotifiedAsync(item.Id); // always set notified for now to prevent massive notification spam
                    }
                }
                finally
                {
                    notifySemaphore.Release();
                }
            }
            else
            {
                // plan the notification anyways, even if the location might be updated, in case no update is received (low phone battery for example)
                // it will be ignored if any of the conditions (user location, traffic, event start time) changed
                await _butler.InstallAsync(new WebhookRequest()
                {
                    When = item.IndicateTime.Add(-FocusConstants.NotifyTime).UtcDateTime,
                    Data = new NotifyUserRequest()
                    {
                        UserId      = userId,
                        FocusItemId = item.Id
                    },
                    Url = options.NotifyUserCallbackUri
                });
            }
        }
コード例 #3
0
        private async Task <DateTimeOffset?> RequestLocationForItems(string userId, FocusManageResult manageResult, DateTimeOffset now, DateTimeOffset locationTimeStamp)
        {
            var candidates = manageResult.ActiveItems.Where(
                v => null != v.DirectionsMetadata &&
                null != v.Directions &&
                v.DirectionsMetadata.TravelStatus != TravelStatus.Finished);
            var requirement = UpdateTimes(candidates, now, locationTimeStamp).OrderBy(v => v.Time).FirstOrDefault();

            if (null != requirement)
            {
                await logger.LogForFocusItem(userId, requirement.FocusItem.Id, $"Location update for {requirement.Reason} {requirement.FocusItem.CalendarEvent?.Subject} at {requirement.Time:t}");

                if (requirement.Time < now + FocusConstants.ShortestLocationUpdateTime)
                {
                    return(now + FocusConstants.ShortestLocationUpdateTime);
                }
                return(requirement.Time);
            }
            return(null);
        }
コード例 #4
0
        private async Task <TransitDirections> GetFreshDirections(string userId, Event evt, FocusItem item, Location location)
        {
            string directionsKey = null;
            var    address       = await ResolveAddress(userId, evt);

            if (null != address && null != location)
            {
                try
                {
                    var start = new Coordinate()
                    {
                        Lat = location.Latitude,
                        Lng = location.Longitude
                    };
                    DateTimeOffset directionRequestTime = DateTimeOffset.Now;
                    if (item.DirectionsMetadata?.TravelStatus == TravelStatus.OnJourney)
                    {
                        directionRequestTime = location.Timestamp;
                    }
                    bool             requestWithNow   = evt.Start <= directionRequestTime;
                    DirectionsResult directionsResult = null;
                    const int        preferredRoute   = 0;
                    if (!requestWithNow)
                    {
                        directionsResult = await travelServiceClient.Users[userId].Directions.Transit.Get(start, address, evt.Start);
                        if (null != directionsResult.NotFound ||
                            directionsResult.TransitDirections.Routes[preferredRoute].DepatureTime < directionRequestTime)
                        {
                            requestWithNow = true;
                        }
                    }
                    if (requestWithNow)
                    {
                        directionsResult = await travelServiceClient.Users[userId].Directions.Transit.Get(start, address, null, directionRequestTime);
                    }
                    directionsKey = directionsResult?.CacheKey;
                    await focusStore.UpdateDirections(item.Id, directionsResult,
                                                      null != directionsResult.NotFound?null : (int?)preferredRoute);

                    item.DirectionsMetadata = new DirectionsMetadata()
                    {
                        Error         = directionsResult.NotFound?.Reason,
                        Key           = directionsResult.CacheKey,
                        PeferredRoute = preferredRoute
                    };
                    if (null == directionsResult.NotFound)
                    {
                        await travelServiceClient.Directions[directionsResult.CacheKey]
                        .Subscribe(new Uri(_options.DirectionsCallbackUri));
                    }
                    return(directionsResult.TransitDirections);
                }
                catch (TravelServiceException ex)
                {
                    await logger.LogForFocusItem(userId, item.Id, $"Error while retrieving directions for {evt.Subject}: {ex.Message}",
                                                 logLevel : LogLevel.Error);
                }
            }
            // TODO maybe clear directions with focusStore.UpdateDirections
            return(null);
        }