using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using FarmmapsApi; using FarmmapsApi.Models; using FarmmapsApi.Services; using FarmmapsDataDownload.Models; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using static FarmmapsApiSamples.Constants; namespace FarmmapsDataDownload { public class DataDownloadApplication : IApplication { private const string DownloadFolder = "Downloads"; private const string SettingsFile = "settings.json"; private readonly ILogger _logger; private readonly FarmmapsApiService _farmmapsApiService; private readonly DataDownloadService _dataDownloadService; private readonly GeneralService _generalService; private Settings _settings; public DataDownloadApplication(ILogger logger, FarmmapsApiService farmmapsApiService, GeneralService generalService, DataDownloadService dataDownloadService) { _logger = logger; _farmmapsApiService = farmmapsApiService; _generalService = generalService; _dataDownloadService = dataDownloadService; } public async Task RunAsync() { var fieldsInputJson = File.ReadAllText("DataDownloadInput.json"); List fieldsInputs = JsonConvert.DeserializeObject>(fieldsInputJson); if (!Directory.Exists(DownloadFolder)) Directory.CreateDirectory(DownloadFolder); // !! 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, DataDownloadInput input) { // !!specify if you are using an already created cropfield: bool useCreatedCropfield = input.UseCreatedCropfield; var cropYear = input.CropYear; var fieldName = input.fieldName; bool storeSatelliteStatistics = input.StoreSatelliteStatistics; string settingsfile = $"Settings_{fieldName}.json"; LoadSettings(settingsfile); var uploadedRoot = roots.SingleOrDefault(r => r.Name == "Uploaded"); if (uploadedRoot == null) { _logger.LogError("Could not find a needed root item"); return; } var myDriveRoot = roots.SingleOrDefault(r => r.Name == "My drive"); 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.Year, 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 shadow data if (input.GetShadowData) { _logger.LogInformation("Calculate shadow map for field"); var shadowItem = await _generalService.RunShadowTask(cropfieldItem); if (shadowItem == null) { _logger.LogError("Something went wrong while obtaining the shadow map"); return; } _logger.LogInformation("Downloading shadow map"); await _farmmapsApiService.DownloadItemAsync(shadowItem.Code, Path.Combine(DownloadFolder, $"{input.OutputFileName}_shadow.zip")); } // Get satellite data if (input.GetSatelliteData) { // check if satellite task not yet done, do here and save taskcode if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.SatelliteTaskCode)) { var satelliteTaskCode = await _generalService.RunSatelliteTask(cropfieldItem); _settings.SatelliteTaskCode = satelliteTaskCode; SaveSettings(settingsfile); } // Select a particular satellite item from satelliteTask Item satalliteItem = await _generalService.FindSatelliteItem(cropfieldItem, _settings.SatelliteTaskCode); int selectedLayer= 2; if (input.SatelliteBand == "ndvi") selectedLayer = 0; if (input.SatelliteBand == "wdvi") selectedLayer = 1; if (input.SatelliteBand == "natural") selectedLayer = 2; var satelliteBand = satalliteItem.Data["layers"][selectedLayer]["name"]; //Store satellite data to csv if (storeSatelliteStatistics == true && (selectedLayer == 0 || selectedLayer ==1)) { var satelliteStatistics = satalliteItem.Data["layers"][selectedLayer]["renderer"]["band"]["statistics"]; Console.WriteLine($"Satellite image date: {satalliteItem.DataDate}"); var SatelliteStatsFile = $"{DownloadFolder}/SatelliteDataStatistics_{fieldName}_{input.SatelliteBand}_{satalliteItem.DataDate.Value:yyyy-MM-dd}.csv"; using var w = new StreamWriter(SatelliteStatsFile); { foreach (var item in satelliteStatistics) { var line = string.Format("{0}", item); w.WriteLine(line); w.Flush(); } } } var inputType = (satalliteItem.Data["layers"] as JArray)?[selectedLayer]["name"].ToString(); if (string.IsNullOrEmpty(inputType)) { _logger.LogError("Could not get the input type name from the satellite item"); return; } // download the geotiff of needed inputtype var SatelliteImageDate = (DateTime)satalliteItem.DataDate; var SatelliteDate = SatelliteImageDate.ToString("yyyyMMdd"); _logger.LogInformation("Downloading geotiff file"); await _farmmapsApiService.DownloadItemAsync(satalliteItem.Code, Path.Combine(DownloadFolder, $"satelliteGeotiff_{input.OutputFileName}_{inputType}_{SatelliteDate}.zip")); } // Get vanDerSat data if (input.GetVanDerSatData) { // check if satellite task not yet done, do here and save taskcode if (useCreatedCropfield == false || string.IsNullOrEmpty(_settings.VanDerSatTaskCode)) { var vanDerSatTaskCode = await _generalService.RunVanDerSatTask(cropfieldItem); _settings.VanDerSatTaskCode = vanDerSatTaskCode; SaveSettings(settingsfile); } // Select a particular satellite item from satelliteTask Item vanDerSatItem = await _generalService.FindVanDerSatItem(cropfieldItem, _settings.VanDerSatTaskCode, fieldName, input.StoreVanDerSatStatistics); } } // 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); } } }