public static async Task Run([TimerTrigger("0 */5 * * * *")] TimerInfo myTimer, [CosmosDB( databaseName: "FreeCosmosDB", collectionName: "TrackMe", ConnectionStringSetting = "CosmosDBForFree" )] IAsyncCollector <KMLInfo> asyncCollectorKMLInfo, [CosmosDB( databaseName: "FreeCosmosDB", collectionName: "TrackMe", ConnectionStringSetting = "CosmosDBForFree" )] DocumentClient documentClient, [CosmosDB( databaseName: "FreeCosmosDB", collectionName: "TrackMe", ConnectionStringSetting = "CosmosDBForFree", SqlQuery = "SELECT * FROM c WHERE c.groupid = 'user'" )] IEnumerable <InReachUser> inReachUsers, ExecutionContext context) { var config = new ConfigurationBuilder() .SetBasePath(context.FunctionAppDirectory) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); var SendEmailFunctionKey = config["SendEmailInReachFunctionKey"]; var SendEmailFunctionUrl = config["SendEmailFunctionUrl"]; var WebSiteUrl = config["WebSiteUrl"]; var TodayTrackId = config["TodayTrackId"]; var StorageContainerConnectionString = config["StorageContainerConnectionString"]; CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageContainerConnectionString); CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); Uri collectionUri = UriFactory.CreateDocumentCollectionUri("FreeCosmosDB", "TrackMe"); List <Emails> emails = new List <Emails>(); DateTime dateTimeUTC = DateTime.UtcNow.ToUniversalTime(); //getting active tracks from CosmosDB var query = new SqlQuerySpec("SELECT * FROM c WHERE (c.d1 < @dateTimeUTC and c.d2 > @dateTimeUTC) or c.id = @TodayTrack", new SqlParameterCollection(new SqlParameter[] { new SqlParameter { Name = "@dateTimeUTC", Value = dateTimeUTC }, new SqlParameter { Name = "@TodayTrack", Value = TodayTrackId } })); IEnumerable <KMLInfo> kMLInfos = documentClient.CreateDocumentQuery <KMLInfo>(collectionUri, query, new FeedOptions { EnableCrossPartitionQuery = true }).AsEnumerable(); //remove all duplicates by LastPointTimestamp and groupid field to make only one query to Garmin per user (if user has multiple Live tracks in same time) IEnumerable <KMLInfo> kMLInfoDeDups = kMLInfos.GroupBy(x => new { x.LastPointTimestamp, x.groupid }).Select(x => x.First()).ToList(); //getting feed from garmin, one feed for each user if LastpointTimestamp is same foreach (var kMLInfoDeDup in kMLInfoDeDups) { DateTime lastd1 = DateTime.SpecifyKind(DateTime.Parse(kMLInfoDeDup.d1, CultureInfo.InvariantCulture), DateTimeKind.Utc); DateTime today = DateTime.UtcNow.ToUniversalTime().AddDays(-1); //set d1 to LastPointTimestamp + 1 second (if LastTimestamp exist) to download the feed from that point forward from Garmin if (!string.IsNullOrEmpty(kMLInfoDeDup.LastPointTimestamp)) { kMLInfoDeDup.d1 = DateTime.Parse(kMLInfoDeDup.LastPointTimestamp, CultureInfo.InvariantCulture).AddSeconds(1).ToString("yyyy-MM-ddTHH:mm:ssZ"); } else { kMLInfoDeDup.d1 = DateTime.Parse(kMLInfoDeDup.d1, CultureInfo.InvariantCulture).ToString("yyyy-MM-ddTHH:mm:ssZ"); } //resetting Today's track, once at night according to user Timezone if (lastd1 < today && kMLInfoDeDup.id == TodayTrackId) { var dated1 = DateTime.UtcNow.ToUniversalTime().AddHours(kMLInfoDeDup.UserTimezone).ToString("yyyy-MM-dd"); var dateTimed1 = DateTime.Parse(dated1).AddHours(-kMLInfoDeDup.UserTimezone).ToString("yyyy-MM-ddTHH:mm:ssZ"); var dateTimed2 = DateTime.Parse(dated1).AddDays(1).AddHours(-kMLInfoDeDup.UserTimezone).ToString("yyyy-MM-ddTHH:mm:ssZ"); kMLInfoDeDup.d1 = dateTimed1; kMLInfoDeDup.d2 = dateTimed2; kMLInfoDeDup.LastPointTimestamp = ""; kMLInfoDeDup.LastLatitude = 0; kMLInfoDeDup.LastLongitude = 0; kMLInfoDeDup.LastTotalDistance = 0; kMLInfoDeDup.LastTotalTime = ""; kMLInfoDeDup.TrackStartTime = ""; await asyncCollectorKMLInfo.AddAsync(kMLInfoDeDup); //delete Today's blobs foreach (var blob in helperKMLParse.Blobs) { var blobName = $"{kMLInfoDeDup.groupid}/{kMLInfoDeDup.id}/{blob.BlobName}.kml"; await helperKMLParse.RemoveBlobAsync(blobName, blobClient); } } //getting always only last point from garmin (except if new day with active tracking has started) HelperGetKMLFromGarmin GetKMLFromGarmin = new HelperGetKMLFromGarmin(); var kmlFeedresult = await GetKMLFromGarmin.GetKMLAsync(kMLInfoDeDup); kMLInfoDeDup.LastPoint = kmlFeedresult; } foreach (var kMLInfo in kMLInfos) { var kmlFeedresult = kMLInfoDeDups.First(x => x.groupid == kMLInfo.groupid).LastPoint; //if there are new points, then load whole track from database and add the point if (helperKMLParse.IsThereNewPoints(kmlFeedresult, kMLInfo)) { var user = new InReachUser(); foreach (var usr in inReachUsers) { if (usr.userWebId == kMLInfo.groupid) { user = usr; break; } } //open KML feeds from Blobstorage var blobs = helperKMLParse.Blobs; foreach (var blob in blobs) { var blobName = $"{kMLInfo.groupid}/{kMLInfo.id}/{blob.BlobName}.kml"; blob.BlobValue = await helperKMLParse.GetFromBlobAsync(blobName, blobClient); } //process the full track helperKMLParse.ParseKMLFile(kmlFeedresult, kMLInfo, blobs, emails, user, WebSiteUrl); kMLInfo.d1 = DateTime.Parse(kMLInfo.d1, CultureInfo.InvariantCulture).ToString("yyyy-MM-ddTHH:mm:ssZ"); kMLInfo.d2 = DateTime.Parse(kMLInfo.d2, CultureInfo.InvariantCulture).ToString("yyyy-MM-ddTHH:mm:ssZ"); await asyncCollectorKMLInfo.AddAsync(kMLInfo); //save blobs foreach (var blob in blobs) { var blobName = $"{kMLInfo.groupid}/{kMLInfo.id}/{blob.BlobName}.kml"; await helperKMLParse.AddToBlobAsync(blobName, blob.BlobValue, blobClient); } } } //remove all duplicates by DateTime field and sending the list to SendEmailFunction if (emails.Any()) { List <Emails> emailList = emails.GroupBy(x => x.DateTime).Select(x => x.First()).ToList(); HttpClient client = new HttpClient(); Uri SendEmailFunctionUri = new Uri($"{SendEmailFunctionUrl}?code={SendEmailFunctionKey}"); var returnMessage = await client.PostAsJsonAsync(SendEmailFunctionUri, emailList); } }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req, [CosmosDB( databaseName: "FreeCosmosDB", collectionName: "TrackMe", ConnectionStringSetting = "CosmosDBForFree" )] IAsyncCollector <KMLInfo> asyncCollectorKMLInfo, [CosmosDB( databaseName: "FreeCosmosDB", collectionName: "TrackMe", ConnectionStringSetting = "CosmosDBForFree", SqlQuery = "SELECT * FROM c WHERE c.groupid = 'user'" )] IEnumerable <InReachUser> inReachUsers, ExecutionContext context ) { var config = new ConfigurationBuilder() .SetBasePath(context.FunctionAppDirectory) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); var StorageContainerConnectionString = config["StorageContainerConnectionString"]; CloudStorageAccount storageAccount = CloudStorageAccount.Parse(StorageContainerConnectionString); CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); ClaimsPrincipal Identities = req.HttpContext.User; var checkUser = new HelperCheckUser(); var LoggedInUser = checkUser.LoggedInUser(inReachUsers, Identities); var IsAuthenticated = false; if (LoggedInUser.status == Status.ExistingUser) { IsAuthenticated = true; } if (IsAuthenticated) { string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); if (requestBody != "") { var kMLFull = JsonConvert.DeserializeObject <KMLFull>(requestBody); KMLInfo kMLInfo = new KMLInfo() { id = kMLFull.id, Title = kMLFull.Title, d1 = kMLFull.d1, d2 = kMLFull.d2, InReachWebAddress = kMLFull.InReachWebAddress, InReachWebPassword = kMLFull.InReachWebPassword, UserTimezone = kMLFull.UserTimezone }; var blobs = helperKMLParse.Blobs; blobs.ForEach(x => x.BlobValue = ""); blobs.First(x => x.BlobName == "plannedtrack").BlobValue = kMLFull.PlannedTrack; //1. replace ö->o ä->a etc //2. first: UrlEncode is removing all weird charactes and spaces //3. second: HttpUtility.UrlEncode is removing some not named weird characters, just in case //4. third: UrlEncode again is removing possible %-marks //setting id field only on initial track creation if (string.IsNullOrEmpty(kMLInfo.id)) { string id = RemoveDiacritics(kMLInfo.Title); id = UrlEncode(HttpUtility.UrlEncode(UrlEncode(id))); kMLInfo.id = id; } kMLInfo.LastPointTimestamp = ""; kMLInfo.groupid = LoggedInUser.userWebId; kMLInfo.IsLongTrack = false; var dateD1 = DateTime.Parse(kMLInfo.d1).AddHours(-kMLInfo.UserTimezone); var dateD2 = DateTime.Parse(kMLInfo.d2).AddDays(1).AddHours(-kMLInfo.UserTimezone); TimeSpan timeSpan = dateD2 - dateD1; //this setting affects of parsing all points (slow) or not. Depending on the duration of the track if (timeSpan.TotalDays > 2) { kMLInfo.IsLongTrack = true; } kMLInfo.d1 = dateD1.ToString("yyyy-MM-ddTHH:mm:ssZ"); kMLInfo.d2 = dateD2.ToString("yyyy-MM-ddTHH:mm:ssZ"); HelperGetKMLFromGarmin helperGetKMLFromGarmin = new HelperGetKMLFromGarmin(); //get feed grom garmin var kmlFeedresult = await helperGetKMLFromGarmin.GetKMLAsync(kMLInfo); //parse and transform the feed and save to database helperKMLParse.ParseKMLFile(kmlFeedresult, kMLInfo, blobs, new List <Emails>(), LoggedInUser); await asyncCollectorKMLInfo.AddAsync(kMLInfo); //save blobs foreach (var blob in blobs) { var blobName = $"{kMLInfo.groupid}/{kMLInfo.id}/{blob.BlobName}.kml"; await helperKMLParse.AddToBlobAsync(blobName, blob.BlobValue, blobClient); } } } return(new OkObjectResult(IsAuthenticated)); }
static async Task ManageTodayTrack(InReachUser LoggedInUser, IAsyncCollector <KMLInfo> addDocuments, DocumentClient client, Uri collectionUri, string TodayTrackId, string SendEmailFunctionUrl, string SendEmailFunctionKey, string WebSiteUrl, CloudBlobClient blobClient) { var dated1 = DateTime.UtcNow.ToUniversalTime().ToString("yyyy-MM-dd"); var dated2 = DateTime.UtcNow.ToUniversalTime().ToString("yyyy-MM-dd"); var dateTimed1 = DateTime.Parse(dated1).AddHours(-LoggedInUser.UserTimezone).ToString("yyyy-MM-ddTHH:mm:ssZ"); var dateTimed2 = DateTime.Parse(dated2).AddDays(1).AddHours(-LoggedInUser.UserTimezone).ToString("yyyy-MM-ddTHH:mm:ssZ"); KMLInfo kMLInfo = new KMLInfo() { id = TodayTrackId, Title = "Today's Live Track", d1 = dateTimed1, d2 = dateTimed2, groupid = LoggedInUser.userWebId, InReachWebAddress = LoggedInUser.InReachWebAddress, InReachWebPassword = LoggedInUser.InReachWebPassword, UserTimezone = LoggedInUser.UserTimezone, IsLongTrack = false }; //create Today's track if (LoggedInUser.Active) { HelperGetKMLFromGarmin helperGetKMLFromGarmin = new HelperGetKMLFromGarmin(); var emails = new List <Emails>(); //get feed grom garmin var kmlFeedresult = await helperGetKMLFromGarmin.GetKMLAsync(kMLInfo); var blobs = helperKMLParse.Blobs; //parse and transform the feed and save to database helperKMLParse.ParseKMLFile(kmlFeedresult, kMLInfo, blobs, emails, LoggedInUser, WebSiteUrl); await addDocuments.AddAsync(kMLInfo); //save blobs foreach (var blob in blobs) { var blobName = $"{kMLInfo.groupid}/{kMLInfo.id}/{blob.BlobName}.kml"; await helperKMLParse.AddToBlobAsync(blobName, blob.BlobValue, blobClient); } //sending out emails if (emails.Any()) { HttpClient httpClient = new HttpClient(); Uri SendEmailFunctionUri = new Uri($"{SendEmailFunctionUrl}?code={SendEmailFunctionKey}"); var returnMessage = await httpClient.PostAsJsonAsync(SendEmailFunctionUri, emails); } } //delete Today's track if (!LoggedInUser.Active) { //select and delete document var queryOne = new SqlQuerySpec("SELECT c._self, c.groupid, c.id FROM c WHERE c.id = @id", new SqlParameterCollection(new SqlParameter[] { new SqlParameter { Name = "@id", Value = kMLInfo.id } })); KMLInfo kML = client.CreateDocumentQuery(collectionUri, queryOne, new FeedOptions { PartitionKey = new PartitionKey(kMLInfo.groupid) }).AsEnumerable().FirstOrDefault(); if (!(kML is null)) { //delete metadata await client.DeleteDocumentAsync(kML._self, new RequestOptions { PartitionKey = new PartitionKey(kML.groupid) }); //delete blobs foreach (var blob in helperKMLParse.Blobs) { var blobName = $"{kML.groupid}/{kML.id}/{blob.BlobName}.kml"; await helperKMLParse.RemoveBlobAsync(blobName, blobClient); } } } }