Compare commits

...

19 Commits

Author SHA1 Message Date
Waldek 6459f464d5
Update requirements.txt 2022-03-02 12:46:15 +01:00
Waldek 1437717baf
Update monitor.py 2021-05-22 12:20:42 +02:00
Waldek 41f2b476da
Update requirements.txt 2021-05-16 11:48:16 +02:00
Waldek 14da413cde
Update README.md 2021-05-13 07:50:54 +02:00
Waldek 28593d7d83
Add files via upload 2021-05-03 16:29:42 +02:00
Waldek e5c06f09d4
Delete talkgroup_ids.json 2021-05-03 16:29:26 +02:00
Waldek e88ce75a3f
Timeout typical TOT 180 sec for missing END of TX info 2021-04-07 06:33:54 +02:00
Waldek 79fae60b61
Update README.md 2021-04-05 19:22:57 +02:00
Waldek c8bea5ebec
TX time round a number upward 2021-04-05 18:42:23 +02:00
Waldek e198d65292
updated LH code 2021-04-05 13:29:24 +02:00
Waldek c0f77cd5a3
remove LASTHEARD_INC 2021-04-05 10:58:02 +02:00
Waldek df5bb45e87
remove LASTHEARD_INC 2021-04-05 10:57:25 +02:00
Waldek 6559eb1de9
remove LASTHERAD_INC 2021-04-05 10:56:54 +02:00
Waldek 1ff80680c6
Update config_SAMPLE.py 2021-04-05 10:34:08 +02:00
Waldek 5d3cca44dd
changed format code 2021-04-05 10:31:22 +02:00
Waldek 12ea9ae665
Update main_table.html 2021-04-05 10:24:24 +02:00
Waldek 748d9bb958
Update index_template.html 2021-04-05 10:08:38 +02:00
Waldek 6a06963030
Lastheard with TX-ing 2021-04-05 10:07:48 +02:00
Waldek 3b44c3c76e
remove table 2021-04-05 09:54:19 +02:00
7 changed files with 96 additions and 2403 deletions

View File

