From c02b232837f59d01852f246274d00476506a7e0b Mon Sep 17 00:00:00 2001 From: Riepma Date: Fri, 12 Feb 2021 17:10:25 +0100 Subject: [PATCH] Added Taskmap sample code to potenAPI --- FarmmapsApi/Services/GeneralService.cs | 48 ++++++++++++++++++++- FarmmapsPoten/FarmmapsPoten.csproj | 3 -- FarmmapsPoten/Models/PotenInput.cs | 13 +++++- FarmmapsPoten/PotenApplication.cs | 35 +++++++++++++-- FarmmapsPoten/PotenInput.json | 59 +++++++++++++++++--------- FarmmapsPoten/PotenService.cs | 46 +++++++++++++++++++- 6 files changed, 170 insertions(+), 34 deletions(-) diff --git a/FarmmapsApi/Services/GeneralService.cs b/FarmmapsApi/Services/GeneralService.cs index 6bb9c76..d1556b1 100644 --- a/FarmmapsApi/Services/GeneralService.cs +++ b/FarmmapsApi/Services/GeneralService.cs @@ -38,7 +38,7 @@ namespace FarmmapsApi.Services } public async Task UploadDataAsync(UserRoot root, string itemType, string filePath, string itemName) { - var startUpload = DateTime.UtcNow; + var startUpload = DateTime.UtcNow.AddSeconds(-3); var result = await _farmmapsApiService.UploadFile(filePath, root.Code, progress => _logger.LogInformation($"Status: {progress.Status} - BytesSent: {progress.BytesSent}")); @@ -74,6 +74,10 @@ namespace FarmmapsApi.Services public async Task GeotiffToShape(Item tiffItem) { var taskmapRequest = new TaskRequest { TaskType = TASKMAP_TASK }; + + taskmapRequest.attributes["cellWidth"] = "3"; + taskmapRequest.attributes["cellHeight"] = "1"; + taskmapRequest.attributes["angle"] = "0"; string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(tiffItem.Code, taskmapRequest); @@ -92,7 +96,7 @@ namespace FarmmapsApi.Services //the taskmap is a child of the input tiff var itemName = "Taskmap"; - var taskMapItem = await FindChildItemAsync(tiffItem.Code, + var taskMapItem = await FindChildItemAsync(tiffItem.ParentCode, SHAPE_PROCESSED_ITEMTYPE, itemName); if (taskMapItem == null) { _logger.LogError("Could not find the shape taskmap as a child item under the input"); @@ -102,6 +106,46 @@ namespace FarmmapsApi.Services return taskMapItem; } + // Create taskmap based on width, height and direction + public async Task CreateTaskmap(Item tiffItem, string cellWidth, string cellHeight, string startPoint, string endPoint = null, string angle = null) + { + var taskmapRequest = new TaskRequest { TaskType = TASKMAP_TASK }; + taskmapRequest.attributes["inputCode"] = tiffItem.Code; + taskmapRequest.attributes["cellWidth"] = cellWidth; //metres + taskmapRequest.attributes["cellHeight"] = cellHeight; //metres + taskmapRequest.attributes["startPoint"] = startPoint; // Coordinates WGS84 + if (angle == null) taskmapRequest.attributes["endPoint"] = endPoint; // Coordinates WGS84 + if (endPoint == null) taskmapRequest.attributes["angle"] = angle; // degrees between 0.0 and 360.0 + + string itemTaskCode = await _farmmapsApiService.QueueTaskAsync(tiffItem.Code, taskmapRequest); + + await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => { + var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(tiffItem.Code, itemTaskCode); + _logger.LogInformation($"Waiting on conversion to Taskmap; status: {itemTaskStatus.State}"); + if (itemTaskStatus.IsFinished) + tokenSource.Cancel(); + }); + + var itemTask = await _farmmapsApiService.GetTaskStatusAsync(tiffItem.Code, itemTaskCode); + if (itemTask.State == ItemTaskState.Error) + { + _logger.LogError($"Something went wrong with task execution: {itemTask.Message}"); + return null; + } + + //the taskmap is a child of the input tiff + var itemName = "Taskmap"; + var taskMapItem = await FindChildItemAsync(tiffItem.ParentCode, + SHAPE_PROCESSED_ITEMTYPE, itemName); + if (taskMapItem == null) + { + _logger.LogError("Could not find the shape taskmap as a child item under the input"); + return null; + } + + return taskMapItem; + } + public async Task RunAndWaitForTask(Item subjectItem, string taskIdentifier, Action configureCallback = null, int retrySeconds = 3) { diff --git a/FarmmapsPoten/FarmmapsPoten.csproj b/FarmmapsPoten/FarmmapsPoten.csproj index 1ff2fe3..f76d9da 100644 --- a/FarmmapsPoten/FarmmapsPoten.csproj +++ b/FarmmapsPoten/FarmmapsPoten.csproj @@ -12,9 +12,6 @@ Always - - PreserveNewest - diff --git a/FarmmapsPoten/Models/PotenInput.cs b/FarmmapsPoten/Models/PotenInput.cs index 3bb03be..dc97b6b 100644 --- a/FarmmapsPoten/Models/PotenInput.cs +++ b/FarmmapsPoten/Models/PotenInput.cs @@ -5,14 +5,23 @@ namespace FarmmapsPoten.Models { public class PotenInput { - public bool UseShadow { get; set; } - public string File { get; set; } public string OutputFileName { get; set; } public string FieldName { get; set; } public int PlantingYear { get; set; } public string MeanDensity { get; set; } public string Variation { get; set; } + public bool UseShadow { get; set; } + public bool ConvertToCountPerArea { get; set; } + public float Rijbreedte_m { get; set; } public JObject GeometryJson { get; set; } + + public bool GenerateTaskmap { get; set; } + public string CellWidth { get; set; } + public string CellHeight { get; set; } + public JObject StartPoint { get; set; } + public JObject EndPoint { get; set; } + public string Angle { get; set; } + } } \ No newline at end of file diff --git a/FarmmapsPoten/PotenApplication.cs b/FarmmapsPoten/PotenApplication.cs index 42a4ac3..b3dad38 100644 --- a/FarmmapsPoten/PotenApplication.cs +++ b/FarmmapsPoten/PotenApplication.cs @@ -58,6 +58,8 @@ namespace FarmmapsVRApoten var variation = input.Variation; var fieldName = input.FieldName; bool useShadow = input.UseShadow; + bool convertToCountPerArea = input.ConvertToCountPerArea; + float rijBreedte_m = input.Rijbreedte_m; var myDrive = roots.SingleOrDefault(r => r.Name == "My drive"); if (myDrive == null) { @@ -94,7 +96,8 @@ namespace FarmmapsVRApoten //Calculating AHN map _logger.LogInformation("retreiving AHN map for field"); var AHNItem = await _generalService.RunAhnTask(cropfieldItem); - if (AHNItem == null) { + if (AHNItem == null) + { _logger.LogError("Something went wrong while obtaining the AHN map"); return; } @@ -160,6 +163,8 @@ namespace FarmmapsVRApoten Path.Combine(DownloadFolder, $"VRApoten_inputGeotiff_{input.OutputFileName}.zip")); } + + // create appliance map _logger.LogInformation("Calculating application map"); @@ -180,13 +185,35 @@ namespace FarmmapsVRApoten ? "Download application map completed." : "Something went wrong while downloading."); - _logger.LogInformation($"Converting geotiff to shape"); - var taskmap = await _generalService.GeotiffToShape(applianceMapItem); - if (taskmap == null) { + + // if convertToCountPerArea == True, than recalculate pootafstand in cm to # of poters/m2 from the geotiffItem with the use of the zoneringsTask + if (convertToCountPerArea) + { + applianceMapItem = + await _potenService.ConvertToCountPerAreaTroughZonering(cropfieldItem, applianceMapItem, input.Rijbreedte_m); + + } + + + //GEOTIFF TO Taskmap + _logger.LogInformation($"Converting geotiff to taskmap"); + var taskmap = await _generalService.CreateTaskmap(applianceMapItem, input.CellWidth, input.CellHeight, input.StartPoint.ToString(Formatting.None), + input.EndPoint.ToString(Formatting.None), input.Angle); + if (taskmap == null) + { _logger.LogError("Something went wrong with geotiff to shape transformation"); return; } + + ////GEOTIFF TO SHAPE + //_logger.LogInformation($"Converting geotiff to shape"); + //var geotiffToShapeItem= await _generalService.GeotiffToShape(applianceMapItem); + //if (taskmap == null) { + // _logger.LogError("Something went wrong with geotiff to shape transformation"); + // return; + //} + _logger.LogInformation("Downloading taskmap"); await _farmmapsApiService.DownloadItemAsync(taskmap.Code, Path.Combine(DownloadFolder, $"VRApoten_taskmap_{input.OutputFileName}.zip")); diff --git a/FarmmapsPoten/PotenInput.json b/FarmmapsPoten/PotenInput.json index e67acba..7fb8b26 100644 --- a/FarmmapsPoten/PotenInput.json +++ b/FarmmapsPoten/PotenInput.json @@ -1,24 +1,41 @@ [ - { - "File": "PlantingSampleDataLutum.zip", - //"File": "Lutum_SampleDataPlanting.zip", - "OutputFileName": "vraPoten_SampleData", - "FieldName": "lutum", - "PlantingYear": 2020, - "MeanDensity": "30", - "Variation": "20", - "UseShadow": false, - "geometryJson": { - "type": "Polygon", - "coordinates": [ - [ - [ 5.66886041703652044, 52.52929999060298627 ], - [ 5.6716230923214912, 52.52946316399909676 ], - [ 5.67185376229668581, 52.5280565894154563 ], - [ 5.66903207841337231, 52.52790646510525363 ], - [ 5.66886041703652044, 52.52929999060298627 ] - ] - ] + { + "File": "PlantingSampleDataLutum.zip", + //"File": "Lutum_SampleDataPlanting.zip", + "OutputFileName": "20210212_vraPoten_SampleData_TASKMAP_ENDPOINT", + "FieldName": "lutum", + "PlantingYear": 2020, + "MeanDensity": "30", + "Variation": "20", + "UseShadow": false, + "ConvertToCountPerArea": false, + "Rijbreedte_m": 0.75, + "geometryJson": { + "type": "Polygon", + "coordinates": [ + [ + [ 5.66886041703652044, 52.52929999060298627 ], + [ 5.6716230923214912, 52.52946316399909676 ], + [ 5.67185376229668581, 52.5280565894154563 ], + [ 5.66903207841337231, 52.52790646510525363 ], + [ 5.66886041703652044, 52.52929999060298627 ] + ] + ] + }, + + "GenerateTaskmap": true, + "CellWidth": "3", + "CellHeight": "10", + "StartPoint": { + "type": "Point", + "coordinates": [ 5.66886041703652044, 52.52929999060298627 ] + }, + "EndPoint": { + "type": "Point", + "coordinates": [ 5.6716230923214912, 52.52946316399909676 ] + } // if no angle + + //"Angle": "317.0" // if no endpoint } - } + ] diff --git a/FarmmapsPoten/PotenService.cs b/FarmmapsPoten/PotenService.cs index 7a839c2..c77f393 100644 --- a/FarmmapsPoten/PotenService.cs +++ b/FarmmapsPoten/PotenService.cs @@ -82,10 +82,52 @@ namespace FarmmapsVRApoten return applianceMapItem; - } + } - } + // Extra task making use of the zonering task to convert the planting distance in cm to number of seeds per m2 + public async Task ConvertToCountPerAreaTroughZonering(Item cropfieldItem, Item geotiffItem, float rijBreedte_m) + { + var zoneringTaskRequest = new TaskRequest() { TaskType = VRAZONERING_TASK }; + zoneringTaskRequest.attributes["formula"] = $"((100/[0])/{rijBreedte_m.ToString()})"; + zoneringTaskRequest.attributes["output"] = "{\"Name\":\"CountPerAreaConversion\",\"Quantity\":\"CountPerArea\",\"Unit\":\"#/m2\"}"; + zoneringTaskRequest.attributes["inputs"] = $"{{\"ItemCode\":{geotiffItem.Code},\"LayerName\":null\"}}"; + + var taskCode = await _farmmapsApiService.QueueTaskAsync(cropfieldItem.Code, zoneringTaskRequest); + + await PollTask(TimeSpan.FromSeconds(5), async (tokenSource) => + { + var itemTaskStatus = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode); + _logger.LogInformation($"Waiting on convertion to Count per area through zoneringTast; Status: {itemTaskStatus.State}"); + if (itemTaskStatus.IsFinished) + tokenSource.Cancel(); + }); + + var itemTask = await _farmmapsApiService.GetTaskStatusAsync(cropfieldItem.Code, taskCode); + if (itemTask.State == ItemTaskState.Error) + { + _logger.LogError($"Something went wrong with task execution: {itemTask.Message}"); + return null; + } + + var itemName = $"VRAZonering"; + 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())); + i => + i.Name.ToLower().Contains(itemName.ToLower())); + if (applianceMapItem == null) + { + _logger.LogError("Could not find the converted to count per area geotiff child item under cropfield"); + return null; + } + + return applianceMapItem; + } + + + } }