Skip to content

Commit

Permalink
APRS-IS beacon item
Browse files Browse the repository at this point in the history
  • Loading branch information
valentintintin committed Mar 28, 2024
1 parent fb3a7bd commit 660a29a
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 5 deletions.
57 changes: 53 additions & 4 deletions Monitor/Monitor/Workers/AprsIsApp.cs
Expand Up @@ -2,6 +2,8 @@
using System.Reactive.Linq;
using AprsSharp.AprsIsClient;
using AprsSharp.AprsParser;
using AprsSharp.Shared;
using GeoCoordinatePortable;
using Microsoft.EntityFrameworkCore;
using Monitor.Context;
using Monitor.Extensions;
Expand All @@ -14,30 +16,61 @@ public class AprsIsApp : AEnabledWorker
private readonly SerialMessageService _serialMessageService;
private readonly AprsIsClient _aprsIsClient;
private readonly string _callsign, _passcode, _server, _filter;
private readonly string? _objectName, _objectComment;
private readonly DataContext _context;
private readonly Position? _objectPosition;
private readonly TimeSpan? _durationHeard = TimeSpan.FromMinutes(30);
private readonly TcpConnection _tcpConnection = new();

public AprsIsApp(ILogger<AprsIsApp> logger, IServiceProvider serviceProvider,
IConfiguration configuration, IDbContextFactory<DataContext> contextFactory) : base(logger, serviceProvider)
{
_serialMessageService = Services.GetRequiredService<SerialMessageService>();
_context = contextFactory.CreateDbContext();

_aprsIsClient = new AprsIsClient(Services.GetRequiredService<ILogger<AprsIsClient>>());
_aprsIsClient = new AprsIsClient(Services.GetRequiredService<ILogger<AprsIsClient>>(), _tcpConnection);
_aprsIsClient.ReceivedPacket += ComputeReceivedPacket;
// _aprsIsClient.ReceivedTcpMessage += message => Logger.LogTrace(message);

var configurationSection = configuration.GetSection("AprsIs");
var positionSection = configuration.GetSection("Position");

var latitude = positionSection.GetValueOrThrow<double>("Latitude");
var longitude = positionSection.GetValueOrThrow<double>("Longitude");

_callsign = configurationSection.GetValueOrThrow<string>("Callsign");
_passcode = configurationSection.GetValueOrThrow<string>("Passcode");
_server = configurationSection.GetValueOrThrow<string>("Server");
_filter = $"r/{positionSection.GetValueOrThrow<double>("Latitude").ToString( CultureInfo.InvariantCulture)}/{positionSection.GetValueOrThrow<double>("Longitude").ToString(CultureInfo.InvariantCulture)}/{configurationSection.GetValueOrThrow<int>("RadiusKm")} -e/{_callsign} {configurationSection.GetValueOrThrow<string>("Filter")}\n";
_filter = $"r/{latitude.ToString( CultureInfo.InvariantCulture)}/{longitude.ToString(CultureInfo.InvariantCulture)}/{configurationSection.GetValueOrThrow<int>("RadiusKm")} -e/{_callsign} {configurationSection.GetValueOrThrow<string>("Filter")}\n";

if (configurationSection.GetValue("AlwaysTx", true))
{
_durationHeard = null;
}

var beaconObjectSection = configurationSection.GetSection("BeaconObject");
if (beaconObjectSection.GetValue("Enable", false))
{
_objectName = beaconObjectSection.GetValueOrThrow<string>("Name");
_objectComment = beaconObjectSection.GetValue<string>("Comment");
_objectPosition = new Position(new GeoCoordinate(latitude, longitude),
beaconObjectSection.GetValueOrThrow<char>("SymbolTable"),
beaconObjectSection.GetValueOrThrow<char>("SymbolCode")
);

_aprsIsClient.ChangedState += state =>
{
if (state == ConnectionState.LoggedIn)
{
SendBeaconObjectPacket();
}
};

AddDisposable(Observable.Timer(TimeSpan.FromMinutes(30)).Subscribe(_ =>
{
SendBeaconObjectPacket();
}));
}
}

protected override Task Start()
Expand All @@ -47,11 +80,18 @@ protected override Task Start()
return Task.CompletedTask;
}

protected override Task Stop()
protected override async Task Stop()
{
if (_objectPosition != null)
{
SendBeaconObjectPacket(false);

await Task.Delay(1500);
}

_aprsIsClient.Disconnect();

return base.Stop();
await base.Stop();
}

private void ComputeReceivedPacket(Packet packet)
Expand Down Expand Up @@ -97,4 +137,13 @@ private bool HasStationHeard()
var lastHeard = DateTime.UtcNow - _durationHeard.Value;
return _context.LoRas.Any(e => !e.IsTx && e.CreatedAt >= lastHeard);
}

private void SendBeaconObjectPacket(bool alive = true)
{
var packet = $"{_callsign}>TCPIP:){_objectName}{(alive ? '!' : '_')}{_objectPosition!.Encode()}{_objectComment} Up:{EntitiesManagerService.Entities.SystemUptime.Value}";

Logger.LogInformation("Send packet beacon object alive ? {alive} : {packet}", alive, packet);

_tcpConnection.SendString(packet + "\n");
}
}
5 changes: 5 additions & 0 deletions Monitor/Monitor/appsettings.Development.json
Expand Up @@ -38,5 +38,10 @@
"Skip": 0
}
]
},
"AprsIs": {
"BeaconObject": {
"Enable": false
}
}
}
9 changes: 8 additions & 1 deletion Monitor/Monitor/appsettings.json
Expand Up @@ -74,6 +74,13 @@
"Server": "france.aprs2.net",
"RadiusKm": "20",
"Filter": "-e/PE2KMV",
"AlwaysTx": false
"AlwaysTx": false,
"BeaconObject": {
"Enable": true,
"Name": "F4HVV Cam",
"SymbolTable": "/",
"SymbolCode": "I",
"Comment": "https://f4hvv.valentin-saugnier.fr"
}
}
}

0 comments on commit 660a29a

Please sign in to comment.