Improve cadastral GPS reliability and mobile overlays

This commit is contained in:
livio committed 2026-10-02 08:38:14 +02:00
1 parent 29c3848a22
commit 5ea424b46c
7 files changed
+243 -30

No files matched your search

+79 -10
View File
@@ -1,4 +1,6 @@
using System.Globalization;
using System.Net;
using System.Net.Http.Headers;
using System.Xml.Linq;
namespace LMEMappeCatastaliApp.Services;
@@ -13,8 +15,9 @@ public sealed class OfficialCadastreService
public OfficialCadastreService()
{
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/0.2");
_httpClient.DefaultRequestHeaders.Accept.ParseAdd("application/gml+xml");
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("LMEMappeCatastali/1.0 (Android)");
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/gml+xml"));
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml", 0.9));
}
public async Task<string> GetParcelsNearAsync(
@@ -22,14 +25,30 @@ public sealed class OfficialCadastreService
double longitude,
double radiusMeters,
CancellationToken cancellationToken = default)
=> await GetFeaturesNearAsync(
{
var firstRadius = Math.Clamp(radiusMeters, 12, 30);
var xml = await GetFeaturesNearAsync(
latitude,
longitude,
radiusMeters,
firstRadius,
"CP:CadastralParcel",
100,
cancellationToken);
if (firstRadius >= 30 || ContainsFeatures(xml))
{
return xml;
}
return await GetFeaturesNearAsync(
latitude,
longitude,
30,
"CP:CadastralParcel",
100,
cancellationToken);
}
public async Task<string> GetSheetsNearAsync(
double latitude,
double longitude,
@@ -78,15 +97,65 @@ public sealed class OfficialCadastreService
var url = WfsEndpoint + "?" + string.Join("&", query.Select(item =>
$"{Uri.EscapeDataString(item.Key)}={Uri.EscapeDataString(item.Value)}"));
using var response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseContentRead, cancellationToken);
if (!response.IsSuccessStatusCode)
for (var attempt = 0; attempt < 3; attempt++)
{
throw new HttpRequestException($"Il servizio WFS AdE ha risposto {((int)response.StatusCode)}.");
try
{
using var request = new HttpRequestMessage(HttpMethod.Get, url)
{
Version = HttpVersion.Version11,
VersionPolicy = HttpVersionPolicy.RequestVersionOrLower
};
request.Headers.CacheControl = new CacheControlHeaderValue { NoCache = true };
using var response = await _httpClient.SendAsync(
request,
HttpCompletionOption.ResponseContentRead,
cancellationToken);
if (response.IsSuccessStatusCode)
{
var xml = await response.Content.ReadAsStringAsync(cancellationToken);
ThrowIfExceptionReport(xml);
return xml;
}
if (attempt < 2 && IsTransient(response.StatusCode))
{
await Task.Delay(TimeSpan.FromMilliseconds(500 * (attempt + 1)), cancellationToken);
continue;
}
throw new HttpRequestException($"Il servizio WFS AdE ha risposto {((int)response.StatusCode)}.");
}
catch (HttpRequestException) when (attempt < 2)
{
await Task.Delay(TimeSpan.FromMilliseconds(500 * (attempt + 1)), cancellationToken);
}
catch (TaskCanceledException) when (!cancellationToken.IsCancellationRequested && attempt < 2)
{
await Task.Delay(TimeSpan.FromMilliseconds(500 * (attempt + 1)), cancellationToken);
}
}
var xml = await response.Content.ReadAsStringAsync(cancellationToken);
ThrowIfExceptionReport(xml);
return xml;
throw new HttpRequestException("Il servizio WFS AdE non ha risposto dopo tre tentativi.");
}
private static bool IsTransient(HttpStatusCode statusCode) =>
statusCode is HttpStatusCode.RequestTimeout or HttpStatusCode.TooManyRequests
|| (int)statusCode >= 500;
private static bool ContainsFeatures(string xml)
{
try
{
var document = XDocument.Parse(xml);
return document.Descendants().Any(element =>
element.Name.LocalName is "member" or "featureMember");
}
catch (System.Xml.XmlException)
{
return false;
}
}
private static string Format(double value) => value.ToString("R", CultureInfo.InvariantCulture);