Added DAPNET (POCSAG)
Added new Tab for DAPNET and modified Readme.md
This commit is contained in:
parent
82d56d1e52
commit
032e89b3af
5 changed files with 185 additions and 61 deletions
|
@ -29,5 +29,9 @@ Actually known:
|
|||
|
||||
Finally you should be able to get the new Dashboard calling the hostname of your hotspot and port 8000 (default) in your broser
|
||||
|
||||
## Credits
|
||||
|
||||
*logtailer.py* is based on the work of http://shzhangji.com/blog/2017/07/15/log-tailer-with-websocket-and-python/
|
||||
|
||||
## Screenshots
|
||||
![Screenshot of MMDVMDash Websocketboard](img/Screenshot.png "Screenshot of MMDVMDash Websocketboard")
|
|
@ -49,6 +49,9 @@
|
|||
<li class="nav-item">
|
||||
<a class="nav-link" id="qso-tab" data-toggle="tab" href="#qso" role="tab" aria-controls="qso" aria-selected="false">In QSO</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="dapnet-tab" data-toggle="tab" href="#dapnet" role="tab" aria-controls="dapnet" aria-selected="false">DAPNET Messages</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="about-tab" data-toggle="tab" href="#about" role="tab" aria-controls="about" aria-selected="false">About</a>
|
||||
</li>
|
||||
|
@ -124,7 +127,27 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="dapnet" role="tabpanel" aria-labelledby="dapnet-tab">
|
||||
<div class="panel panel-default">
|
||||
<!-- Standard-Panel-Inhalt -->
|
||||
<div class="panel-heading">Dapnet-Messages<span class="pull-right clickable"><i class="glyphicon glyphicon-chevron-up"></i></span></div>
|
||||
<div class="panel-body">
|
||||
<!-- Tabelle -->
|
||||
<div class="table-responsive">
|
||||
<table id="dapnetmessages" class="table dapnetmessages table-condensed table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Time (UTC)</th>
|
||||
<th>Slot</th>
|
||||
<th>RIC</th>
|
||||
<th>Message</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="about" role="tabpanel" aria-labelledby="about-tab">
|
||||
<div class="panel panel-default">
|
||||
<!-- Standard-Panel-Inhalt -->
|
||||
|
@ -145,8 +168,13 @@
|
|||
var t_localh = $('#localHeard').DataTable( {
|
||||
"order": [[ 0, "desc" ]]
|
||||
} );
|
||||
var ws = new WebSocket("ws://" + window.location.hostname + ":5678");
|
||||
ws.onmessage = function (event) {
|
||||
|
||||
var t_dapnet = $('#dapnetmessages').DataTable( {
|
||||
"order": [[ 0, "desc" ]]
|
||||
} );
|
||||
|
||||
var ws1 = new WebSocket("ws://" + window.location.hostname + ":5678/MMDVM");
|
||||
ws1.onmessage = function (event) {
|
||||
getLastHeard(document, event);
|
||||
getLocalHeard(document, event);
|
||||
};
|
||||
|
@ -170,6 +198,12 @@
|
|||
$('#button').click( function () {
|
||||
t_qso.row('.selected').remove().draw( false );
|
||||
} );
|
||||
|
||||
var ws2 = new WebSocket("ws://" + window.location.hostname + ":5678/DAPNET");
|
||||
ws2.onmessage = function (event) {
|
||||
getDapnetMessages(document, event);
|
||||
};
|
||||
t_dapnet.order( [ 0, 'desc' ] ).draw();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// M: 2020-11-01 21:33:27.454 YSF, received network data from DG2MAS to DG-ID 0 at DG2MAS
|
||||
// M: 2020-11-01 21:33:35.025 YSF, received network end of transmission from DG2MAS to DG-ID 0, 7.7 seconds, 0% packet loss, BER: 0.0%
|
||||
function getTimestamp(logline) {
|
||||
return logline.substring(3,22);
|
||||
return logline.substring(3,26);
|
||||
}
|
||||
|
||||
function getMode(logline) {
|
||||
|
@ -72,6 +72,58 @@ function getAddToQSO(logline) {
|
|||
retval = '<div class="bd-clipboard"><button type="button" class="btn-cpQSO" title="Copy to QSO" id="' + callsign + '" onclick="copyToQSO(\'' + callsign + '\')">Copy</button></div>';
|
||||
return retval;
|
||||
}
|
||||
/*
|
||||
|
||||
*/
|
||||
// 00000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000111111111122222222223333333333
|
||||
// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
|
||||
// M: 2020-11-03 19:33:26.411 Sending message in slot 5 to 0000224, type 6, func Alphanumeric: "YYYYMMDDHHMMSS201103203300"
|
||||
// M: 2020-11-03 19:36:00.124 Sending message in slot 13 to 0002504, type 5, func Numeric: "193600 031120"
|
||||
// M: 2020-11-03 19:36:00.165 Sending message in slot 13 to 0000200, type 6, func Alphanumeric: "XTIME=1936031120XTIME=1936031120"
|
||||
// M: 2020-11-03 19:36:00.216 Sending message in slot 13 to 0000216, type 6, func Alphanumeric: "YYYYMMDDHHMMSS201103193600"
|
||||
|
||||
function getSlot(logline) {
|
||||
return logline.substring(logline.indexOf("slot") + 5, logline.indexOf("to ")).trim();
|
||||
}
|
||||
|
||||
function getRIC(logline) {
|
||||
return logline.substring(logline.indexOf("to ") + 3, logline.indexOf(", type")).trim();
|
||||
}
|
||||
|
||||
function getMessage(logline) {
|
||||
message = logline.substring(logline.indexOf("ric:") + 6);
|
||||
message = message.substring(0, message.length - 1);
|
||||
if (4520 == parseInt(getRIC(logline))) {
|
||||
message = rot1(message);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
function ord(str) {
|
||||
return str.charCodeAt(0);
|
||||
}
|
||||
|
||||
function chr(n) {
|
||||
return String.fromCharCode(n);
|
||||
}
|
||||
|
||||
function rot1(text) {
|
||||
ric = 0;
|
||||
slot = 0;
|
||||
out = "";
|
||||
for (i = 0; i < text.length; i++) {
|
||||
if (i == 0) {
|
||||
ric = ord(text[i])-31;
|
||||
}
|
||||
if (i == 1) {
|
||||
slot = ord(text[i])-32;
|
||||
}
|
||||
if (i > 1) {
|
||||
out += chr(ord(text[i])-1);
|
||||
}
|
||||
}
|
||||
return "Skyper-Rubric-No.: " + ric + ", Slot: " + slot + ", message: " + out;
|
||||
}
|
||||
|
||||
function clocktime() {
|
||||
var now = new Date(),
|
||||
|
@ -106,60 +158,60 @@ function getLastHeard(document, event) {
|
|||
// M: 2020-11-01 21:33:27.454 YSF, received network data from DG2MAS to DG-ID 0 at DG2MAS
|
||||
// M: 2020-11-01 21:33:35.025 YSF, received network end of transmission from DG2MAS to DG-ID 0, 7.7 seconds, 0% packet loss, BER: 0.0%
|
||||
if (event.data.indexOf("Talker Alias") < 0 && event.data.indexOf("Downlink Activate") < 0 && event.data.indexOf("network watchdog") < 0 ) {
|
||||
$(document).ready(function() {
|
||||
var rowIndexes = [],
|
||||
timestamp = getTimestamp(event.data),
|
||||
mode = getMode(event.data),
|
||||
callsign = getCallsign(event.data),
|
||||
target = getTarget(event.data),
|
||||
source = getSource(event.data),
|
||||
duration = getDuration(event.data),
|
||||
loss = getLoss(event.data),
|
||||
ber = getBER(event.data),
|
||||
addToQSO = getAddToQSO(event.data);
|
||||
if (mode == "POCSAG") {
|
||||
callsign = "POCSAG";
|
||||
target = "";
|
||||
source = "";
|
||||
duration = "";
|
||||
loss = "";
|
||||
ber = "";
|
||||
addToQSO = "";
|
||||
}
|
||||
t_lh.rows( function ( idx, data, node ) {
|
||||
if(data[2] === callsign){
|
||||
rowIndexes.push(idx);
|
||||
$(document).ready(function() {
|
||||
var rowIndexes = [],
|
||||
timestamp = getTimestamp(event.data),
|
||||
mode = getMode(event.data),
|
||||
callsign = getCallsign(event.data),
|
||||
target = getTarget(event.data),
|
||||
source = getSource(event.data),
|
||||
duration = getDuration(event.data),
|
||||
loss = getLoss(event.data),
|
||||
ber = getBER(event.data),
|
||||
addToQSO = getAddToQSO(event.data);
|
||||
if (mode == "POCSAG") {
|
||||
callsign = "POCSAG";
|
||||
target = "";
|
||||
source = "";
|
||||
duration = "";
|
||||
loss = "";
|
||||
ber = "";
|
||||
addToQSO = "";
|
||||
}
|
||||
return false;
|
||||
});
|
||||
t_lh.rows( function ( idx, data, node ) {
|
||||
if(data[2] === callsign){
|
||||
rowIndexes.push(idx);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (rowIndexes[0]) {
|
||||
newData = [
|
||||
timestamp,
|
||||
mode,
|
||||
callsign,
|
||||
target,
|
||||
source,
|
||||
duration,
|
||||
loss,
|
||||
ber,
|
||||
addToQSO
|
||||
]
|
||||
t_lh.row(rowIndexes[0]).data( newData ).draw();
|
||||
} else {
|
||||
t_lh.row.add( [
|
||||
timestamp,
|
||||
mode,
|
||||
callsign,
|
||||
target,
|
||||
source,
|
||||
duration,
|
||||
loss,
|
||||
ber,
|
||||
addToQSO
|
||||
] ).draw();
|
||||
}
|
||||
});
|
||||
if (rowIndexes[0]) {
|
||||
newData = [
|
||||
timestamp,
|
||||
mode,
|
||||
callsign,
|
||||
target,
|
||||
source,
|
||||
duration,
|
||||
loss,
|
||||
ber,
|
||||
addToQSO
|
||||
]
|
||||
t_lh.row(rowIndexes[0]).data( newData ).draw();
|
||||
} else {
|
||||
t_lh.row.add( [
|
||||
timestamp,
|
||||
mode,
|
||||
callsign,
|
||||
target,
|
||||
source,
|
||||
duration,
|
||||
loss,
|
||||
ber,
|
||||
addToQSO
|
||||
] ).draw();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,3 +236,23 @@ function getLocalHeard(document, event) {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getDapnetMessages(document, event) {
|
||||
lines = event.data.split("\n");
|
||||
|
||||
//alert(line.indexOf("Sending") > 0);
|
||||
$(document).ready(function() {
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
var line = lines[i];
|
||||
if (line.indexOf("Sending") > 0 ) {
|
||||
t_dapnet.row.add( [
|
||||
getTimestamp(line),
|
||||
getSlot(line),
|
||||
getRIC(line),
|
||||
getMessage(line)
|
||||
] ).draw();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -7,3 +7,8 @@ Webport=8080
|
|||
Logdir=/mnt/ramdisk/
|
||||
Prefix=MMDVM
|
||||
Num_Lines=10000
|
||||
|
||||
[DAPNETGateway]
|
||||
Logdir=/mnt/ramdisk/
|
||||
Prefix=DAPNETGateway
|
||||
|
||||
|
|
19
logtailer.py
19
logtailer.py
|
@ -30,6 +30,12 @@ def view_log(websocket, path):
|
|||
logging.info('Connected, remote={}, path={}'.format(websocket.remote_address, path))
|
||||
|
||||
try:
|
||||
try:
|
||||
parse_result = urlparse(path)
|
||||
except Exception:
|
||||
raise ValueError('Fail to parse URL')
|
||||
|
||||
path = os.path.abspath(parse_result.path)
|
||||
now = datetime.datetime.now()
|
||||
year = str(now.year)
|
||||
month = str(now.month)
|
||||
|
@ -39,19 +45,22 @@ def view_log(websocket, path):
|
|||
if len(day) == 1:
|
||||
day = "0" + day
|
||||
|
||||
file_path = config['MMDVMHost']['Logdir']+config['MMDVMHost']['Prefix']+"-"+year+"-"+month+"-"+day+".log"
|
||||
|
||||
file_path = ""
|
||||
if path == "/MMDVM":
|
||||
file_path = config['MMDVMHost']['Logdir']+config['MMDVMHost']['Prefix']+"-"+year+"-"+month+"-"+day+".log"
|
||||
elif path == "/DAPNET":
|
||||
file_path = config['DAPNETGateway']['Logdir']+config['DAPNETGateway']['Prefix']+"-"+year+"-"+month+"-"+day+".log"
|
||||
logging.info(file_path)
|
||||
if not os.path.isfile(file_path):
|
||||
raise ValueError('Not found')
|
||||
|
||||
path = file_path
|
||||
with open(file_path) as f:
|
||||
with open(file_path, newline = '\n') as f:
|
||||
|
||||
content = ''.join(deque(f, NUM_LINES))
|
||||
content = conv.convert(content, full=False)
|
||||
lines = content.split("\n")
|
||||
for line in lines:
|
||||
if line.find('received') >0 and not line.find('network watchdog') > 0:
|
||||
if line.find('received') >0 or line.find('Sending') > 0:
|
||||
yield from websocket.send(line)
|
||||
|
||||
while True:
|
||||
|
|
Loading…
Reference in a new issue