From 6dea82b97385a615c160f89ece8315d649af21a7 Mon Sep 17 00:00:00 2001 From: Mark van der Wal Date: Wed, 8 Apr 2020 19:28:30 +0200 Subject: [PATCH] Refactored some nitrogen methods. --- FarmmapsApiSamples/Application.cs | 52 --------- .../Data/{ => Herbicide}/Lutum.tiff | Bin .../Data/{ => Herbicide}/vd_born_lutum.zip | Bin .../Data/{ => Herbicide}/vd_born_om.zip | Bin .../Data/{ => Nbs}/Scan_1_20190605.zip | Bin FarmmapsApiSamples/HerbicideService.cs | 10 +- FarmmapsApiSamples/IApp.cs | 9 -- FarmmapsApiSamples/NitrogenService.cs | 109 +++++++----------- FarmmapsApiSamples/Program.cs | 45 +++++++- README.MD | 5 +- 10 files changed, 96 insertions(+), 134 deletions(-) delete mode 100644 FarmmapsApiSamples/Application.cs rename FarmmapsApiSamples/Data/{ => Herbicide}/Lutum.tiff (100%) rename FarmmapsApiSamples/Data/{ => Herbicide}/vd_born_lutum.zip (100%) rename FarmmapsApiSamples/Data/{ => Herbicide}/vd_born_om.zip (100%) rename FarmmapsApiSamples/Data/{ => Nbs}/Scan_1_20190605.zip (100%) delete mode 100644 FarmmapsApiSamples/IApp.cs diff --git a/FarmmapsApiSamples/Application.cs b/FarmmapsApiSamples/Application.cs deleted file mode 100644 index 318764e..0000000 --- a/FarmmapsApiSamples/Application.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Threading.Tasks; -using FarmmapsApi.Models; -using FarmmapsApi.Services; -using Microsoft.Extensions.Logging; - -namespace FarmmapsApiSamples -{ - public class Application : IApp - { - private readonly ILogger _logger; - private readonly FarmmapsApiService _farmmapsApiService; - private readonly FarmmapsEventHub _farmmapsEventHub; - private readonly NitrogenService _nitrogenService; - private readonly HerbicideService _herbicideService; - - public Application(ILogger logger, FarmmapsApiService farmmapsApiService, - FarmmapsEventHub farmmapsEventHub, NitrogenService nitrogenService, - HerbicideService herbicideService) - { - _logger = logger; - _farmmapsApiService = farmmapsApiService; - _farmmapsEventHub = farmmapsEventHub; - _nitrogenService = nitrogenService; - _herbicideService = herbicideService; - - _farmmapsEventHub.EventCallback += OnEvent; - } - - private void OnEvent(EventMessage @event) - { -// _logger.LogInformation(@event.EventType); - } - - public async Task RunAsync() - { - try - { - // !! this call is needed the first time an api is called with a fresh clientid and secret !! - await _farmmapsApiService.GetCurrentUserCodeAsync(); - var roots = await _farmmapsApiService.GetCurrentUserRootsAsync(); - - await _nitrogenService.TestFlow(roots); -// await _herbicideService.TestFlow(roots); - } - catch (Exception ex) - { - _logger.LogError(ex.Message); - } - } - } -} \ No newline at end of file diff --git a/FarmmapsApiSamples/Data/Lutum.tiff b/FarmmapsApiSamples/Data/Herbicide/Lutum.tiff similarity index 100% rename from FarmmapsApiSamples/Data/Lutum.tiff rename to FarmmapsApiSamples/Data/Herbicide/Lutum.tiff diff --git a/FarmmapsApiSamples/Data/vd_born_lutum.zip b/FarmmapsApiSamples/Data/Herbicide/vd_born_lutum.zip similarity index 100% rename from FarmmapsApiSamples/Data/vd_born_lutum.zip rename to FarmmapsApiSamples/Data/Herbicide/vd_born_lutum.zip diff --git a/FarmmapsApiSamples/Data/vd_born_om.zip b/FarmmapsApiSamples/Data/Herbicide/vd_born_om.zip similarity index 100% rename from FarmmapsApiSamples/Data/vd_born_om.zip rename to FarmmapsApiSamples/Data/Herbicide/vd_born_om.zip diff --git a/FarmmapsApiSamples/Data/Scan_1_20190605.zip b/FarmmapsApiSamples/Data/Nbs/Scan_1_20190605.zip similarity index 100% rename from FarmmapsApiSamples/Data/Scan_1_20190605.zip rename to FarmmapsApiSamples/Data/Nbs/Scan_1_20190605.zip diff --git a/FarmmapsApiSamples/HerbicideService.cs b/FarmmapsApiSamples/HerbicideService.cs index 8a1cf11..c42216a 100644 --- a/FarmmapsApiSamples/HerbicideService.cs +++ b/FarmmapsApiSamples/HerbicideService.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using FarmmapsApi.Models; using FarmmapsApi.Services; using FarmmapsApiSamples.Models; -using Google.Apis.Upload; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -80,7 +79,8 @@ namespace FarmmapsApiSamples var cropfieldItem = await CreateCropfieldSingleLutumItemAsync(myDrive.Code); _logger.LogInformation("Uploading data"); - var inputItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE, Path.Combine("Data", "Lutum.tiff"), "Lutum.tiff"); + var filePath = Path.Combine("Data", "Herbicide", "Lutum.tiff"); + var inputItem = await _generalService.UploadDataAsync(uploadedRoot, GEOTIFF_PROCESSED_ITEMTYPE, filePath, "Lutum.tiff"); if(inputItem == null) { _logger.LogError($"Failed to upload data"); @@ -120,7 +120,8 @@ namespace FarmmapsApiSamples // upload data _logger.LogInformation("Uploading lutum data"); - var inputItem = await _generalService.UploadZipWithShapeAsync(uploadedRoot, Path.Combine("Data", "vd_born_lutum.zip"), "Lutum"); + var inputItem = await _generalService.UploadZipWithShapeAsync(uploadedRoot, + Path.Combine("Data", "Herbicide", "vd_born_lutum.zip"), "Lutum"); if(inputItem == null) { _logger.LogError($"Failed to upload lutum data"); @@ -128,7 +129,8 @@ namespace FarmmapsApiSamples } _logger.LogInformation("Uploading organic matter data"); - var inputExtraItem = await _generalService.UploadZipWithShapeAsync(uploadedRoot, Path.Combine("Data", "vd_born_om.zip"), "OS"); + var inputExtraItem = await _generalService.UploadZipWithShapeAsync(uploadedRoot, + Path.Combine("Data", "Herbicide", "vd_born_om.zip"), "OS"); if(inputExtraItem == null) { _logger.LogError($"Failed to upload organic matter data"); diff --git a/FarmmapsApiSamples/IApp.cs b/FarmmapsApiSamples/IApp.cs deleted file mode 100644 index 8390891..0000000 --- a/FarmmapsApiSamples/IApp.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace FarmmapsApiSamples -{ - public interface IApp - { - Task RunAsync(); - } -} \ No newline at end of file diff --git a/FarmmapsApiSamples/NitrogenService.cs b/FarmmapsApiSamples/NitrogenService.cs index 72fb9a1..d8481f0 100644 --- a/FarmmapsApiSamples/NitrogenService.cs +++ b/FarmmapsApiSamples/NitrogenService.cs @@ -50,9 +50,10 @@ namespace FarmmapsApiSamples return; } - var cropfieldItem = await GetOrCreateCropfieldItemAsync(myDriveRoot.Code); - - var dataPath = Path.Combine("Data", "Scan_1_20190605.zip"); + var cropfieldItem = await CreateCropfieldItemAsync(myDriveRoot.Code, "VRA NBS cropfield", 2020, + @"{ ""type"": ""Polygon"", ""coordinates"": [ [ [ 3.40843828875524, 50.638966444680605 ], [ 3.408953272886064, 50.639197789621612 ], [ 3.409242951459603, 50.639469958681836 ], [ 3.409328782148028, 50.639612846807708 ], [ 3.409457528180712, 50.639789755314411 ], [ 3.409639918393741, 50.640014292074966 ], [ 3.409833037442765, 50.640211611372706 ], [ 3.410069071836049, 50.640395321698435 ], [ 3.410380208081761, 50.640572227259661 ], [ 3.410605513638958, 50.640715112034222 ], [ 3.411925160474145, 50.641177783561204 ], [ 3.411935889310142, 50.640728720085136 ], [ 3.412590348309737, 50.63948356709389 ], [ 3.413244807309242, 50.638224772339846 ], [ 3.413400375432099, 50.637901562841307 ], [ 3.413539850300779, 50.637449065809889 ], [ 3.413475477284437, 50.637418445552932 ], [ 3.40999396998362, 50.637449065810451 ], [ 3.409940325803365, 50.638102293212661 ], [ 3.409575545377398, 50.638483338338325 ], [ 3.409060561246574, 50.638707881340494 ], [ 3.40843828875524, 50.638966444680605 ] ] ] }"); + + var dataPath = Path.Combine("Data", "Nbs", "Scan_1_20190605.zip"); var isariaShapeItem = await _generalService.UploadZipWithShapeAsync(uploadedRoot, dataPath, "Scan_1_20190605"); if (isariaShapeItem == null) { @@ -60,6 +61,7 @@ namespace FarmmapsApiSamples return; } + _logger.LogInformation($"Converting shape to geotiff"); var isariaGeotiffItem = await _generalService.ShapeToGeotiff(isariaShapeItem); if (isariaGeotiffItem == null) { @@ -68,7 +70,8 @@ namespace FarmmapsApiSamples } _logger.LogInformation($"Calculating targetN with targetYield: {60}"); - var targetN = await CalculateTargetN(cropfieldItem, plantingDate, measurementDate, 60); + var targetNItem = await CreateTargetNItem(cropfieldItem); + var targetN = await CalculateTargetN(cropfieldItem, targetNItem, plantingDate, measurementDate, "consumption", "irmi", 60); _logger.LogInformation($"TargetN: {targetN}"); _logger.LogInformation("Calculating uptake map"); @@ -80,35 +83,39 @@ namespace FarmmapsApiSamples _logger.LogInformation("Calculating appliance map"); var applianceMapItem = - await CalculateApplicationMap(cropfieldItem, isariaGeotiffItem, plantingDate, measurementDate, targetN); + await CalculateApplicationMap(cropfieldItem, isariaGeotiffItem, plantingDate, measurementDate, "irmi", targetN); _logger.LogInformation("Downloading appliance map"); await _farmmapsApiService.DownloadItemAsync(applianceMapItem.Code, Path.Combine(downloadFolder, $"{applianceMapItem.Name}.zip")); } - private async Task GetOrCreateCropfieldItemAsync(string parentItemCode) + private async Task CreateCropfieldItemAsync(string parentItemCode, string name, int year, string fieldGeomJson) { - var cropfieldItems = await - _farmmapsApiService.GetItemChildrenAsync(parentItemCode, CROPFIELD_ITEMTYPE); - - if (cropfieldItems.Count > 0) - return cropfieldItems[0]; - - var currentYear = new DateTime(DateTime.UtcNow.Year, 1, 1); + var currentYear = new DateTime(year, 1, 1); var cropfieldItemRequest = new ItemRequest() { ParentCode = parentItemCode, ItemType = CROPFIELD_ITEMTYPE, - Name = "Cropfield for VRA", + Name = name, DataDate = currentYear, DataEndDate = currentYear.AddYears(1).AddDays(-1), Data = JObject.Parse("{}"), - Geometry = JObject.Parse( - @"{ ""type"": ""Polygon"", ""coordinates"": [ [ [ 3.40843828875524, 50.638966444680605 ], [ 3.408953272886064, 50.639197789621612 ], [ 3.409242951459603, 50.639469958681836 ], [ 3.409328782148028, 50.639612846807708 ], [ 3.409457528180712, 50.639789755314411 ], [ 3.409639918393741, 50.640014292074966 ], [ 3.409833037442765, 50.640211611372706 ], [ 3.410069071836049, 50.640395321698435 ], [ 3.410380208081761, 50.640572227259661 ], [ 3.410605513638958, 50.640715112034222 ], [ 3.411925160474145, 50.641177783561204 ], [ 3.411935889310142, 50.640728720085136 ], [ 3.412590348309737, 50.63948356709389 ], [ 3.413244807309242, 50.638224772339846 ], [ 3.413400375432099, 50.637901562841307 ], [ 3.413539850300779, 50.637449065809889 ], [ 3.413475477284437, 50.637418445552932 ], [ 3.40999396998362, 50.637449065810451 ], [ 3.409940325803365, 50.638102293212661 ], [ 3.409575545377398, 50.638483338338325 ], [ 3.409060561246574, 50.638707881340494 ], [ 3.40843828875524, 50.638966444680605 ] ] ] }") + Geometry = JObject.Parse(fieldGeomJson) }; return await _farmmapsApiService.CreateItemAsync(cropfieldItemRequest); } + + public async Task CreateTargetNItem(Item cropfieldItem) + { + var itemRequest = new ItemRequest() + { + ParentCode = cropfieldItem.ParentCode, + ItemType = USERINPUT_ITEMTYPE, + Name = "TargetN" + }; + return await _farmmapsApiService.CreateItemAsync(itemRequest); + } /// /// Calculates TargetN, makes the assumption the cropfield and user.input(targetn) item have the same parent @@ -118,31 +125,16 @@ namespace FarmmapsApiSamples /// The date the crop is planted /// The date the measurements are taken /// The TargetN - public async Task CalculateTargetN(Item cropfieldItem, DateTime plantingDate, - DateTime measurementDate, int targetYield) + public async Task CalculateTargetN(Item cropfieldItem, Item targetNItem, DateTime plantingDate, + DateTime measurementDate, string inputType, string purposeType, int targetYield) { - var targetNItems = await - _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.ParentCode, USERINPUT_ITEMTYPE); - - Item targetNItem; - if (targetNItems.Count == 0) - { - _logger.LogInformation("Creating targetN item"); - var itemRequest = CreateTargetNItemRequest(cropfieldItem.ParentCode); - targetNItem = await _farmmapsApiService.CreateItemAsync(itemRequest); - } - else - { - targetNItem = targetNItems[0]; - } - var nbsTargetNRequest = new TaskRequest {TaskType = VRANBS_TASK}; nbsTargetNRequest.attributes["operation"] = "targetn"; nbsTargetNRequest.attributes["inputCode"] = targetNItem.Code; nbsTargetNRequest.attributes["plantingDate"] = plantingDate.ToString(); nbsTargetNRequest.attributes["measurementDate"] = measurementDate.ToString(); - nbsTargetNRequest.attributes["inputType"] = "irmi"; - nbsTargetNRequest.attributes["purposeType"] = "consumption"; + nbsTargetNRequest.attributes["inputType"] = inputType; + nbsTargetNRequest.attributes["purposeType"] = purposeType.ToLower(); nbsTargetNRequest.attributes["targetYield"] = targetYield.ToString(); string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsTargetNRequest); @@ -176,14 +168,14 @@ namespace FarmmapsApiSamples /// The date the measurements are taken /// public async Task CalculateUptakeMap(Item cropfieldItem, Item inputItem, DateTime plantingDate, - DateTime measurementDate) + DateTime measurementDate, string inputType = "irmi") { var nbsUptakeMapRequest = new TaskRequest {TaskType = VRANBS_TASK}; nbsUptakeMapRequest.attributes["operation"] = "uptake"; nbsUptakeMapRequest.attributes["inputCode"] = inputItem.Code; nbsUptakeMapRequest.attributes["plantingDate"] = plantingDate.ToString(); nbsUptakeMapRequest.attributes["measurementDate"] = measurementDate.ToString(); - nbsUptakeMapRequest.attributes["inputType"] = "irmi"; + nbsUptakeMapRequest.attributes["inputType"] = inputType.ToLower(); string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsUptakeMapRequest); @@ -200,21 +192,19 @@ namespace FarmmapsApiSamples _logger.LogError($"Something went wrong with task execution: {itemTask.Message}"); return null; } - - var geotiffItems = await - _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.Code, GEOTIFF_PROCESSED_ITEMTYPE); - - // maybe poll here to, to wait for geotiff task process to be finished? - // how to uniquely know which item is really created!? - var nitrogenItem = geotiffItems.SingleOrDefault(i => i.Name.Contains("uptake") && i.Updated >= itemTask.Finished); - if (nitrogenItem == null) + var itemName = "VRANbs uptake"; + var uptakeMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code, + GEOTIFF_PROCESSED_ITEMTYPE, itemName, + i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) && + i.Name.ToLower().Contains(itemName.ToLower())); + if (uptakeMapItem == null) { _logger.LogError("Could not find the uptake geotiff child item under cropfield"); return null; } - return nitrogenItem; + return uptakeMapItem; } @@ -225,10 +215,11 @@ namespace FarmmapsApiSamples /// The farmmaps item containing the geotiff data /// The date the crop is planted /// The date the measurements are taken + /// The inputtype to use /// The target nitrogen to use for the calculations /// public async Task CalculateApplicationMap(Item cropfieldItem, Item inputItem, DateTime plantingDate, - DateTime measurementDate, double targetN) + DateTime measurementDate, string inputType = "irmi", double targetN = 60.0) { var nbsApplianceMapRequest = new TaskRequest {TaskType = VRANBS_TASK}; nbsApplianceMapRequest.attributes["operation"] = "application"; @@ -236,7 +227,7 @@ namespace FarmmapsApiSamples nbsApplianceMapRequest.attributes["plantingDate"] = plantingDate.ToString(); nbsApplianceMapRequest.attributes["measurementDate"] = measurementDate.ToString(); nbsApplianceMapRequest.attributes["inputCode"] = inputItem.Code; - nbsApplianceMapRequest.attributes["inputType"] = "irmi"; + nbsApplianceMapRequest.attributes["inputType"] = inputType.ToLower(); nbsApplianceMapRequest.attributes["targetN"] = targetN.ToString(CultureInfo.InvariantCulture); string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, nbsApplianceMapRequest); @@ -254,14 +245,12 @@ namespace FarmmapsApiSamples _logger.LogError($"Something went wrong with task execution: {itemTask.Message}"); return null; } - - var geotiffItems = await - _farmmapsApiService.GetItemChildrenAsync(cropfieldItem.Code, GEOTIFF_PROCESSED_ITEMTYPE); - - // maybe poll here too, to wait for geotiff task process to be finished? - // how to uniquely know which item is really created!? - var applianceMapItem = geotiffItems.SingleOrDefault(i => i.Name.Contains("nitrogen") && i.Updated >= itemTask.Finished); + var itemName = $"VRANbs application"; + var applianceMapItem = await _generalService.FindChildItemAsync(cropfieldItem.Code, + GEOTIFF_PROCESSED_ITEMTYPE, itemName, + i => i.Updated >= itemTask.Finished.GetValueOrDefault(DateTime.UtcNow) && + i.Name.ToLower().Contains(itemName.ToLower())); if (applianceMapItem == null) { _logger.LogError("Could not find the application map geotiff child item under cropfield"); @@ -270,15 +259,5 @@ namespace FarmmapsApiSamples return applianceMapItem; } - - private ItemRequest CreateTargetNItemRequest(string parentItemCode) - { - return new ItemRequest() - { - ParentCode = parentItemCode, - ItemType = USERINPUT_ITEMTYPE, - Name = "TargetN" - }; - } } } \ No newline at end of file diff --git a/FarmmapsApiSamples/Program.cs b/FarmmapsApiSamples/Program.cs index 764b26c..55e7675 100644 --- a/FarmmapsApiSamples/Program.cs +++ b/FarmmapsApiSamples/Program.cs @@ -11,6 +11,12 @@ namespace FarmmapsApiSamples { class Program { + private readonly ILogger _logger; + private readonly FarmmapsApiService _farmmapsApiService; + private readonly FarmmapsEventHub _farmmapsEventHub; + private readonly NitrogenService _nitrogenService; + private readonly HerbicideService _herbicideService; + private static async Task Main(string[] args) { IConfiguration config = new ConfigurationBuilder() @@ -26,12 +32,47 @@ namespace FarmmapsApiSamples .AddFarmmapsServices(configuration) .AddTransient() .AddTransient() - .AddSingleton() + .AddSingleton() .BuildServiceProvider(); await serviceProvider.GetService().AuthenticateAsync(); // await serviceProvider.GetService().StartEventHub(); - await serviceProvider.GetService().RunAsync(); + await serviceProvider.GetService().RunAsync(); + } + + public Program(ILogger logger, FarmmapsApiService farmmapsApiService, + FarmmapsEventHub farmmapsEventHub, NitrogenService nitrogenService, + HerbicideService herbicideService) + { + _logger = logger; + _farmmapsApiService = farmmapsApiService; + _farmmapsEventHub = farmmapsEventHub; + _nitrogenService = nitrogenService; + _herbicideService = herbicideService; + + _farmmapsEventHub.EventCallback += OnEvent; + } + + private void OnEvent(EventMessage @event) + { +// _logger.LogInformation(@event.EventType); + } + + public async Task RunAsync() + { + try + { + // !! this call is needed the first time an api is called with a fresh clientid and secret !! + await _farmmapsApiService.GetCurrentUserCodeAsync(); + var roots = await _farmmapsApiService.GetCurrentUserRootsAsync(); + + await _nitrogenService.TestFlow(roots); +// await _herbicideService.TestFlow(roots); + } + catch (Exception ex) + { + _logger.LogError(ex.Message); + } } } } \ No newline at end of file diff --git a/README.MD b/README.MD index b6a6328..3eb0045 100644 --- a/README.MD +++ b/README.MD @@ -2,5 +2,6 @@ Put your clientId and clientSecret in the appsettings.json. -* Needs upload API. -* Needs testing of all public api methods. \ No newline at end of file +* Isn't 100% complete. +* Needs proper testing of all public api methods. +* Needs documentation of all public api methods. \ No newline at end of file