diff --git a/FarmmapsApiSamples/Constants.cs b/FarmmapsApiSamples/Constants.cs index 1d458b3..30f50f1 100644 --- a/FarmmapsApiSamples/Constants.cs +++ b/FarmmapsApiSamples/Constants.cs @@ -4,8 +4,10 @@ namespace FarmmapsApiSamples { public const string USERINPUT_ITEMTYPE = "vnd.farmmaps.itemtype.user.input"; public const string GEOTIFF_ITEMTYPE = "vnd.farmmaps.itemtype.geotiff"; + public const string GEOTIFF_PROCESSED_ITEMTYPE = "vnd.farmmaps.itemtype.geotiff.processed"; public const string CROPFIELD_ITEMTYPE = "vnd.farmmaps.itemtype.cropfield"; public const string SHAPE_PROCESSED_ITEMTYPE = "vnd.farmmaps.itemtype.shape.processed"; + public const string SHAPE_ITEMTYPE = "vnd.farmmaps.itemtype.shape"; public const string VRANBS_TASK = "vnd.farmmaps.task.vranbs"; } } \ No newline at end of file diff --git a/FarmmapsApiSamples/NbsApp.cs b/FarmmapsApiSamples/NbsApp.cs index 7f8d7a6..473ff3c 100644 --- a/FarmmapsApiSamples/NbsApp.cs +++ b/FarmmapsApiSamples/NbsApp.cs @@ -19,7 +19,7 @@ namespace FarmmapsApiSamples private readonly NitrogenService _nitrogenService; public NbsApp(ILogger logger, FarmmapsApiService farmmapsApiService, - FarmmapsEventHub farmmapsEventHub, NitrogenService nitrogenService) + FarmmapsEventHub farmmapsEventHub, NitrogenService nitrogenService) { _logger = logger; _farmmapsApiService = farmmapsApiService; @@ -39,49 +39,39 @@ namespace FarmmapsApiSamples try { var roots = await _farmmapsApiService.GetCurrentUserRootsAsync(); - - // upload data to Uploaded var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded"); - if (uploadedRoot != null) + var myDriveRoot = roots.SingleOrDefault(r => r.Name == "My drive"); + if (uploadedRoot == null || myDriveRoot == null) { - var dataPath = Path.Combine("Data", "Scan_1_20190605.zip"); - var result = await _farmmapsApiService.UploadFile(dataPath, uploadedRoot.Code, - progress => _logger.LogInformation($"Status: {progress.Status} - BytesSent: {progress.BytesSent}")); - - if (result.Progress.Status == UploadStatus.Failed) - { - _logger.LogError($"Uploading failed {result.Progress.Exception.Message}"); - return; - } - - // find file we need to use, we use delay as hack until events work correctly -// await Task.Delay(10000); - -// var isariaDataFilter = JObject.Parse(@""); -// var uploadedFilesChildren = await -// _farmmapsApiService.GetItemChildrenAsync(uploadedRoot.Code, SHAPE_PROCESSED_ITEMTYPE); - - // need to transform shape data to geotiff -// var shapeToGeotiffRequest = new TaskRequest() -// { -// TaskType = "vnd.farmmaps.task.shapetogeotiff" -// }; -// var taskCode = await _farmmapsApiService.QueueTaskAsync(, shapeToGeotiffRequest); - - - var myDriveRoot = roots.SingleOrDefault(r => r.Name == "My drive"); - if (myDriveRoot != null) - { - var cropfieldItem = await GetOrCreateCropfieldItem(myDriveRoot.Code); - - _logger.LogInformation($"Calculating targetN with targetYield: {60}"); - var targetN = await _nitrogenService.CalculateTargetN(cropfieldItem, 60); - _logger.LogInformation($"TargetN: {targetN}"); - - _logger.LogInformation("Calculating nitrogen map"); -// var nitrogenMapItem = CalculateNitrogenMap(cropfieldItem,, targetN); - } + _logger.LogError("Could not find a needed root item"); + return; } + + var dataPath = Path.Combine("Data", "Scan_1_20190605.zip"); + var result = await _farmmapsApiService.UploadFile(dataPath, uploadedRoot.Code, + progress => _logger.LogInformation($"Status: {progress.Status} - BytesSent: {progress.BytesSent}")); + + if (result.Progress.Status == UploadStatus.Failed) + { + _logger.LogError($"Uploading failed {result.Progress.Exception.Message}"); + return; + } + + var isariaGeotiffItem = await _nitrogenService.ProcessIsaria(uploadedRoot.Code,"Scan_1_20190605.zip"); + + // create and calculate target N + var cropfieldItem = await GetOrCreateCropfieldItemAsync(myDriveRoot.Code); + + _logger.LogInformation($"Calculating targetN with targetYield: {60}"); + var targetN = await _nitrogenService.CalculateTargetN(cropfieldItem, 60); + _logger.LogInformation($"TargetN: {targetN}"); + + _logger.LogInformation("Calculating nitrogen map"); + var nitrogenMapItem = + await _nitrogenService.CalculateNitrogenMap(cropfieldItem, isariaGeotiffItem, targetN); + + _logger.LogInformation("Downloading nitrogen map"); + await _farmmapsApiService.DownloadItemAsync(nitrogenMapItem.Code, $"{nitrogenMapItem.Name}.zip"); } catch (Exception ex) { @@ -89,7 +79,7 @@ namespace FarmmapsApiSamples } } - private async Task GetOrCreateCropfieldItem(string parentItemCode) + private async Task GetOrCreateCropfieldItemAsync(string parentItemCode) { var cropfieldItems = await _farmmapsApiService.GetItemChildrenAsync(parentItemCode, CROPFIELD_ITEMTYPE); @@ -101,7 +91,7 @@ namespace FarmmapsApiSamples var cropfieldItemRequest = new ItemRequest() { ParentCode = parentItemCode, - ItemType = "vnd.farmmaps.itemtype.cropfield", + ItemType = CROPFIELD_ITEMTYPE, Name = "Cropfield for VRA", DataDate = currentYear, DataEndDate = currentYear.AddYears(1), diff --git a/FarmmapsApiSamples/NitrogenService.cs b/FarmmapsApiSamples/NitrogenService.cs index cc94516..5157546 100644 --- a/FarmmapsApiSamples/NitrogenService.cs +++ b/FarmmapsApiSamples/NitrogenService.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Threading.Tasks; using FarmmapsApi.Models; @@ -21,6 +23,63 @@ namespace FarmmapsApiSamples _farmmapsApiService = farmmapsApiService; } + public async Task ProcessIsaria(string parentCode, string zipName) + { + // get processed isaria data (this can end in an infinite loop...) + // need better way of getting new items processed in a context... + Item isariaShapeItem = null; + await PollTask(TimeSpan.FromSeconds(3), async source => + { + _logger.LogInformation("Trying to get isaria data"); + var uploadedFilesChildren = await _farmmapsApiService.GetItemChildrenAsync(parentCode); + + var zipItems = uploadedFilesChildren.Where(i => i.Name == zipName); + var isariaTasks = new List>>(); + foreach (var zipItem in zipItems) + { + isariaTasks.Add(_farmmapsApiService.GetItemChildrenAsync(zipItem.Code, + SHAPE_PROCESSED_ITEMTYPE)); + } + + List[] items = await Task.WhenAll(isariaTasks); + if (items.Length > 0) + { + var nameWithoutExtension = Path.GetFileNameWithoutExtension(zipName); + var flatItems = items.SelectMany(i => i).Where(i => i.Name.Contains(nameWithoutExtension)).ToList(); + if (flatItems.Count > 0) + { + isariaShapeItem = flatItems.OrderByDescending(i => i.Created).First(); + source.Cancel(); + } + } + }); + + _logger.LogInformation("Found isaria data"); + _logger.LogInformation("Converting shape to geotiff"); + + // need to transform shape data to geotiff + var shapeToGeotiffRequest = new TaskRequest() + { + TaskType = "vnd.farmmaps.task.shapetogeotiff" + }; + var taskCode = await _farmmapsApiService.QueueTaskAsync(isariaShapeItem.Code, shapeToGeotiffRequest); + + await PollTask(TimeSpan.FromSeconds(3), async (tokenSource) => + { + _logger.LogInformation("Checking shapetogeotiff task status"); + var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(isariaShapeItem.Code, taskCode); + if (itemTaskStatus.State != ItemTaskState.Processing && itemTaskStatus.State != ItemTaskState.Scheduled) + tokenSource.Cancel(); + }); + + _logger.LogInformation("Isaria shape converted to geotiff"); + + // the parent of the shape item is now the tiff isaria item + isariaShapeItem = await _farmmapsApiService.GetItemAsync(isariaShapeItem.Code); + + return await _farmmapsApiService.GetItemAsync(isariaShapeItem.ParentCode); ; + } + /// /// Calculates TargetN, makes the assumption the cropfield and user.input(targetn) item have the same parent /// diff --git a/README.MD b/README.MD index 33c4519..b6a6328 100644 --- a/README.MD +++ b/README.MD @@ -1,3 +1,5 @@ +##### NOT PRODUCTION READY CODE, JUST AN EXAMPLE + Put your clientId and clientSecret in the appsettings.json. * Needs upload API.