{"id":37797463,"url":"https://github.com/trasukg/local-aprs","last_synced_at":"2026-01-17T15:42:55.787Z","repository":{"id":6285993,"uuid":"55277130","full_name":"trasukg/local-aprs","owner":"trasukg","description":"local-aprs is a 'local' web server and client for aprs messages.","archived":false,"fork":false,"pushed_at":"2025-10-16T01:30:54.000Z","size":3977,"stargazers_count":37,"open_issues_count":3,"forks_count":4,"subscribers_count":6,"default_branch":"develop","last_synced_at":"2026-01-17T02:23:25.615Z","etag":null,"topics":["amateur-radio","aprs","hacktoberfest","tnc"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trasukg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-02T04:10:27.000Z","updated_at":"2025-07-02T14:18:12.000Z","dependencies_parsed_at":"2023-01-13T13:55:36.065Z","dependency_job_id":null,"html_url":"https://github.com/trasukg/local-aprs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/trasukg/local-aprs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trasukg%2Flocal-aprs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trasukg%2Flocal-aprs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trasukg%2Flocal-aprs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trasukg%2Flocal-aprs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trasukg","download_url":"https://codeload.github.com/trasukg/local-aprs/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trasukg%2Flocal-aprs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28511851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T13:38:16.342Z","status":"ssl_error","status_checked_at":"2026-01-17T13:37:44.060Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amateur-radio","aprs","hacktoberfest","tnc"],"created_at":"2026-01-16T15:21:35.627Z","updated_at":"2026-01-17T15:42:50.775Z","avatar_url":"https://github.com/trasukg.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Local-APRS\n\nlocal-aprs is a 'local' web server and client for aprs messages.  Imagine\nan event.  There are 10 amateurs there with handheld radios, but do those\nhandhelds have APRS capability?  Probably not.  But chances are, those same\namateurs are carrying smart phones.  And those phones (or tablets)\nusually have GPS receivers.  Now, the event may not have good internet\ncoverage on the cell system, which is to be expected (or perhaps we're in a\n\"when all else fails\" scenario).  So we don't want to count on connections to\nAPRS-IS, or any internet connection.  How about if we had a local aprs server that\ncould be setup on-site?  The local server would consist of a radio, TNC, a\nserver (like a Raspberry Pi perhaps), and a wifi access point.\n\nThe individual users connect to the local-aprs server through their wireless\ndevices, on the local wi-fi.  Now they can see tactical information\n(bulletins, object status, etc) on their cell-phones even though there may\nnot be internet or cellular coverage.  And they're connected to the wider-area\ntactical situation through APRS.  They can exchange messages, set beacons,\nupdate objects, etc.  They still have the handheld radios, obviously,\nfor coordination and instructions, and anything that doesn't fit on APRS,\nbut the voice channel now doesn't have to be tied up with\nstatus and position reports.\n\nEvent controllers or others could also access the tactical situation through\ntablets or laptops.  This is not unlike Bob's [ZipLan](http://aprs.org/APRS-docs/ZIP-LAN.TXT) concept, only implemented with\nwi-fi.\n\nEffectively, local-aprs allows multiple amateurs to share the APRS radio\nhardware within the range of the local wi-fi access point.  Then data can be\nshared over the range of the APRS digipeaters, as usual.\n\nThe same basic system could be used in a home network, so you can check the\n\"over-the-air\" APRS status through your phone, tablet, or installed in a car,\nto connect with APRS messaging (put the radio and wifi interface in the trunk,\nand then see the status on your phone).\n\n# System Architecture\n\nThere is a server component running under Node.js that connects to the TNC and\nradio through whatever serial connections are required.  The proof-of-concept\nsystem uses a Raspberry Pi connected to a Pac-Comm 320 TNC, connected to a\nYaesu FT2400 radio.\n\nThe server component runs the Express web server, and starts up a monitor\non the serial port.  When data comes in, it gets passed through the KISS framing\nparser and APRS parser contained in the 'utils-for-aprs' project, and stored in\nJSON format.  The last\nhour's packets are stored for replay when a client connects.  Live packets\nare repeated out to the clients using web sockets.\n\nThe client is an Angular application that's served out by the server.  It runs\nin the client's browser, and communicates back to the server using web sockets.\nIt provides responsive-web\ncharacteristics, so it runs on a variety of devices.\n\nUpon initial connection, the server plays back the last hour's packets, so that\nthe user has an instantly-available view of the APRS situation.  (Note - this\nis a neat thing about APRS.  Since the protocol has a \"Net Cycle Time\" of 30\nminutes max, all the senders will repeat their packets within this time.  So\nthe server doesn't have to do any \"intelligent\" status recording.  It just has to\nreplay the packets, and the clients are automatically current). The web socket\nconnection remains open.  Any APRS packets received by the TNC are\nsent out the web socket connections by the server.\n\nThe server can also serve out local copies of \"slippy map\" tiles for the local\narea, to support clients that are big enough to display maps.\n\nThe client will need to authenticate to the server and also establish the identity\nof the human user, so that the right call sign, etc, can be used.  It is also\npossible to establish a receive-only connection that doesn't require a call sign\n(e.g. for EOC displays or unlicensed users monitoring the tactical situation).\n\nWhen the client wants to send an APRS message, it sends the message to the server\nusing its open websocket connection.  The packet is in the JSON format\nas produced by the APRSParser. The server sends the packet out over the TNC\nas a \"third-party\" packet, and also handles re-sends and the packet decay\nalgorithm (the server \"owns\" the radio, so gets to manage the traffic over it).\n\nIf required, the server can also run a local digipeater.\n\nThis project includes the code for the web socket server that connects to the\nTNC and radio.  The TNC connection is KISS-over-TCP to localhost:8001\n\nThe client application will be separate, as will the map server.  All the pieces\nwill end up as separate applications that are installed behind a front-end web\nserver (e.g. Apache).\n\n# Running the system\n\nRight now, the system is a development-mode system. In\norder to run, clone the repository and then run   \n    gulp  \nCopy the 'config.json.sample' file to 'config.json' and edit it to reflect the\nrequired KISS port and KISS host.  For example, if you're using Dire Wolf\non the local machine, then you'd set them as follows:\n\n    {\n      \"kiss-host\": \"localhost\",\n      \"kiss-port\": 8001,\n      \"standardPacketMinutesToLive\": 60,\n      \"bulletinHoursToLive\": 4,\n      \"announcementHoursToLive\": 24\n    }\n\nIf you were using 'share-tnc' on a host called 'raspberrypi', you'd set it like:\n\n    {\n      \"kiss-host\": \"raspberrypi\",\n      \"kiss-port\": 8001,\n      \"standardPacketMinutesToLive\": 60,\n      \"bulletinHoursToLive\": 4,\n      \"announcementHoursToLive\": 24\n    }\n\nNow, run 'npm start' or 'gulp run', and the system will startup\nand begin to serve out the application,\nwhich you can access at localhost:3000.\n\n# Portability\n\nlocal-aprs has been tested on OSX and Windows 7, and should be good to go\nwherever you can run Node.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrasukg%2Flocal-aprs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrasukg%2Flocal-aprs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrasukg%2Flocal-aprs/lists"}