diff --git a/FarmmapsApiSamples.sln b/FarmmapsApiSamples.sln index e44d74d..49b0a34 100644 --- a/FarmmapsApiSamples.sln +++ b/FarmmapsApiSamples.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.30320.27 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33122.133 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsNbs", "FarmmapsNbs\FarmmapsNbs.csproj", "{E08EF7E9-F09E-42D8-825C-164E458C78F4}" EndProject @@ -31,6 +31,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Secrets", "Secrets\Secrets. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FarmmapsCleanUp", "FarmmapsCleanUp\FarmmapsCleanUp.csproj", "{5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FarmmapsKPI", "FarmmapsKPI\FarmmapsKPI.csproj", "{14575235-9867-4CE5-A22F-3F9FE002FF42}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -81,6 +83,10 @@ Global {5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}.Debug|Any CPU.Build.0 = Debug|Any CPU {5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {5E4387F9-5953-4A9B-BCA5-DF3964EED3CB}.Release|Any CPU.Build.0 = Release|Any CPU + {14575235-9867-4CE5-A22F-3F9FE002FF42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {14575235-9867-4CE5-A22F-3F9FE002FF42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {14575235-9867-4CE5-A22F-3F9FE002FF42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {14575235-9867-4CE5-A22F-3F9FE002FF42}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FarmmapsKPI/FarmmapsKPI.csproj b/FarmmapsKPI/FarmmapsKPI.csproj new file mode 100644 index 0000000..bdd33b9 --- /dev/null +++ b/FarmmapsKPI/FarmmapsKPI.csproj @@ -0,0 +1,12 @@ + + + + Exe + netcoreapp3.1 + + + + + + + diff --git a/FarmmapsKPI/KPIApplication.cs b/FarmmapsKPI/KPIApplication.cs new file mode 100644 index 0000000..0e8bac8 --- /dev/null +++ b/FarmmapsKPI/KPIApplication.cs @@ -0,0 +1,199 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Threading.Tasks; +using FarmmapsApi; +using FarmmapsApi.Models; +using FarmmapsApi.Services; +using FarmmapsKPI.Models; +using Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using static FarmmapsApiSamples.Constants; + +namespace FarmmapsKPI +{ + public class KPIApplication : IApplication + { + //private const string DownloadFolder = "Downloads"; + private const string SettingsFile = "settings.json"; + + private readonly ILogger _logger; + private readonly FarmmapsApiService _farmmapsApiService; + private readonly KPIService _dataDownloadService; + private readonly GeneralService _generalService; + + private Settings _settings; + + public KPIApplication(ILogger logger, FarmmapsApiService farmmapsApiService, + GeneralService generalService, KPIService dataDownloadService) + { + _logger = logger; + _farmmapsApiService = farmmapsApiService; + _generalService = generalService; + _dataDownloadService = dataDownloadService; + } + + public async Task RunAsync() + { + var fieldsInputJson = File.ReadAllText("KPIInput.json"); + + List fieldsInputs = JsonConvert.DeserializeObject>(fieldsInputJson); + + // !! 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(); + + foreach (var input in fieldsInputs) + { + try + { + await Process(roots, input); + } + catch (Exception ex) + { + _logger.LogError(ex.Message); + } + } + } + + private async Task Process(List roots, KPIInput input) + { + string downloadFolder = input.DownloadFolder; + if (string.IsNullOrEmpty(downloadFolder)) { + downloadFolder = "Downloads"; + } + if (!Directory.Exists(downloadFolder)) + Directory.CreateDirectory(downloadFolder); + + // !!specify if you are using an already created cropfield: + bool useCreatedCropfield = input.UseCreatedCropfield; + var cropYear = input.CropYear; + var fieldName = input.fieldName; + //bool storeSatelliteStatistics = input.StoreSatelliteStatisticsSingleImage; + //bool storeSatelliteStatisticsCropYear = input.StoreSatelliteStatisticsCropYear; + //List SatelliteBands = new List(1) { input.SatelliteBand }; + //string headerLineStats = $"FieldName,satelliteDate,satelliteBand,max,min,mean,mode,median,stddev,minPlus,curtosis,maxMinus,skewness,variance,populationCount,variationCoefficient,confidenceIntervalLow, confidenceIntervalHigh,confidenceIntervalErrorMargin" + Environment.NewLine; + + + string settingsfile = $"Settings_{fieldName}.json"; + + LoadSettings(settingsfile); + + var uploadedRoot = roots.SingleOrDefault(r => r.Name == "USER_IN"); + if (uploadedRoot == null) + { + _logger.LogError("Could not find a needed root item"); + return; + } + + var myDriveRoot = roots.SingleOrDefault(r => r.Name == "USER_FILES"); + if (myDriveRoot == null) + { + _logger.LogError("Could not find a needed root item"); + return; + } + + // Use already created cropfield or create new one + Item cropfieldItem; + if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.CropfieldItemCode)) + { + _logger.LogInformation("Creating cropfield"); + cropfieldItem = await _generalService.CreateCropfieldItemAsync(myDriveRoot.Code, + $"DataCropfield {input.OutputFileName}", cropYear, input.GeometryJson.ToString(Formatting.None)); + _settings.CropfieldItemCode = cropfieldItem.Code; + SaveSettings(settingsfile); + } + else + { + _logger.LogInformation("Cropfield already exists, trying to get it"); + cropfieldItem = await _farmmapsApiService.GetItemAsync(_settings.CropfieldItemCode); + } + + //Get croprecordings + if (input.GetCropRecordings) + { + var crprecItem = input.CrprecItem; + _logger.LogInformation($"Trying to get crop recordings of croprecording: {crprecItem}"); + + var cropRec = await _farmmapsApiService.GetItemChildrenAsync(crprecItem, CROPREC_ITEMTYPE); + if (cropRec == null) + { + _logger.LogError("Something went wrong while obtaining the croprecordings"); + return; + } + + var cropRecPath = Path.Combine(downloadFolder, $"croprecordings_{crprecItem}.json"); + _logger.LogInformation($"Found {cropRec.Count} crop recordings"); + var count = 0; + await Task.Delay(500); + foreach (var item in cropRec) + { + Console.WriteLine($"Crop recording #{count}: {item.Name}"); + File.AppendAllText(cropRecPath, item.Data +Environment.NewLine); + count++; + } + _logger.LogInformation($"Downloaded file {cropRecPath}"); + } + else + { + //todo set croprecordings from file + } + + // Get KPI data + + //_logger.LogInformation("Calculate KPI map for field"); + //var KPIItem = await _generalService.RunKPITask(cropfieldItem); + var KPIItem = null; + if (KPIItem == null) + { + _logger.LogError("Something went wrong while obtaining the KPI map"); + return; + } + + //_logger.LogInformation("Downloading KPI map"); + //await _farmmapsApiService.DownloadItemAsync(KPIItem.Code, + // Path.Combine(downloadFolder, $"{input.OutputFileName}_KPI.zip")); + + + + + + } + + // Functions to save previously created cropfields + private void LoadSettings(string file) + { + if (File.Exists(file)) + { + var jsonText = File.ReadAllText(file); + _settings = JsonConvert.DeserializeObject(jsonText); + } + else + { + _settings = new Settings(); + } + } + + private void SaveSettings(string file) + { + if (_settings == null) + return; + + var json = JsonConvert.SerializeObject(_settings); + File.WriteAllText(file, json); + } + private void SaveInfo(string file) + { + if (_settings == null) + return; + + var json = JsonConvert.SerializeObject(_settings); + File.WriteAllText(file, json); + + } + + } +} diff --git a/FarmmapsKPI/KPIInput.json b/FarmmapsKPI/KPIInput.json new file mode 100644 index 0000000..84d35e8 --- /dev/null +++ b/FarmmapsKPI/KPIInput.json @@ -0,0 +1,34 @@ +[ + { + "UseCreatedCropfield": false, + "outputFileName": "TestData", + "fieldName": "TestField", + "DownloadFolder": "Downloads", //"C:\\workdir\\groenmonitor\\", // "Downloads", -> if you just put "Downloads" the program will download to somewhere in ..\FarmMapsApiClient_WURtest\FarmmapsDataDownload\bin\Debug\netcoreapp3.1\Downloads\ + "GetCropRecordings": true, + "CrprecItem": "...", //item code of de crop recording parrent - can be found by opening the crop recording page of a field. + "GetShadowData": false, + "GetSatelliteData": false, + "SatelliteBand": "wdvi", // "natural", "ndvi" or "wdvi" + "StoreSatelliteStatisticsSingleImage": false, + "StoreSatelliteStatisticsCropYear": false, + "GetVanDerSatData": false, + "StoreVanDerSatStatistics": false, + "CropYear": 2020, + "geometryJson": { + "type": "Polygon", + "coordinates": [ + [ + [ 4.960707146896585, 52.800583669708487 ], + [ 4.960645975538824, 52.800470217610922 ], + [ 4.962140695752897, 52.799177147194797 ], + [ 4.967523821195745, 52.801502400041208 ], + [ 4.966336768950911, 52.802543735879809 ], + [ 4.961711880764330, 52.801009996856429 ], + [ 4.960707146896585, 52.800583669708487 ] + ] + ] + } + } + + +] \ No newline at end of file diff --git a/FarmmapsKPI/KPIService.cs b/FarmmapsKPI/KPIService.cs new file mode 100644 index 0000000..ce88acd --- /dev/null +++ b/FarmmapsKPI/KPIService.cs @@ -0,0 +1,29 @@ +using System; +using System.Globalization; +using System.Threading.Tasks; +using FarmmapsApi.Models; +using FarmmapsApi.Services; +using FarmmapsKPI.Models; +using Microsoft.Extensions.Logging; +using static FarmmapsApi.Extensions; +using static FarmmapsApiSamples.Constants; + +namespace FarmmapsKPI +{ + public class KPIService + { + private readonly ILogger _logger; + private readonly FarmmapsApiService _farmmapsApiService; + private readonly GeneralService _generalService; + + public KPIService(ILogger logger, FarmmapsApiService farmmapsApiService, + GeneralService generalService) + { + _logger = logger; + _farmmapsApiService = farmmapsApiService; + _generalService = generalService; + } + + + } +} \ No newline at end of file diff --git a/FarmmapsKPI/Models/CropRecordings.cs b/FarmmapsKPI/Models/CropRecordings.cs new file mode 100644 index 0000000..61e667f --- /dev/null +++ b/FarmmapsKPI/Models/CropRecordings.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace FarmmapsKPI.Models +{ + internal class CropRecordings + { + } +} diff --git a/FarmmapsKPI/Models/KPIInput.cs b/FarmmapsKPI/Models/KPIInput.cs new file mode 100644 index 0000000..63e5c68 --- /dev/null +++ b/FarmmapsKPI/Models/KPIInput.cs @@ -0,0 +1,28 @@ +using System; +using Newtonsoft.Json.Linq; + +namespace FarmmapsKPI.Models +{ + public class KPIInput + { + public bool UseCreatedCropfield { get; set; } + public string File { get; set; } + public string InputVariable { get; set; } + public string OutputFileName { get; set; } + public string DownloadFolder { get; set; } + public int CropYear { get; set; } + public JObject GeometryJson { get; set; } + public string InputLayerName { get; set; } + public string fieldName { get; set; } + public bool GetSatelliteData { get; set; } + public bool GetVanDerSatData { get; set; } + public string SatelliteBand { get; set; } + public bool StoreSatelliteStatisticsSingleImage { get; set; } + public bool StoreSatelliteStatisticsCropYear { get; set; } + public bool StoreVanDerSatStatistics { get; set; } + public bool GetShadowData { get; set; } + public bool GetCropRecordings { get; set; } + public string CrprecItem { get; set; } + + } +} \ No newline at end of file diff --git a/FarmmapsKPI/Models/Settings.cs b/FarmmapsKPI/Models/Settings.cs new file mode 100644 index 0000000..bd7ff29 --- /dev/null +++ b/FarmmapsKPI/Models/Settings.cs @@ -0,0 +1,11 @@ +namespace FarmmapsKPI +{ + public class Settings + { + public string CropfieldItemCode { get; set; } + //public string SatelliteTaskCode { get; set; } + //public string VanDerSatTaskCode { get; set; } + //public string WatBalTaskCode { get; set; } + + } +} \ No newline at end of file diff --git a/FarmmapsKPI/Program.cs b/FarmmapsKPI/Program.cs new file mode 100644 index 0000000..9e8e737 --- /dev/null +++ b/FarmmapsKPI/Program.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; +using FarmmapsApi; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace FarmmapsKPI +{ + class Program : FarmmapsProgram + { + private static async Task Main(string[] args) + { + await new Program().Start(args); + } + + protected override void Configure(IServiceCollection serviceCollection) + { + serviceCollection.AddLogging() + .AddTransient(); + } + } +}