PHP code example of guszandy / php-aprs

1. Go to this page and download the library: Download guszandy/php-aprs library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

guszandy / php-aprs example snippets


$packet = (new PacketParser())->parse('YC2UTC-9>APDR16,WIDE1-1:!0748.00S/11022.00E>Driving home');

$packet->latitude();   // -7.8
$packet->longitude();  // 110.366667
$packet->comment;      // Driving home

use Aprs\Parser\PacketParser;
use Aprs\Packet\PositionPacket;
use Aprs\Packet\MessagePacket;

$parser = new PacketParser();

$packet = $parser->parse('YC2UTC-9>APDR16,WIDE1-1,WIDE2-1:!0748.00S/11022.00E>088/036/A=000123Driving home');

echo $packet->source;        // YC2UTC-9
echo $packet->destination;   // APDR16
echo $packet->path;          // WIDE1-1,WIDE2-1

if ($packet instanceof PositionPacket) {
    echo $packet->latitude();        // -7.8
    echo $packet->longitude();       // 110.366667
    echo $packet->course;            // 88
    echo $packet->speedKmh();        // 66.672
    echo $packet->altitudeMeters();  // 37.4904
    echo $packet->comment;           // Driving home
}

$packet = $parser->parse('YC2UTC>APRS::YB0ABC-1 :Hello world{003');

if ($packet instanceof MessagePacket) {
    echo $packet->addressee;   // YB0ABC-1
    echo $packet->text;        // Hello world
    echo $packet->messageId;   // 003
    $packet->expectsAck();     // true
}

use Aprs\Client\AprsIsClient;
use Aprs\Client\ClientOptions;
use Aprs\Client\Filter;
use Aprs\Packet\Packet;

$filter = Filter::create()->range(-7.8, 110.37, 100);   // 100 km around Yogyakarta

$client = new AprsIsClient(ClientOptions::readOnly('YC2UTC', $filter));
$client->connect();

$client->run(function (Packet $packet) {
    echo $packet->source, ' ', $packet->payload, PHP_EOL;
});

$client = new AprsIsClient(ClientOptions::authenticated('YC2UTC'));
$client->connect();
$client->send('YC2UTC>APRS,TCPIP*:>Beaconing from PHP');

$client->run(
    fn (Packet $p) => handle($p),
    fn (ParseException $e, string $line) => error_log("bad packet: $line"),
    fn () => $client->stop(),           // e.g. after a deadline
);

$client->onServerMessage(fn (string $line) => error_log($line));

Filter::create()
    ->range(-7.8, 110.37, 100)   // r/-7.8/110.37/100
    ->budlist('YC2UTC*')         // b/YC2UTC*
    ->type('poimq');             // t/poimq

use Aprs\Encoder\PositionEncoder;

$raw = PositionEncoder::atDegrees(-7.8, 110.366667)
    ->symbol('/', '>')
    ->messagingCapable()
    ->courseSpeed(88, 36)
    ->altitude(123)
    ->comment('Driving home')
    ->toTnc2('YC2UTC-9');

// YC2UTC-9>APZPHP,WIDE1-1,WIDE2-1:=0748.00S/11022.00E>088/036/A=000123Driving home

use Aprs\Encoder\MessageEncoder;

MessageEncoder::message('YB0ABC-1', 'Meet at the repeater', '003');
// :YB0ABC-1 :Meet at the repeater{003

MessageEncoder::ack('YB0ABC-1', '003');        // :YB0ABC-1 :ack003
MessageEncoder::bulletin(3, 'Heavy rain', 'WX'); // :BLN3WX   :Heavy rain

$client->send($raw);

$packet = $parser->parse('M0XER-4>APRS64,qAR,TF3SUT-2:!/.(M4I^C,O `DXa/A=040849');

$packet->latitude();     // 64.11987368
$packet->compressed;     // true
$packet->gpsFixCurrent;  // true

CompressedPositionEncoder::atDegrees(64.11987, -19.07065)
    ->symbol('/', 'O')
    ->courseSpeed(88, 36)
    ->toTnc2('M0XER-4');

$encoder = MicEEncoder::atDegrees(35.586833, 139.701)
    ->symbol('/', '[')
    ->courseSpeed(305, 0)
    ->messageType(MicEMessageType::OffDuty);

$encoder->destination();   // SUSUR1
$encoder->toTnc2('YC2UTC-9');

if ($packet instanceof MicEPacket && $packet->isEmergency()) {
    // ...
}

if ($packet instanceof ThirdPartyPacket) {
    $packet->source;            // YB0IGT   — the gateway
    $packet->originalSource();  // YC2UTC-9 — who actually sent it
    $packet->innermost();       // the original packet, fully parsed
}

// Wrong — objects and Mic-E never reach their own branches.
if ($packet instanceof PositionPacket) { /* ... */ }
elseif ($packet instanceof ObjectPacket) { /* unreachable */ }

// Right — most specific first.
if ($packet instanceof ObjectPacket) { /* ... */ }
elseif ($packet instanceof MicEPacket) { /* ... */ }
elseif ($packet instanceof PositionPacket) { /* ... */ }

if ($packet->hasWeather()) {
    $packet->weather->temperatureC();   // 25.0
    $packet->weather->windSpeedKmh();   // 6.4374
    $packet->weather->humidity;         // 50
}

if ($packet instanceof ObjectPacket && $packet->isKilled()) {
    $map->remove($packet->name);
}

$client->runForever(
    fn (Packet $p) => handle($p),
    ReconnectPolicy::persistent(),          // or ReconnectPolicy::upTo(5)
    fn (ConnectionException $e, int $n) => error_log("drop #$n: {$e->getMessage()}"),
);

foreach ($lines as $line) {
    $packet = $parser->tryParse($line);

    if ($packet === null) {
        $malformed++;
        continue;
    }

    // ...
}

$c = Coordinate::fromAprs('4903.5 N', '07201.75W');

$c->ambiguity;          // 1
$c->latitude;           // 49.05916667  (centre of 49°03.50'–49°03.60')
$c->toAprsLatitude();   // "4903.5 N"

use Aprs\Packet\DataType;
use Aprs\Parser\PayloadParser;

final class QueryParser implements PayloadParser
{
    public function supports(DataType $type): bool
    {
        return $type === DataType::Query;
    }

    public function parse(
        DataType $type,
        Callsign $source,
        Callsign $destination,
        Path $path,
        string $payload,
        string $raw,
    ): Packet {
        // ... build and return your own Packet subclass
    }
}

$parser = new PacketParser();
$parser->register(new QueryParser());
bash
composer 
bash
composer install
php examples/parse-packets.php               # decode built-in samples
php examples/encode-packets.php              # build packets, verify round trips
php examples/compressed-and-mice.php         # compressed + Mic-E, three encodings
php examples/aprs-is-listen.php YC2UTC       # live read-only APRS-IS feed

composer check     # everything below, in order — this is what CI runs
composer lint      # syntax-check every file
composer cs        # PSR-12 check
composer cs-fix    # PSR-12 autofix
composer stan      # PHPStan level 6
composer test      # PHPUnit