From 191d36dbbea5fab6141d9a144f154c98757e284f Mon Sep 17 00:00:00 2001 From: Ariel Costas Guerrero Date: Wed, 18 Feb 2026 12:23:04 +0100 Subject: feat: Add CtagShuttle support with real-time WRONG estimate and good position --- .../CtagShuttleRealtimeEstimatesProvider.cs | 30 ++++++++++++++ .../Enmarcha.Sources.CtagShuttle.csproj | 9 +++++ Enmarcha.Sources.CtagShuttle/Status.cs | 46 ++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 Enmarcha.Sources.CtagShuttle/CtagShuttleRealtimeEstimatesProvider.cs create mode 100644 Enmarcha.Sources.CtagShuttle/Enmarcha.Sources.CtagShuttle.csproj create mode 100644 Enmarcha.Sources.CtagShuttle/Status.cs (limited to 'Enmarcha.Sources.CtagShuttle') diff --git a/Enmarcha.Sources.CtagShuttle/CtagShuttleRealtimeEstimatesProvider.cs b/Enmarcha.Sources.CtagShuttle/CtagShuttleRealtimeEstimatesProvider.cs new file mode 100644 index 0000000..3ec0c6f --- /dev/null +++ b/Enmarcha.Sources.CtagShuttle/CtagShuttleRealtimeEstimatesProvider.cs @@ -0,0 +1,30 @@ +using System.Net.Http.Json; + +namespace Enmarcha.Sources.CtagShuttle; + +public class CtagShuttleRealtimeEstimatesProvider +{ + private HttpClient _http; + + public CtagShuttleRealtimeEstimatesProvider(HttpClient http) + { + _http = http; + } + + public async Task GetShuttleStatus() + { + const string url = "https://shuttle.brain4mobility.com/status"; + + var response = await _http.GetAsync(url); + var status = await response.Content.ReadFromJsonAsync(); + + if (status is null) + { + throw new InvalidOperationException("Failed to retrieve shuttle status"); + } + + return status; + } + +} + diff --git a/Enmarcha.Sources.CtagShuttle/Enmarcha.Sources.CtagShuttle.csproj b/Enmarcha.Sources.CtagShuttle/Enmarcha.Sources.CtagShuttle.csproj new file mode 100644 index 0000000..237d661 --- /dev/null +++ b/Enmarcha.Sources.CtagShuttle/Enmarcha.Sources.CtagShuttle.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/Enmarcha.Sources.CtagShuttle/Status.cs b/Enmarcha.Sources.CtagShuttle/Status.cs new file mode 100644 index 0000000..ecf2da1 --- /dev/null +++ b/Enmarcha.Sources.CtagShuttle/Status.cs @@ -0,0 +1,46 @@ +using System.Text.Json.Serialization; + +namespace Enmarcha.Sources.CtagShuttle; + +public class CtagShuttleStatus +{ + [JsonPropertyName("status")] public required string StatusValue { get; set; } + [JsonPropertyName("lat")] public double Latitude { get; set; } + [JsonPropertyName("lng")] public double Longitude { get; set; } + [JsonPropertyName("last_position_at")] public required string LastPositionAtValue { get; set; } + [JsonPropertyName("free_seats")] public int FreeSeats { get; set; } + + [JsonPropertyName("last_occupancy_at")] + public required string LastOccupancyAtValue { get; set; } + + [JsonIgnore] + public Status Status => Status.Parse(StatusValue); + + [JsonIgnore] + public DateTime LastPositionAt => DateTime.Parse(LastPositionAtValue); + + [JsonIgnore] + public DateTime LastOccupancyAt => DateTime.Parse(LastOccupancyAtValue); +} + +public enum Status +{ + Idle, + Operating +} + +public static class StatusExtensions +{ + extension(Status) + { + public static Status Parse(string value) + { + return value switch + { + "idle" => Status.Idle, + "operating" => Status.Operating, + _ => throw new ArgumentException($"Invalid status value: {value}") + }; + } + } +} -- cgit v1.3