Compare commits
3 commits
39ad571465
...
08a1672c97
Author | SHA1 | Date | |
---|---|---|---|
Wolfgang | 08a1672c97 | ||
Wolfgang | 5e6e486290 | ||
Wolfgang | d715fa5337 |
45
README.md
45
README.md
|
@ -1,2 +1,47 @@
|
||||||
# dapnet2ntfy
|
# dapnet2ntfy
|
||||||
|
|
||||||
|
**dapnet2ntfy** forwards messages from the [DAPNET](https://hampager.de/) to [ntfy](https://ntfy.sh/).
|
||||||
|
|
||||||
|
Similar to other [gateways](https://hampager.de/dokuwiki/doku.php#gateways_apps), especially the [Telegram Bot DB0USD](https://hampager.de/dokuwiki/doku.php?id=usecasetelegrambot), it allows receiving messages, when there is no pager with reception at hand.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
### DAPNET account
|
||||||
|
|
||||||
|
A normal account at [hampager.de](https://support.hampager.de/open.php) (select 'Help Topic -> New DAPNET Account with or without RIC').
|
||||||
|
|
||||||
|
A transmitter registered at [hampager.de](https://support.hampager.de/open.php) (select 'Help Topic -> New DAPNET Transmitter').
|
||||||
|
|
||||||
|
### ntfy account
|
||||||
|
|
||||||
|
Use ntfy.sh or set up your own server: [DOCS](https://docs.ntfy.sh/).
|
||||||
|
|
||||||
|
### perl modules
|
||||||
|
|
||||||
|
- IO::Socket::INET
|
||||||
|
- IO::Socket::Timeout
|
||||||
|
- Errno
|
||||||
|
- HTTP::Request
|
||||||
|
- LWP::UserAgent
|
||||||
|
- MIME::Base64
|
||||||
|
- POSIX
|
||||||
|
- utf8
|
||||||
|
|
||||||
|
#### For Debian:
|
||||||
|
|
||||||
|
```console
|
||||||
|
apt install perl-base libio-socket-timeout-perl libhttp-message-perl libwww-perl
|
||||||
|
```
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Instructions for installing the script to $HOME/bin/
|
||||||
|
```console
|
||||||
|
mkdir -p $HOME/.config/systemd/user/
|
||||||
|
cp dapnet2ntfy.service $HOME/.config/systemd/user/
|
||||||
|
mkdir -p $HOME/bin
|
||||||
|
install -m 700 dapnet2ntfy.pl $HOME/bin/
|
||||||
|
# edit the configuration section to your needs
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable dapnet2ntfy.service --now
|
||||||
|
```
|
||||||
|
|
197
dapnet2ntfy.pl
Executable file
197
dapnet2ntfy.pl
Executable file
|
@ -0,0 +1,197 @@
|
||||||
|
#!/usr/bin/env perl
|
||||||
|
|
||||||
|
# Protocol for connecting transmitters to DAPNET:
|
||||||
|
# https://hampager.de/dokuwiki/doku.php?id=dapnetprotocol
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
|
||||||
|
# configuration
|
||||||
|
my $version = '0.5.0';
|
||||||
|
my $dapnet_username = '';
|
||||||
|
my $dapnet_password = '';
|
||||||
|
my $dapnet_server = 'dapnet.afu.rwth-aachen.de';
|
||||||
|
#my $dapnet_server = 'db0dbn.ig-funk-siebengebirge.de';
|
||||||
|
my $dapnet_port = '43434',
|
||||||
|
my $ntfy_username = '';
|
||||||
|
my $ntfy_password = '';
|
||||||
|
my $ntfy_url = 'https://server/topic';
|
||||||
|
my $debug = 1;
|
||||||
|
my $dapnet_timeout_read_seconds = 125;
|
||||||
|
my $dapnet_timeout_write_seconds = 5;
|
||||||
|
|
||||||
|
my %rics = (
|
||||||
|
# on pager
|
||||||
|
'630224' => 'PM',
|
||||||
|
'1041' => 'MOWAS',
|
||||||
|
'1063' => 'METAR',
|
||||||
|
'1064' => 'WX-Lokal',
|
||||||
|
'1080' => 'APRS-WX',
|
||||||
|
'1081' => 'DWD',
|
||||||
|
# for info
|
||||||
|
# all
|
||||||
|
'1001' => 'DAPNET-News',
|
||||||
|
'1028' => 'Clubnews',
|
||||||
|
#'1060' => 'Stats',
|
||||||
|
# dl-all
|
||||||
|
'1016' => 'DL-HH',
|
||||||
|
'1040' => 'Notfunk-DL',
|
||||||
|
'1044' => 'HAMNET',
|
||||||
|
'1055' => 'DAPNET-Team',
|
||||||
|
'1058' => 'xOTA',
|
||||||
|
# dl-hh
|
||||||
|
'1042' => 'Notfunk-Lokal',
|
||||||
|
'1083' => 'Feinstaub',
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
# start of program
|
||||||
|
use IO::Socket::INET;
|
||||||
|
use IO::Socket::Timeout;;
|
||||||
|
use Errno qw(ETIMEDOUT EWOULDBLOCK);
|
||||||
|
use HTTP::Request ();
|
||||||
|
use LWP::UserAgent;
|
||||||
|
use MIME::Base64;
|
||||||
|
use POSIX qw(strftime);
|
||||||
|
use utf8;
|
||||||
|
|
||||||
|
my $run = 1;
|
||||||
|
$SIG{INT} = sub {
|
||||||
|
print STDERR "terminating\n";
|
||||||
|
$run = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
sub debug_print {
|
||||||
|
if ($debug) {
|
||||||
|
print STDERR strftime("%F %T", localtime) . " $_[0]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub decode_umlauts {
|
||||||
|
# [\]{|}~ -> ÄÖÜäöüß
|
||||||
|
my $s = $_[0];
|
||||||
|
$s =~ tr/[\\]{|}~/ÄÖÜäöüß/;
|
||||||
|
utf8::encode($s);
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub decode_skyper
|
||||||
|
{
|
||||||
|
# message is ROT-1 encoded
|
||||||
|
my $s = '';
|
||||||
|
foreach my $c (split('', $_[0])) {
|
||||||
|
$s = $s . chr(ord($c) - 1);
|
||||||
|
}
|
||||||
|
$s = decode_umlauts($s);
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
|
# replace decimal RIC with hex value
|
||||||
|
# better to do this now, not every time a message arrives
|
||||||
|
%rics = map { sprintf("%X", $_) => $rics{$_} } keys %rics;
|
||||||
|
|
||||||
|
my $ntfy_auth_header = 'Basic ' . encode_base64($ntfy_username . ':' . $ntfy_password);
|
||||||
|
|
||||||
|
while ($run) {
|
||||||
|
debug_print "connecting to $dapnet_server\n";
|
||||||
|
my $socket = IO::Socket::INET->new(
|
||||||
|
PeerAddr => $dapnet_server,
|
||||||
|
PeerPort => $dapnet_port,
|
||||||
|
Timeout => $dapnet_timeout_read_seconds,
|
||||||
|
Proto => 'tcp',
|
||||||
|
);
|
||||||
|
if (! $socket) {
|
||||||
|
print STDERR "connection problem, reconnect\n";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
# set up timeout for reading/writing
|
||||||
|
IO::Socket::Timeout->enable_timeouts_on($socket);
|
||||||
|
$socket->read_timeout($dapnet_timeout_read_seconds);
|
||||||
|
$socket->write_timeout($dapnet_timeout_write_seconds);
|
||||||
|
|
||||||
|
my $reconnect = 0;
|
||||||
|
#my $last_received = time;
|
||||||
|
|
||||||
|
# login
|
||||||
|
$socket->send("[dapnet2ntfy v$version $dapnet_username $dapnet_password]\r\n");
|
||||||
|
while (!$reconnect) {
|
||||||
|
$reconnect = 0;
|
||||||
|
my $data = <$socket>;
|
||||||
|
if (! $data && ( 0+$! == ETIMEDOUT || 0+$! == EWOULDBLOCK )) {
|
||||||
|
print STDERR "timeout, reconnect\n";
|
||||||
|
$reconnect = 1;
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
#$socket->recv($data,1024);
|
||||||
|
chomp $data;
|
||||||
|
debug_print "received: $data.\n" ;
|
||||||
|
if ($data =~ /^2:(.*)$/) {
|
||||||
|
# ident to server
|
||||||
|
# example: 2:00AF
|
||||||
|
$socket->send("2:$1:0000\r\n+\r\n");
|
||||||
|
} elsif ($data =~ /^([34]):.*$/) {
|
||||||
|
# time sync and time slot
|
||||||
|
# example: 3:+0090
|
||||||
|
# example: 4:048C
|
||||||
|
$socket->send("+\r\n");
|
||||||
|
if ($1 == '4') {
|
||||||
|
print STDERR "listening to $dapnet_server\n";
|
||||||
|
}
|
||||||
|
} elsif ($data =~ /^7/) {
|
||||||
|
# login failed
|
||||||
|
print STDERR "login to $dapnet_server failed:\n";
|
||||||
|
print STDERR "$data\n";
|
||||||
|
$run = 0;
|
||||||
|
} elsif ($data =~ /^#([0-9a-fA-F]+) (.*)$/) {
|
||||||
|
# messages
|
||||||
|
# example: #02 6:1:D8:3:YYYYMMDDHHMMSS231222141600
|
||||||
|
|
||||||
|
# increase counter and send it back
|
||||||
|
my $cnt = hex $1;
|
||||||
|
if ($cnt >= 255) {
|
||||||
|
# reset counter on FF
|
||||||
|
$cnt = 0;
|
||||||
|
} else {
|
||||||
|
++$cnt;
|
||||||
|
}
|
||||||
|
$socket->send('#' . sprintf("%02X", $cnt) . " +\r\n");
|
||||||
|
|
||||||
|
# parse message
|
||||||
|
my ($type, $speed, $ric, $bit, $msg) = split(/:/, $2, 5);
|
||||||
|
# ignore speed, and bit
|
||||||
|
# split only 5 times, message can contain :
|
||||||
|
if ($type == '6') {
|
||||||
|
# type 6 is for messages
|
||||||
|
if (exists($rics{$ric})) {
|
||||||
|
# ric is in wanted list
|
||||||
|
# send to ntfy
|
||||||
|
my $ua = LWP::UserAgent->new;
|
||||||
|
my $request = HTTP::Request->new(
|
||||||
|
'POST',
|
||||||
|
$ntfy_url,
|
||||||
|
[ 'Authorization' => $ntfy_auth_header ],
|
||||||
|
"DAPNET: $rics{$ric}: " . decode_umlauts($msg)
|
||||||
|
);
|
||||||
|
my $response = $ua->request($request);
|
||||||
|
} elsif ($debug && ($ric =~ /^11A[08]$/)) {
|
||||||
|
# skyper message
|
||||||
|
debug_print "Skyper message: " . decode_skyper($msg) . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elsif ($data eq '') {
|
||||||
|
print STDERR "connection problem, reconnect\n";
|
||||||
|
$reconnect = 1;
|
||||||
|
}
|
||||||
|
#if (time - $last_received > $dapnet_timeout_read_seconds) {
|
||||||
|
# print STDERR "timeout, reconnect\n";
|
||||||
|
# $reconnect = 1;
|
||||||
|
#} else {
|
||||||
|
# $last_received = time;
|
||||||
|
#}
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
#$socket->close();
|
||||||
|
$socket->shutdown(SHUT_RDWR);
|
||||||
|
}
|
11
dapnet2ntfy.service
Normal file
11
dapnet2ntfy.service
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Gateway for messages from DAPNET to ntfy
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=%h/bin/dapnet2ntfy.pl
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
|
Loading…
Reference in a new issue