diff --git a/tools/livetrack/README.md b/tools/livetrack/README.md new file mode 100644 index 0000000..bd8785f --- /dev/null +++ b/tools/livetrack/README.md @@ -0,0 +1,17 @@ + +fwd_positions_udp.pl is run on the tbeam server monitoring the logger output. Example: + perl fwd_positions_udp.pl --file /usr/local/src/sx1302_hal/util_net_downlink/uplinks_20260219_123102.csv --host ryzdesk --port 1777 + +udp2ws.pl is run on ryzdesk to receiving incoming packets and ready them for consumption bye the HTML page + +The chain is: +1) the semtech 1303 listening captures transmissions and then sends them via UDP +2) the logger listens and logs the UDP to a csv +3) fwd_positions_udp.pl monitors the csv and then send via another UDP data to ryzdesk +4) udp2wr.pl runs on ryzdesk and receives the tbeam's data and makes it available to the HTML page's JavaScript + +TODO: tie into my own map server (has high zoom capability) + +Just writing this now to capture what happened last night as I may not get back to +this for a couple of weeks given the upcoming Voron project. + diff --git a/tools/livetrack/udp2ws.pl b/tools/livetrack/udp2ws.pl new file mode 100644 index 0000000..f585254 --- /dev/null +++ b/tools/livetrack/udp2ws.pl @@ -0,0 +1,60 @@ +#!/usr/bin/env perl +# 20260219 ChatGPT +# $Id$ +# $HeadURL$ + +use strict; +use warnings; + +use Mojolicious::Lite -signatures; +use Mojo::IOLoop; +use IO::Socket::INET; + +my $udp_port = 1777; + +# Track websocket clients +my %clients; + +websocket '/stream' => sub ($c) { + my $id = sprintf("%x", rand(0xffffffff)); + $clients{$id} = $c->tx; + + $c->on(finish => sub ($c, $code, $reason) { + delete $clients{$id}; + }); +}; + +# UDP socket (non-blocking) +my $udp = IO::Socket::INET->new( + LocalPort => $udp_port, + Proto => 'udp', +) or die "udp bind $udp_port: $!\n"; + +$udp->blocking(0); + +# Register UDP fd with Mojo reactor +my $loop = Mojo::IOLoop->singleton; + +#Mojo::IOLoop->reactor->io($udp => sub ($reactor, $writable) { +$loop->reactor->io($udp => sub ($reactor, $writable) { + my $datagram = ''; + my $peer = $udp->recv($datagram, 2048); + return unless defined $peer && length $datagram; + + $datagram =~ s/\r?\n$//; + + for my $id (keys %clients) { + my $tx = $clients{$id}; + next unless $tx && !$tx->is_finished; + $tx->send($datagram); + } +}); + +#Mojo::IOLoop->reactor->watch($udp, 1, 0); +$loop->reactor->watch($udp, 1, 0); + +get '/' => sub ($c) { + $c->render(text => "udp2ws up (udp:$udp_port ws:/stream)\n"); +}; + +app->start;