@ -16,6 +16,7 @@ This is version HBMonitor V2
cd /opt cd /opt
git clone https://github.com/sp2ong/HBMonv2.git git clone https://github.com/sp2ong/HBMonv2.git
cd HBMonv2 cd HBMonv2
git checkout TXing-webpython
chmod +x install.sh chmod +x install.sh
./install.sh ./install.sh
cp config-SAMPLE.py config.py cp config-SAMPLE.py config.py
@ -33,11 +34,6 @@ This is version HBMonitor V2
If you use openbrige links, in config.py in OPB_FILTER enter NETWORK_ID to do not display If you use openbrige links, in config.py in OPB_FILTER enter NETWORK_ID to do not display
unnecessary entries in LASTHEARD. unnecessary entries in LASTHEARD.
Please remember the table lastheard displays only station transmissions that are longer than 2 seconds.
If you don't want to have the lastheard list set in config.py:
LASTHEARD_INC = False
If you want to have more than the last 15 entries in the Lastherad table If you want to have more than the last 15 entries in the Lastherad table
change in the monitor.py file line from change in the monitor.py file line from
if n == 15: if n == 15:
@ -63,8 +59,6 @@ This is version HBMonitor V2
In directory sysinfo/ you can find info on how to setup display SYSTEM Info data in Monitor. In directory sysinfo/ you can find info on how to setup display SYSTEM Info data in Monitor.
If not need monitor online rules (I do not recommend please use in config.py BRIDGES_INC = False
--- ---
**hbmonitor3 by KC1AWV** **hbmonitor3 by KC1AWV**

View File

@ -2,7 +2,6 @@ REPORT_NAME = 'Dashboard of local DMR network' # Name of the monit
# #
CONFIG_INC = True # Include HBlink stats CONFIG_INC = True # Include HBlink stats
HOMEBREW_INC = True # Display Homebrew Peers status HOMEBREW_INC = True # Display Homebrew Peers status
LASTHEARD_INC = True # Display lastheard table on main page
BRIDGES_INC = False # Display Bridge status and button BRIDGES_INC = False # Display Bridge status and button
EMPTY_MASTERS = False # Display Enable (True) or DISABLE (False) empty masters in status EMPTY_MASTERS = False # Display Enable (True) or DISABLE (False) empty masters in status
# #
@ -43,7 +42,7 @@ THEME_COLOR = 'background-image: linear-gradient(to bottom, #337ab7 0%, #265
OPB_FILTER = "" OPB_FILTER = ""
# Authorization of access to dashboard # Authorization of access to dashboard
WEB_AUTH = True WEB_AUTH = False
WEB_USER = 'hblink' WEB_USER = 'hblink'
WEB_PASS = 'hblink' WEB_PASS = 'hblink'

View File

@ -34,6 +34,7 @@ import datetime
import os import os
import csv import csv
import math
from itertools import islice from itertools import islice
from subprocess import check_call, CalledProcessError from subprocess import check_call, CalledProcessError
@ -107,7 +108,6 @@ YELLOW = 'fffccd'
URL_PATH = 'main' URL_PATH = 'main'
# Define setup setings # Define setup setings
CTABLE['SETUP']['LASTHEARD'] = LASTHEARD_INC
BTABLE['SETUP']['BRIDGES'] = BRIDGES_INC BTABLE['SETUP']['BRIDGES'] = BRIDGES_INC
# OPB Filter for lastheard # OPB Filter for lastheard
@ -738,49 +738,17 @@ def process_message(_bmessage):
p = _message[1:].split(",") p = _message[1:].split(",")
rts_update(p) rts_update(p)
opbfilter = get_opbf() opbfilter = get_opbf()
# open lastheard.log file
lh_logfile = open(LOG_PATH+"lastheard.log", "a")
if p[0] == 'GROUP VOICE' and p[2] != 'TX' and p[5] not in opbfilter: if p[0] == 'GROUP VOICE' and p[2] != 'TX' and p[5] not in opbfilter:
if p[1] == 'END': if p[1] == 'END':
log_message = '{} {} {} SYS: {:8.8s} SRC_ID: {:9.9s} TS: {} TGID: {:7.7s} {:17.17s} SUB: {:9.9s}; {:18.18s} Time: {}s '.format(_now[10:19], p[0][6:], p[1], p[3], p[5], p[7],p[8],alias_tgid(int(p[8]),talkgroup_ids), p[6], alias_short(int(p[6]), subscriber_ids), int(float(p[9]))) log_message = '{} {} {} SYS: {:8.8s} SRC_ID: {:9.9s} TS: {} TGID: {:7.7s} {:17.17s} SUB: {:9.9s}; {:18.18s} Time: {}s '.format(_now[10:19], p[0][6:], p[1], p[3], p[5], p[7],p[8],alias_tgid(int(p[8]),talkgroup_ids), p[6], alias_short(int(p[6]), subscriber_ids), int(float(p[9])))
# log only to file if system is NOT OpenBridge event (not logging open bridge system, name depends on your OB definitions) AND transmit time is LONGER as 2sec (make sense for very short transmits)
if LASTHEARD_INC:
if int(float(p[9]))> 2:
log_lh_message = '{},{},{},{},{},{},{},TS{},TG{},{},{},{}'.format(_now, p[9], p[0], p[1], p[3], p[5], alias_call(int(p[5]), subscriber_ids), p[7], p[8],alias_tgid(int(p[8]),talkgroup_ids),p[6], alias_short(int(p[6]), subscriber_ids)) log_lh_message = '{},{},{},{},{},{},{},TS{},TG{},{},{},{}'.format(_now, p[9], p[0], p[1], p[3], p[5], alias_call(int(p[5]), subscriber_ids), p[7], p[8],alias_tgid(int(p[8]),talkgroup_ids),p[6], alias_short(int(p[6]), subscriber_ids))
lh_logfile = open(LOG_PATH+"lastheard.log", "a")
lh_logfile.write(log_lh_message + '\n') lh_logfile.write(log_lh_message + '\n')
lh_logfile.close()
# Lastheard in Dashboard by SP2ONG
my_list=[]
n=0
f = open(PATH+"templates/lastheard.html", "w")
f.write("<br><fieldset style=\"border-radius: 8px; background-color:#f0f0f0f0;margin-left:15px;margin-right:15px;font-size:14px;border-top-left-radius: 10px; border-top-right-radius: 10px;border-bottom-left-radius: 10px; border-bottom-right-radius: 10px;\">\n")
f.write("<legend><b><font color=\"#000\">&nbsp;.: Lastheard :.&nbsp;</font></b></legend>\n")
f.write("<table style=\"width:100%; font: 10pt arial, sans-serif\">\n")
f.write("<TR style=\" height: 32px;font: 10pt arial, sans-serif;"+THEME_COLOR+"\"><TH>Date</TH><TH>Time</TH><TH>Callsign (DMR-Id)</TH><TH>Name</TH><TH>TG#</TH><TH>TG Name</TH><TH>TX (s)</TH><TH>Slot</TH><TH>System</TH></TR>\n")
with open(LOG_PATH+"lastheard.log", "r") as textfile:
for row in islice(reversed(list(csv.reader(textfile))),200):
duration=row[1]
dur=str(int(float(duration.strip())))
if row[10] not in my_list:
if row[11].strip().isdigit() or row[11] == "N0CALL" or row[11] == "NOCALL":
qrz = "<b><font color=#464646>"+row[11]+"</font></b>"
else:
qrz = "<a style=\"font: 9pt arial,sans-serif;font-weight:bold;color:#0066ff;\" target=\"_blank\" href=https://qrz.com/db/"+row[11]+">"+row[11]+"</a></b><span style=\"font: 7pt arial,sans-serif\"> ("+row[10]+")</span>"
if len(row) < 13:
hline="<TR style=\"background-color:#f9f9f9f9;\"><TD>"+row[0][:10]+"</TD><TD>"+row[0][11:16]+"</TD><TD>"+qrz+"</TD><TD><font color=#002d62><b></b></font></TD><TD><font color=#b5651d><b>"+row[8][2:]+"</b></font></TD><TD><font color=green><b>"+row[9]+"</b></font></TD><TD>"+dur+"</TD><TD>"+row[7][2:]+"</TD><TD>"+row[4]+"</TD></TR>"
my_list.append(row[10])
n += 1
else:
hline="<TR style=\"background-color:#f9f9f9f9;\"><TD>"+row[0][:10]+"</TD><TD>"+row[0][11:16]+"</TD><TD>"+qrz+"</TD><TD><font color=#002d62><b>"+row[12]+"</b></font></TD><TD><font color=#b5651d><b>"+row[8][2:]+"</b></font></TD><TD><font color=green><b>"+row[9]+"</b></font></TD><TD>"+dur+"</TD><TD>"+row[7][2:]+"</TD><TD>"+row[4]+"</TD></TR>"
my_list.append(row[10])
n += 1
f.write(hline+"\n")
if n == 15:
break
f.write("</table></fieldset><br>")
f.close()
# End of Lastheard
elif p[1] == 'START': elif p[1] == 'START':
log_message = '{} {} {} SYS: {:8.8s} SRC_ID: {:9.9s} TS: {} TGID: {:7.7s} {:17.17s} SUB: {:9.9s}; {:18.18s}'.format(_now[10:19], p[0][6:], p[1], p[3], p[5], p[7],p[8], alias_tgid(int(p[8]),talkgroup_ids), p[6], alias_short(int(p[6]), subscriber_ids)) log_message = '{} {} {} SYS: {:8.8s} SRC_ID: {:9.9s} TS: {} TGID: {:7.7s} {:17.17s} SUB: {:9.9s}; {:18.18s}'.format(_now[10:19], p[0][6:], p[1], p[3], p[5], p[7],p[8], alias_tgid(int(p[8]),talkgroup_ids), p[6], alias_short(int(p[6]), subscriber_ids))
log_lh_message = '{},{},{},{},{},{},{},TS{},TG{},{},{},{}'.format(_now, 0, p[0], p[1], p[3], p[5], alias_call(int(p[5]), subscriber_ids), p[7], p[8],alias_tgid(int(p[8]),talkgroup_ids),p[6], alias_short(int(p[6]), subscriber_ids))
lh_logfile.write(log_lh_message + '\n')
elif p[1] == 'END WITHOUT MATCHING START': elif p[1] == 'END WITHOUT MATCHING START':
log_message = '{} {} {} on SYSTEM {:8.8s}: SRC_ID: {:9.9s} TS: {} TGID: {:7.7s} {:17.17s} SUB: {:9.9s}; {:18.18s}'.format(_now[10:19], p[0][6:], p[1], p[3], p[5], p[7], p[8],alias_tgid(int(p[8]),talkgroup_ids),p[6], alias_short(int(p[6]), subscriber_ids)) log_message = '{} {} {} on SYSTEM {:8.8s}: SRC_ID: {:9.9s} TS: {} TGID: {:7.7s} {:17.17s} SUB: {:9.9s}; {:18.18s}'.format(_now[10:19], p[0][6:], p[1], p[3], p[5], p[7], p[8],alias_tgid(int(p[8]),talkgroup_ids),p[6], alias_short(int(p[6]), subscriber_ids))
else: else:
@ -792,9 +760,67 @@ def process_message(_bmessage):
else: else:
logging.debug('{} UNKNOWN LOG MESSAGE'.format(_now[10:19])) logging.debug('{} UNKNOWN LOG MESSAGE'.format(_now[10:19]))
# close lastheard.log file
lh_logfile.close()
else: else:
logging.debug('got unknown opcode: {}, message: {}'.format(repr(opcode), repr(_message[1:]))) logging.debug('got unknown opcode: {}, message: {}'.format(repr(opcode), repr(_message[1:])))
# Lastheard with TX-ing in Dashboard by SP2ONG
my_list=[]
n = 0
f = open(PATH+"templates/lastheard.html", "w")
f.write("<fieldset style=\"border-radius: 8px; background-color:#f0f0f0f0;margin-left:15px;margin-right:15px;font-size:14px;border-top-left-radius: 10px; border-top-right-radius: 10px;border-bottom-left-radius: 10px; border-bottom-right-radius: 10px;\">\n")
f.write("<legend><b><font color=\"#000\">&nbsp;.: DMR Server activity :.&nbsp;</font></b></legend>\n")
f.write("<table style=\"width:100%; font: 10pt arial, sans-serif\">\n")
f.write("<TR style=\" height: 32px;font: 10pt arial, sans-serif;"+THEME_COLOR+"\"><TH>Date</TH><TH>Time</TH><TH>Callsign (DMR-Id)</TH><TH>Name</TH><TH>TG#</TH><TH>TG Name</TH><TH>&nbsp;TX (s)&nbsp;</TH><TH>System</TH></TR>\n")
with open(LOG_PATH+"lastheard.log", "r") as textfile:
for row in islice(reversed(list(csv.reader(textfile))),400):
duration_in_s = 0
duration=row[1]
dur=str(int(math.ceil(float(duration.strip()))))
year=int(float(row[0][:4].strip()))
month=int(float(row[0][5:7].strip()))
day=int(float(row[0][8:10].strip()))
hour=int(float(row[0][11:13].strip()))
min=int(float(row[0][14:16].strip()))
sec=int(float(row[0][17:19].strip()))
then = datetime.datetime(year, month, day, hour, min, sec)
now = datetime.datetime.now()
durations = now - then
duration_in_s = durations.total_seconds()
# Timeout typical TOT 180 sec for missing END of TX info
if dur=="0" and row[3]=="START" and duration_in_s < 180:
durtx='<td style=\"background:#f33; color:white;font-weight:bold;\">TX-ing</td>'
else:
if dur=="0":
txdur="&#8734;"
else:
txdur=str(int(math.ceil(float(duration.strip()))))
durtx="<td>"+txdur+"</td>"
if row[10] not in my_list:
if row[11].strip().isdigit() or row[11] == "N0CALL" or row[11] == "NOCALL":
qrz = "<b><font color=#464646>"+row[11]+"</font></b>"
else:
qrz = "<a style=\"font: 9pt arial,sans-serif;font-weight:bold;color:#0066ff;\" target=\"_blank\" href=https://qrz.com/db/"+row[11]+">"+row[11]+"</a></b><span style=\"font: 7pt arial,sans-serif\"> ("+row[10]+")</span>"
if len(row) < 13:
hline="<TR style=\"background-color:#f9f9f9f9;\"><TD>"+row[0][:10]+"</TD><TD>"+row[0][11:16]+"</TD><TD>"+qrz+"</TD><TD><font color=#002d62><b></b></font></TD><TD><font color=#b5651d><b>"+row[8][2:]+"</b></font></TD><TD><font color=green><b>"+row[9]+"</b></font></TD><TD>"+durtx+"</TD><TD>"+row[4]+"</TD></TR>"
my_list.append(row[10])
n += 1
else:
hline="<TR style=\"background-color:#f9f9f9f9;\"><TD>"+row[0][:10]+"</TD><TD>"+row[0][11:16]+"</TD><TD>"+qrz+"</TD><TD><font color=#002d62><b>"+row[12]+"</b></font></TD><TD><font color=#b5651d><b>"+row[8][2:]+"</b></font></TD><TD><font color=green><b>"+row[9]+"</b></font></TD><TD>"+durtx+"</TD><TD>"+row[4]+"</TD></TR>"
my_list.append(row[10])
n += 1
f.write(hline+"\n")
# n max number items in lastheard table
if n == 15:
break
f.write("</table></fieldset><br>")
f.close()
# refresh main page
main = 'i' + itemplate.render(_table=CTABLE,themec=THEME_COLOR,dbridges=BTABLE['SETUP']['BRIDGES'],auth=WEB_AUTH)
dashboard_server.broadcast(main)
def load_dictionary(_message): def load_dictionary(_message):
data = _message[1:] data = _message[1:]
return loads(data) return loads(data)

View File

@ -2,4 +2,6 @@ Twisted
dmr_utils3 dmr_utils3
bitstring bitstring
autobahn autobahn
jinja2 jinja2==2.11.3
markupsafe==2.0.1

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@
.button { <<<theme_color>>> } .button { <<<theme_color>>> }
.dropbtn { <<<theme_color>>> } .dropbtn { <<<theme_color>>> }
</style> </style>
<meta name="description" content="Copyright (c) 2016-2021.The Regents of the K0USY Group. All rights reserved. Version SP2ONG 2019-2021 (v20210401)" /> <meta name="description" content="Copyright (c) 2016-2021.The Regents of the K0USY Group. All rights reserved. Version SP2ONG 2019-2021 (v20210405)" />
</head> </head>
<body style="background-color: #d0d0d0;font: 10pt arial, sans-serif;"> <body style="background-color: #d0d0d0;font: 10pt arial, sans-serif;">
<center><div style="width:1250px; text-align: center; margin-top:5px;"> <center><div style="width:1250px; text-align: center; margin-top:5px;">
@ -34,7 +34,7 @@
--> -->
<div style="width: 1100px;"> <div style="width: 1100px;">
<p style="text-align: center;"><span style="text-align: center;"> <p style="text-align: center;"><span style="text-align: center;">
Copyright (c) 2016-2021<br>The Regents of the <a target="_blank" href=http://k0usy.mystrikingly.com/>K0USY Group</a>. All rights reserved.<br><a title="HBMonv2 SP2ONG v20210401" target="_blank" href=https://github.com/sp2ong/HBMonv2>Version SP2ONG 2019-2021</a><br><br></span> Copyright (c) 2016-2021<br>The Regents of the <a target="_blank" href=http://k0usy.mystrikingly.com/>K0USY Group</a>. All rights reserved.<br><a title="HBMonv2 SP2ONG v20210405" target="_blank" href=https://github.com/sp2ong/HBMonv2>Version SP2ONG 2019-2021</a><br><br></span>
<!-- THIS COPYRIGHT NOTICE MUST BE DISPLAYED AS A CONDITION OF THE LICENCE GRANT FOR THIS SOFTWARE. ALL DERIVATEIVES WORKS MUST CARRY THIS NOTICE --> <!-- THIS COPYRIGHT NOTICE MUST BE DISPLAYED AS A CONDITION OF THE LICENCE GRANT FOR THIS SOFTWARE. ALL DERIVATEIVES WORKS MUST CARRY THIS NOTICE -->
<!-- This is version of HBMonitor SP2ONG 2019-2021 (v20210401)--> <!-- This is version of HBMonitor SP2ONG 2019-2021 (v20210401)-->
</p> </p>

View File

@ -1,85 +1,10 @@
{% include 'buttons.html' ignore missing %} {% include 'buttons.html' ignore missing %}
<fieldset style="background-color:#f0f0f0f0;margin-left:15px;margin-right:15px;font-size:14px;border-top-left-radius: 10px; border-top-right-radius: 10px;border-bottom-left-radius: 10px; border-bottom-right-radius: 10px;"> {% include 'lastheard.html' ignore missing %}
<legend><b><font color="#000">&nbsp;.: DMR Server activity :.&nbsp;</font></b></legend>
{% if _table['MASTERS']|length >0 %}
<table style="table-layout:fixed;font: 10pt arial, sans-serif;margin-top:4px;margin-bottom:4px;" width=100%>
<tr style="height:30px;font: 10pt arial, sans-serif;{{ themec }}">
<th style='width: 20%;'>Systems M&P</th>
<th style='width: 40%;'>Source</th>
<th style='width: 40%;'>Destination</th>
</tr>
{% for _master in _table['MASTERS'] %}
{% for _client, _cdata in _table['MASTERS'][_master]['PEERS'].items() %}
{% if _cdata[1]['TS'] == True or _cdata[2]['TS'] == True %}
<tr style="background-color:#f9f9f9f9;line-height:1.4;">
{% if _cdata[1]['TRX'] == "RX" %}
<td style="font-weight:bold; padding-left: 20px; text-align:left;color:#464646;">M: {{_master}}</td>
<td style="font: 9.5pt arial, sans-serif;font-weight: 600;color:#0d1a81;">{{ _cdata[1]['SUB']|safe }} [<span style="align-items: center;justify-content:center;font-size: 8pt;font-weight:600;color:brown;">TS {{ 1 if _cdata[1]['TS'] == True else 2 }}</span>]</td>
<td style="font: 9.5pt arial, sans-serif;font-weight: 600;color:#b5651d;">{{ _cdata[1]['DEST']|safe }}</td>
{% endif %}
{% if _cdata[2]['TRX'] == "RX" %}
<td style="font-weight:bold; padding-left: 20px; text-align:left;color:#464646">M: {{_master}}</td>
<td style="font: 9.5pt arial, sans-serif;font-weight: 600;color:#0d1a81;">{{ _cdata[2]['SUB']|safe }} [<span style="align-items: center;justify-content:center;font-size: 8pt;font-weight:600;color:brown;">TS {{ 1 if _cdata[1]['TS'] == True else 2 }}</span>]</td>
<td style="font: 9.5pt arial, sans-serif;font-weight: 600;color:#b5651d;">{{ _cdata[2]['DEST']|safe }}</td>
{% endif %}
</tr>
{% endif %}
{% endfor %}
{% endfor %}
{% else %}
<table style='width:100%; font: 13pt arial, sans-serif; margin-top:4px;margin-bottom:4px;'>
<tr style='border:none; background-color:#f9f9f9f9;'>
<td style='border:none;height:60px;'><font color=brown><b><center>Waiting for data from the DMR server ...</center></b></td>
</tr>
</table>
{% endif %}
{% for _peer, _pdata in _table['PEERS'].items() %}
{% if _pdata[1]['TS'] == True or _pdata[2]['TS'] == True %}
<tr style="background-color:#f9f9f9f9;line-height:1.4;">
{% if _pdata[1]['TRX'] == "RX" %}
<td style="font-weight:bold; padding-left: 20px; text-align:left;color:#464646;">P: {{_peer}} </td>
<td style="font: 9.5pt arial, sans-serif;font-weight: 600;color:#0d1a81;">{{ _pdata[1]['SUB']|safe }} [<span style="align-items: center;justify-content:center;font-size: 8pt;font-weight:600;color:brown;">TS {{ 1 if _pdata[1]['TS'] == True else 2 }}</span>]</td>
<td style="font: 9.5pt arial, sans-serif;font-weight: 600;color:#b5651d;">{{ _pdata[1]['DEST']|safe }}</td>
{% endif %}
{% if _pdata[2]['TRX'] == "RX" %}
<td style="font-weight:bold; padding-left: 20px; text-align:left;color:#464646;">P: {{_peer}} </td>
<td style="font: 9.5pt arial, sans-serif;font-weight: 600;color:#0d1a81;">{{ _pdata[2]['SUB']|safe }} [<span style="align-items: center;justify-content:center;font-size: 8pt;font-weight:600;color:brown;">TS {{ 1 if _pdata[1]['TS'] == True else 2 }}</span>]</td>
<td style="font: 9.5pt arial, sans-serif;font-weight: 600;color:#b5651d;">{{ _pdata[2]['DEST']|safe }}</td>
{% endif %}
</tr>
{% endif %}
{% endfor %}
<tr style="background-color:#f9f9f9;" height="2px"><td colspan=3><hr style="padding:0px; margin:0px;border:none;color:#f9f9f9;background-color:#f9f9f9;"></td></tr>
{% if _table['OPENBRIDGES']|length >0 %}
<tr style="height:30px;width:100%; font: 10pt arial, sans-serif;{{ themec }}">
<th style='width: 20%;'>Systems OpenBridge</th>
<th colspan=2 style='width: 80%;'>Active Incoming Calls</th>
</tr>
{% for _openbridge in _table['OPENBRIDGES'] %}
{% set rx = namespace(value=0) %}
{% if _table['OPENBRIDGES'][_openbridge]['STREAMS']|length >0 %}
{% for entry in _table['OPENBRIDGES'][_openbridge]['STREAMS'] if _table['OPENBRIDGES'][_openbridge]['STREAMS'][entry][0]=='RX' %}
{% set rx.value=1 %}
{% endfor %}
{% if rx.value == 1 %}
<tr style="background-color:#f9f9f9f9;line-height:1.6;">
<td style="font-weight:bold; padding-left: 20px; text-align:left;"> {{ _openbridge}} </td>
<td colspan=2 style="background-color:#f9f9f9f9; font: 9pt arial, sans-serif; font-weight: 600; color:#464646;">
{% for entry in _table['OPENBRIDGES'][_openbridge]['STREAMS'] if _table['OPENBRIDGES'][_openbridge]['STREAMS'][entry][0] == 'RX' %}[<span style="color:#008000;">{{ _table['OPENBRIDGES'][_openbridge]['STREAMS'][entry][0] }}</span>: <font color=#0065ff> {{ _table['OPENBRIDGES'][_openbridge]['STREAMS'][entry][1] }}</font> >> <font color=#b5651d> {{ _table['OPENBRIDGES'][_openbridge]['STREAMS'][entry][2] }}</font>]&nbsp; {% endfor %}
</td>
</tr>
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
</table>
</fieldset>
{% if _table['SETUP']['LASTHEARD'] == True %}
{% include 'lastheard.html' ignore missing %}
{% endif %}
<fieldset style="background-color:#f0f0f0f0;margin-left:15px;margin-right:15px;font-size:14px;border-top-left-radius: 10px; border-top-right-radius: 10px;border-bottom-left-radius: 10px; border-bottom-right-radius: 10px;"> <fieldset style="background-color:#f0f0f0f0;margin-left:15px;margin-right:15px;font-size:14px;border-top-left-radius: 10px; border-top-right-radius: 10px;border-bottom-left-radius: 10px; border-bottom-right-radius: 10px;">
<legend><b><font color="#000">&nbsp;.: Connected to DMR Server :.&nbsp;</font></b></legend> <legend><b><font color="#000">&nbsp;.: Connected to DMR Server :.&nbsp;</font></b></legend>
{% if _table['MASTERS']|length >0 %}
<table style="table-layout:fixed;width:100%; font: 10pt arial, sans-serif;font-weight:600;margin-top:5px;margin-bottom:5px;" width=100%> <table style="table-layout:fixed;width:100%; font: 10pt arial, sans-serif;font-weight:600;margin-top:5px;margin-bottom:5px;" width=100%>
{% if _table['MASTERS']|length >0 %} {% if _table['MASTERS']|length >0 %}
<tr style="background-color:#f9f9f9f9;"><td> <tr style="background-color:#f9f9f9f9;"><td>
@ -128,6 +53,12 @@
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
<br> <br></td></tr></table>
</td></tr></table> {% else %}
<table style='width:100%; font: 13pt arial, sans-serif; margin-top:4px;margin-bottom:5px;'>
<tr style='border:none; background-color:#f9f9f9f9;'>
<td style='border:none;height:60px;'><font color=brown><b><center>Waiting for data from the DMR server ...</center></b></td>
</tr>
</table>
{% endif %}
</fieldset> </fieldset>