From 5358e5c5f3265e53ee4a3a28f689f2acee5fc419 Mon Sep 17 00:00:00 2001 From: Waldek Date: Sun, 9 Jun 2019 09:39:36 +0200 Subject: [PATCH] Delete web_tables.py --- web_tables.py | 679 -------------------------------------------------- 1 file changed, 679 deletions(-) delete mode 100755 web_tables.py diff --git a/web_tables.py b/web_tables.py deleted file mode 100755 index 534654a..0000000 --- a/web_tables.py +++ /dev/null @@ -1,679 +0,0 @@ -#!/usr/bin/env python -# -############################################################################### -# Copyright (C) 2016-2019 Cortney T. Buffington, N0MJS -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -############################################################################### - -from __future__ import print_function - -# Standard modules -import logging -import sys - -# Twisted modules -from twisted.internet.protocol import ReconnectingClientFactory, Protocol -from twisted.protocols.basic import NetstringReceiver -from twisted.internet import reactor, task -from twisted.web.server import Site -#from twisted.web.static import File -from twisted.web.resource import Resource - -# Autobahn provides websocket service under Twisted -from autobahn.twisted.websocket import WebSocketServerProtocol, WebSocketServerFactory - -# Specific functions to import from standard modules -#from pprint import pprint -from time import time, strftime, localtime -from cPickle import loads -from binascii import b2a_hex as h -from os.path import getmtime -from collections import deque -from time import time - -# Web templating environment -from jinja2 import Environment, PackageLoader, select_autoescape - -# Utilities from K0USY Group sister project -from dmr_utils.utils import int_id, get_alias, try_download, mk_full_id_dict, hex_str_4 - -# Configuration variables and constants -from config import * - -# Opcodes for reporting protocol to HBlink -OPCODE = { - 'CONFIG_REQ': '\x00', - 'CONFIG_SND': '\x01', - 'BRIDGE_REQ': '\x02', - 'BRIDGE_SND': '\x03', - 'CONFIG_UPD': '\x04', - 'BRIDGE_UPD': '\x05', - 'LINK_EVENT': '\x06', - 'BRDG_EVENT': '\x07', - } - -# Global Variables: -CONFIG = {} -CTABLE = {'MASTERS': {}, 'PEERS': {}, 'OPENBRIDGES': {}} -BRIDGES = {} -BTABLE = {} -BTABLE['BRIDGES'] = {} -BRIDGES_RX = '' -CONFIG_RX = '' -LOGBUF = deque(100*[''], 100) -RED = 'ff0000' -BLACK = '000000' -GREEN = '00ff00' -BLUE = '0000ff' -ORANGE = 'ff8000' -WHITE = 'ffffff' - - -# For importing HTML templates -def get_template(_file): - with open(_file, 'r') as html: - return html.read() - -# Alias string processor -def alias_string(_id, _dict): - alias = get_alias(_id, _dict, 'CALLSIGN', 'CITY', 'STATE') - if type(alias) == list: - for x,item in enumerate(alias): - if item == None: - alias.pop(x) - return ', '.join(alias) - else: - return alias - -def alias_short(_id, _dict): - alias = get_alias(_id, _dict, 'CALLSIGN', 'NAME') - if type(alias) == list: - for x,item in enumerate(alias): - if item == None: - alias.pop(x) - return ', '.join(alias) - else: - return str(alias) - -def alias_call(_id, _dict): - alias = get_alias(_id, _dict, 'CALLSIGN') - if type(alias) == list: - for x,item in enumerate(alias): - if item == None: - alias.pop(x) - return ', '.join(alias) - else: - return str(alias) - -# Return friendly elpasted time from time in seconds. -def since(_time): - now = int(time()) - _time = now - int(_time) - seconds = _time % 60 - minutes = (_time/60) % 60 - hours = (_time/60/60) % 24 - days = (_time/60/60/24) - if days: - return '{}d {}h'.format(days, hours) - elif hours: - return '{}h {}m'.format(hours, minutes) - elif minutes: - return '{}m {}s'.format(minutes, seconds) - else: - return '{}s'.format(seconds) - - -def add_hb_peer(_peer_conf, _ctable_loc, _peer): - _ctable_loc[int_id(_peer)] = {} - _ctable_peer = _ctable_loc[int_id(_peer)] - - # if the Frequency is 000.xxx assume it's not an RF peer, otherwise format the text fields - if _peer_conf['TX_FREQ'][:3] == '000' or _peer_conf['RX_FREQ'][:3] == '000': - _ctable_peer['TX_FREQ'] = 'N/A' - _ctable_peer['RX_FREQ'] = '' - else: - _ctable_peer['TX_FREQ'] = 'TX: ' + _peer_conf['TX_FREQ'][:3] + '.' + _peer_conf['TX_FREQ'][3:7] - _ctable_peer['RX_FREQ'] = 'RX: ' + _peer_conf['RX_FREQ'][:3] + '.' + _peer_conf['RX_FREQ'][3:7] - - # timeslots are kinda complicated too. 0 = none, 1 or 2 mean that one slot, 3 is both, and anythign else it considered DMO - if (_peer_conf['SLOTS'] == '0'): - _ctable_peer['SLOTS'] = 'NONE' - elif (_peer_conf['SLOTS'] <= '2'): - _ctable_peer['SLOTS'] = _peer_conf['SLOTS'] - elif (_peer_conf['SLOTS'] == '3'): - _ctable_peer['SLOTS'] = 'BOTH' - else: - _ctable_peer['SLOTS'] = 'DMO' - - # Simple translation items - _ctable_peer['COLORCODE'] = _peer_conf['COLORCODE'] - _ctable_peer['CALLSIGN'] = _peer_conf['CALLSIGN'] - _ctable_peer['LOCATION'] = _peer_conf['LOCATION'] - _ctable_peer['CONNECTION'] = _peer_conf['CONNECTION'] - _ctable_peer['CONNECTED'] = since(_peer_conf['CONNECTED']) - _ctable_peer['IP'] = _peer_conf['IP'] - _ctable_peer['PORT'] = _peer_conf['PORT'] - #_ctable_peer['LAST_PING'] = _peer_conf['LAST_PING'] - - # SLOT 1&2 - for real-time montior: make the structure for later use - for ts in range(1,3): - _ctable_peer[ts]= {} - _ctable_peer[ts]['COLOR'] = '' - _ctable_peer[ts]['BGCOLOR'] = '' - _ctable_peer[ts]['TS'] = '' - _ctable_peer[ts]['TYPE'] = '' - _ctable_peer[ts]['SUB'] = '' - _ctable_peer[ts]['SRC'] = '' - _ctable_peer[ts]['DEST'] = '' - - -# Build the HBlink connections table -def build_hblink_table(_config, _stats_table): - for _hbp, _hbp_data in _config.iteritems(): - if _hbp_data['ENABLED'] == True: - - # Process Master Systems - if _hbp_data['MODE'] == 'MASTER': - _stats_table['MASTERS'][_hbp] = {} - if _hbp_data['REPEAT']: - _stats_table['MASTERS'][_hbp]['REPEAT'] = "repeat" - else: - _stats_table['MASTERS'][_hbp]['REPEAT'] = "isolate" - _stats_table['MASTERS'][_hbp]['PEERS'] = {} - for _peer in _hbp_data['PEERS']: - add_hb_peer(_hbp_data['PEERS'][_peer], _stats_table['MASTERS'][_hbp]['PEERS'], _peer) - - # Proccess Peer Systems - elif _hbp_data['MODE'] == 'PEER': - _stats_table['PEERS'][_hbp] = {} - _stats_table['PEERS'][_hbp]['CALLSIGN'] = _hbp_data['CALLSIGN'] - _stats_table['PEERS'][_hbp]['LOCATION'] = _hbp_data['LOCATION'] - _stats_table['PEERS'][_hbp]['RADIO_ID'] = int_id(_hbp_data['RADIO_ID']) - _stats_table['PEERS'][_hbp]['MASTER_IP'] = _hbp_data['MASTER_IP'] - _stats_table['PEERS'][_hbp]['MASTER_PORT'] = _hbp_data['MASTER_PORT'] - _stats_table['PEERS'][_hbp]['STATS'] = {} - _stats_table['PEERS'][_hbp]['STATS']['CONNECTION'] = _hbp_data['STATS']['CONNECTION'] - _stats_table['PEERS'][_hbp]['STATS']['CONNECTED'] = since(_hbp_data['STATS']['CONNECTED']) - _stats_table['PEERS'][_hbp]['STATS']['PINGS_SENT'] = _hbp_data['STATS']['PINGS_SENT'] - _stats_table['PEERS'][_hbp]['STATS']['PINGS_ACKD'] = _hbp_data['STATS']['PINGS_ACKD'] - if _hbp_data['SLOTS'] == 0: - _stats_table['PEERS'][_hbp]['SLOTS'] = 'NONE' - elif _hbp_data['SLOTS'] <= '2': - _stats_table['PEERS'][_hbp]['SLOTS'] = _hbp_data['SLOTS'] - elif _hbp_data['SLOTS'] == '3': - _stats_table['PEERS'][_hbp]['SLOTS'] = 'BOTH' - else: - _stats_table['SLOTS'][_hbp]['SLOTS'] = 'DMO' - # SLOT 1&2 - for real-time montior: make the structure for later use - - for ts in range(1,3): - _stats_table['PEERS'][_hbp][ts]= {} - _stats_table['PEERS'][_hbp][ts]['COLOR'] = '' - _stats_table['PEERS'][_hbp][ts]['BGCOLOR'] = '' - _stats_table['PEERS'][_hbp][ts]['TS'] = '' - _stats_table['PEERS'][_hbp][ts]['TYPE'] = '' - _stats_table['PEERS'][_hbp][ts]['SUB'] = '' - _stats_table['PEERS'][_hbp][ts]['SRC'] = '' - _stats_table['PEERS'][_hbp][ts]['DEST'] = '' - - - # Process OpenBridge systems - elif _hbp_data['MODE'] == 'OPENBRIDGE': - _stats_table['OPENBRIDGES'][_hbp] = {} - _stats_table['OPENBRIDGES'][_hbp]['NETWORK_ID'] = int_id(_hbp_data['NETWORK_ID']) - _stats_table['OPENBRIDGES'][_hbp]['TARGET_IP'] = _hbp_data['TARGET_IP'] - _stats_table['OPENBRIDGES'][_hbp]['TARGET_PORT'] = _hbp_data['TARGET_PORT'] - _stats_table['OPENBRIDGES'][_hbp]['STREAMS'] = {} - - #return(_stats_table) - -def update_hblink_table(_config, _stats_table): - # Is there a system in HBlink's config monitor doesn't know about? - for _hbp in _config: - if _config[_hbp]['MODE'] == 'MASTER': - for _peer in _config[_hbp]['PEERS']: - if int_id(_peer) not in _stats_table['MASTERS'][_hbp]['PEERS'] and _config[_hbp]['PEERS'][_peer]['CONNECTION'] == 'YES': - logger.info('Adding peer to CTABLE that has registerred: %s', int_id(_peer)) - add_hb_peer(_config[_hbp]['PEERS'][_peer], _stats_table['MASTERS'][_hbp]['PEERS'], _peer) - - # Is there a system in monitor that's been removed from HBlink's config? - for _hbp in _stats_table['MASTERS']: - remove_list = [] - if _config[_hbp]['MODE'] == 'MASTER': - for _peer in _stats_table['MASTERS'][_hbp]['PEERS']: - if hex_str_4(_peer) not in _config[_hbp]['PEERS']: - remove_list.append(_peer) - - for _peer in remove_list: - logger.info('Deleting stats peer not in hblink config: %s', _peer) - del (_stats_table['MASTERS'][_hbp]['PEERS'][_peer]) - - # Update connection time - for _hbp in _stats_table['MASTERS']: - for _peer in _stats_table['MASTERS'][_hbp]['PEERS']: - if hex_str_4(_peer) in _config[_hbp]['PEERS']: - _stats_table['MASTERS'][_hbp]['PEERS'][_peer]['CONNECTED'] = since(_config[_hbp]['PEERS'][hex_str_4(_peer)]['CONNECTED']) - - for _hbp in _stats_table['PEERS']: - _stats_table['PEERS'][_hbp]['STATS']['CONNECTED'] = since(_config[_hbp]['STATS']['CONNECTED']) - _stats_table['PEERS'][_hbp]['STATS']['PINGS_SENT'] = _config[_hbp]['STATS']['PINGS_SENT'] - _stats_table['PEERS'][_hbp]['STATS']['PINGS_ACKD'] = _config[_hbp]['STATS']['PINGS_ACKD'] - - build_stats() - -# -# CONFBRIDGE TABLE FUNCTIONS -# -def build_bridge_table(_bridges): - _stats_table = {} - _now = time() - _cnow = strftime('%Y-%m-%d %H:%M:%S', localtime(_now)) - - for _bridge, _bridge_data in _bridges.iteritems(): - _stats_table[_bridge] = {} - - for system in _bridges[_bridge]: - _stats_table[_bridge][system['SYSTEM']] = {} - _stats_table[_bridge][system['SYSTEM']]['TS'] = system['TS'] - _stats_table[_bridge][system['SYSTEM']]['TGID'] = int_id(system['TGID']) - - if system['TO_TYPE'] == 'ON' or system['TO_TYPE'] == 'OFF': - if system['TIMER'] - _now > 0: - _stats_table[_bridge][system['SYSTEM']]['EXP_TIME'] = int(system['TIMER'] - _now) - else: - _stats_table[_bridge][system['SYSTEM']]['EXP_TIME'] = 'Expired' - if system['TO_TYPE'] == 'ON': - _stats_table[_bridge][system['SYSTEM']]['TO_ACTION'] = 'Disconnect' - else: - _stats_table[_bridge][system['SYSTEM']]['TO_ACTION'] = 'Connect' - else: - _stats_table[_bridge][system['SYSTEM']]['EXP_TIME'] = 'N/A' - _stats_table[_bridge][system['SYSTEM']]['TO_ACTION'] = 'None' - - if system['ACTIVE'] == True: - _stats_table[_bridge][system['SYSTEM']]['ACTIVE'] = 'Connected' - _stats_table[_bridge][system['SYSTEM']]['COLOR'] = BLACK - _stats_table[_bridge][system['SYSTEM']]['BGCOLOR'] = GREEN - elif system['ACTIVE'] == False: - _stats_table[_bridge][system['SYSTEM']]['ACTIVE'] = 'Disconnected' - _stats_table[_bridge][system['SYSTEM']]['COLOR'] = WHITE - _stats_table[_bridge][system['SYSTEM']]['BGCOLOR'] = RED - - for i in range(len(system['ON'])): - system['ON'][i] = str(int_id(system['ON'][i])) - - _stats_table[_bridge][system['SYSTEM']]['TRIG_ON'] = ', '.join(system['ON']) - - for i in range(len(system['OFF'])): - system['OFF'][i] = str(int_id(system['OFF'][i])) - - _stats_table[_bridge][system['SYSTEM']]['TRIG_OFF'] = ', '.join(system['OFF']) - return _stats_table - -# -# BUILD HBlink AND CONFBRIDGE TABLES FROM CONFIG/BRIDGES DICTS -# THIS CURRENTLY IS A TIMED CALL -# -build_time = time() -def build_stats(): - global build_time - now = time() - if True: #now > build_time + 1: - if CONFIG: - table = 'd' + dtemplate.render(_table=CTABLE) - dashboard_server.broadcast(table) - if BRIDGES: - table = 'b' + btemplate.render(_table=BTABLE['BRIDGES']) - dashboard_server.broadcast(table) - build_time = now - - -def timeout_clients(): - now = time() - try: - for client in dashboard_server.clients: - if dashboard_server.clients[client] + CLIENT_TIMEOUT < now: - logger.info('TIMEOUT: disconnecting client %s', dashboard_server.clients[client]) - try: - dashboard.sendClose(client) - except Exception as e: - logger.error('Exception caught parsing client timeout %s', e) - except: - logger.info('CLIENT TIMEOUT: List does not exist, skipping. If this message persists, contact the developer') - - -def rts_update(p): - callType = p[0] - action = p[1] - trx = p[2] - system = p[3] - streamId = p[4] - sourcePeer = int(p[5]) - sourceSub = int(p[6]) - timeSlot = int(p[7]) - destination = int(p[8]) - - if system in CTABLE['MASTERS']: - for peer in CTABLE['MASTERS'][system]['PEERS']: - if sourcePeer == peer: - bgcolor = GREEN - color = BLACK - else: - bgcolor = RED - color = WHITE - - if action == 'START': - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['TS'] = True - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['COLOR'] = color - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['BGCOLOR'] = bgcolor - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['TYPE'] = callType - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['SUB'] = '{} ({})'.format(alias_short(sourceSub, subscriber_ids), sourceSub) - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['SRC'] = peer - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['DEST'] = destination - if action == 'END': - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['TS'] = False - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['COLOR'] = BLACK - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['BGCOLOR'] = WHITE - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['TYPE'] = '' - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['SUB'] = '' - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['SRC'] = '' - CTABLE['MASTERS'][system]['PEERS'][peer][timeSlot]['DEST'] = '' - - if system in CTABLE['OPENBRIDGES']: - if action == 'START': - CTABLE['OPENBRIDGES'][system]['STREAMS'][streamId] = (trx, alias_call(sourceSub, subscriber_ids), destination) - if action == 'END': - if streamId in CTABLE['OPENBRIDGES'][system]['STREAMS']: - del CTABLE['OPENBRIDGES'][system]['STREAMS'][streamId] - - if system in CTABLE['PEERS']: - bgcolor = GREEN - if trx == 'RX': - bgcolor = GREEN - color = BLACK - else: - bgcolor = RED - color = WHITE - - if action == 'START': - CTABLE['PEERS'][system][timeSlot]['TS'] = True - CTABLE['PEERS'][system][timeSlot]['COLOR'] = color - CTABLE['PEERS'][system][timeSlot]['BGCOLOR'] = bgcolor - CTABLE['PEERS'][system][timeSlot]['TYPE'] = callType - CTABLE['PEERS'][system][timeSlot]['SUB'] = '{} ({})'.format(alias_short(sourceSub, subscriber_ids), sourceSub) - CTABLE['PEERS'][system][timeSlot]['SRC'] = sourcePeer - CTABLE['PEERS'][system][timeSlot]['DEST'] = destination - if action == 'END': - CTABLE['PEERS'][system][timeSlot]['TS'] = False - CTABLE['PEERS'][system][timeSlot]['COLOR'] = BLACK - CTABLE['PEERS'][system][timeSlot]['BGCOLOR'] = WHITE - CTABLE['PEERS'][system][timeSlot]['TYPE'] = '' - CTABLE['PEERS'][system][timeSlot]['SUB'] = '' - CTABLE['PEERS'][system][timeSlot]['SRC'] = '' - CTABLE['PEERS'][system][timeSlot]['DEST'] = '' - - build_stats() - -# -# PROCESS IN COMING MESSAGES AND TAKE THE CORRECT ACTION DEPENING ON THE OPCODE -# -def process_message(_message): - global CTABLE, CONFIG, BRIDGES, CONFIG_RX, BRIDGES_RX - opcode = _message[:1] - _now = strftime('%Y-%m-%d %H:%M:%S %Z', localtime(time())) - - if opcode == OPCODE['CONFIG_SND']: - logging.debug('got CONFIG_SND opcode') - CONFIG = load_dictionary(_message) - CONFIG_RX = strftime('%Y-%m-%d %H:%M:%S', localtime(time())) - if CTABLE['MASTERS']: - update_hblink_table(CONFIG, CTABLE) - else: - build_hblink_table(CONFIG, CTABLE) - - elif opcode == OPCODE['BRIDGE_SND']: - logging.debug('got BRIDGE_SND opcode') - BRIDGES = load_dictionary(_message) - BRIDGES_RX = strftime('%Y-%m-%d %H:%M:%S', localtime(time())) - BTABLE['BRIDGES'] = build_bridge_table(BRIDGES) - - elif opcode == OPCODE['LINK_EVENT']: - logging.info('LINK_EVENT Received: {}'.format(repr(_message[1:]))) - - elif opcode == OPCODE['BRDG_EVENT']: - logging.info('BRIDGE EVENT: {}'.format(repr(_message[1:]))) - p = _message[1:].split(",") - rts_update(p) - if p[0] == 'GROUP VOICE' and p[2] != 'TX': - if p[1] == 'END': - log_message = '{}: {} {}: SYS: {:12.12s} SRC: {:8.8s}; {:15.15s} TS: {} TGID: {:>5s} SUB: {:8.8s}; {:30.30s} Time: {}s'.format(_now, p[0], p[1], p[3], p[5], alias_call(int(p[5]), peer_ids), p[7], p[8], p[6], alias_short(int(p[6]), subscriber_ids), p[9]) - elif p[1] == 'START': - log_message = '{}: {} {}: SYS: {:12.12s} SRC: {:8.8s}; {:15.15s} TS: {} TGID: {:>5s} SUB: {:8.8s}; {:30.30s}'.format(_now, p[0], p[1], p[3], p[5], alias_call(int(p[5]), peer_ids), p[7], p[8], p[6], alias_short(int(p[6]), subscriber_ids)) - elif p[1] == 'END WITHOUT MATCHING START': - log_message = '{}: {} {} on SYSTEM {:12.12s}: SRC: {:8.8s}; {}:15.15s TS: {} TGID: {:>5s} SUB: {:8.8s}; {:30.30s}'.format(_now, p[0], p[1], p[3], p[5], alias_call(int(p[5]), peer_ids), p[7], p[8], p[6], alias_short(int(p[6]), subscriber_ids)) - else: - log_message = '{}: UNKNOWN GROUP VOICE LOG MESSAGE'.format(_now) - - dashboard_server.broadcast('l' + log_message) - LOGBUF.append(log_message) - - else: - logging.debug('{}: UNKNOWN LOG MESSAGE'.format(_now)) - - else: - logging.debug('got unknown opcode: {}, message: {}'.format(repr(opcode), repr(_message[1:]))) - -def load_dictionary(_message): - data = _message[1:] - return loads(data) - logging.debug('Successfully decoded dictionary') - -# -# COMMUNICATION WITH THE HBlink INSTANCE -# -class report(NetstringReceiver): - def __init__(self): - pass - - def connectionMade(self): - pass - - def connectionLost(self, reason): - pass - - def stringReceived(self, data): - process_message(data) - - -class reportClientFactory(ReconnectingClientFactory): - def __init__(self): - logging.info('reportClient object for connecting to HBlink.py created at: %s', self) - - def startedConnecting(self, connector): - logging.info('Initiating Connection to Server.') - if 'dashboard_server' in locals() or 'dashboard_server' in globals(): - dashboard_server.broadcast('q' + 'Connection to HBlink Established') - - def buildProtocol(self, addr): - logging.info('Connected.') - logging.info('Resetting reconnection delay') - self.resetDelay() - return report() - - def clientConnectionLost(self, connector, reason): - logging.info('Lost connection. Reason: %s', reason) - ReconnectingClientFactory.clientConnectionLost(self, connector, reason) - dashboard_server.broadcast('q' + 'Connection to HBlink Lost') - - def clientConnectionFailed(self, connector, reason): - logging.info('Connection failed. Reason: %s', reason) - ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) - - -# -# WEBSOCKET COMMUNICATION WITH THE DASHBOARD CLIENT -# -class dashboard(WebSocketServerProtocol): - - def onConnect(self, request): - logging.info('Client connecting: %s', request.peer) - - def onOpen(self): - logging.info('WebSocket connection open.') - self.factory.register(self) - self.sendMessage('d' + str(dtemplate.render(_table=CTABLE))) - self.sendMessage('b' + str(btemplate.render(_table=BTABLE['BRIDGES']))) - for _message in LOGBUF: - if _message: - self.sendMessage('l' + _message) - - def onMessage(self, payload, isBinary): - if isBinary: - logging.info('Binary message received: %s bytes', len(payload)) - else: - logging.info('Text message received: %s', payload.decode('utf8')) - - def connectionLost(self, reason): - WebSocketServerProtocol.connectionLost(self, reason) - self.factory.unregister(self) - - def onClose(self, wasClean, code, reason): - logging.info('WebSocket connection closed: %s', reason) - -class dashboardFactory(WebSocketServerFactory): - - def __init__(self, url): - WebSocketServerFactory.__init__(self, url) - self.clients = {} - - def register(self, client): - if client not in self.clients: - logging.info('registered client %s', client.peer) - self.clients[client] = time() - - def unregister(self, client): - if client in self.clients: - logging.info('unregistered client %s', client.peer) - del self.clients[client] - - def broadcast(self, msg): - logging.debug('broadcasting message to: %s', self.clients) - for c in self.clients: - c.sendMessage(msg.encode('utf8')) - logging.debug('message sent to %s', c.peer) - -# -# STATIC WEBSERVER -# -class web_server(Resource): - isLeaf = True - def render_GET(self, request): - logging.info('static website requested: %s', request) - if request.uri == '/': - return index_html - else: - return 'Bad request' - - - - -if __name__ == '__main__': - logging.basicConfig( - level=logging.INFO, - filename = (LOG_PATH + LOG_NAME), - filemode='a', - format='%(asctime)s %(levelname)s %(message)s', - datefmt='%Y-%m-%d %H:%M:%S' - ) - console = logging.StreamHandler() - console.setLevel(logging.INFO) - formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') - console.setFormatter(formatter) - logging.getLogger('').addHandler(console) - logger = logging.getLogger(__name__) - - logging.info('web_tables.py starting up') - logger.info('\n\nCopyright (c) 2016, 2017, 2018, 2019\n\tThe Regents of the K0USY Group. All rights reserved.\n') - - # Download alias files - result = try_download(PATH, PEER_FILE, PEER_URL, (FILE_RELOAD * 86400)) - logging.info(result) - - result = try_download(PATH, SUBSCRIBER_FILE, SUBSCRIBER_URL, (FILE_RELOAD * 86400)) - logging.info(result) - - # Make Alias Dictionaries - peer_ids = mk_full_id_dict(PATH, PEER_FILE, 'peer') - if peer_ids: - logging.info('ID ALIAS MAPPER: peer_ids dictionary is available') - - subscriber_ids = mk_full_id_dict(PATH, SUBSCRIBER_FILE, 'subscriber') - if subscriber_ids: - logging.info('ID ALIAS MAPPER: subscriber_ids dictionary is available') - - talkgroup_ids = mk_full_id_dict(PATH, TGID_FILE, 'tgid') - if talkgroup_ids: - logging.info('ID ALIAS MAPPER: talkgroup_ids dictionary is available') - - local_subscriber_ids = mk_full_id_dict(PATH, LOCAL_SUB_FILE, 'subscriber') - if local_subscriber_ids: - logging.info('ID ALIAS MAPPER: local_subscriber_ids added to subscriber_ids dictionary') - subscriber_ids.update(local_subscriber_ids) - - local_peer_ids = mk_full_id_dict(PATH, LOCAL_PEER_FILE, 'peer') - if local_peer_ids: - logging.info('ID ALIAS MAPPER: local_peer_ids added peer_ids dictionary') - peer_ids.update(local_peer_ids) - - # Jinja2 Stuff - env = Environment( - loader=PackageLoader('web_tables', 'templates'), - autoescape=select_autoescape(['html', 'xml']) - ) - - dtemplate = env.get_template('hblink_table.html') - btemplate = env.get_template('bridge_table.html') - - # Create Static Website index file - index_html = get_template(PATH + 'index_template.html') - index_html = index_html.replace('<<>>', REPORT_NAME) - if CLIENT_TIMEOUT > 0: - index_html = index_html.replace('<<>>', 'Continuous connections not allowed. Connections time out in {} seconds'.format(CLIENT_TIMEOUT)) - else: - index_html = index_html.replace('<<>>', '') - - # Start update loop - update_stats = task.LoopingCall(build_stats) - update_stats.start(FREQUENCY) - - # Start a timout loop - if CLIENT_TIMEOUT > 0: - timeout = task.LoopingCall(timeout_clients) - timeout.start(10) - - # Connect to HBlink - reactor.connectTCP(HBLINK_IP, HBLINK_PORT, reportClientFactory()) - - # Create websocket server to push content to clients - dashboard_server = dashboardFactory('ws://*:9000') - dashboard_server.protocol = dashboard - reactor.listenTCP(9000, dashboard_server) - - # Create static web server to push initial index.html - website = Site(web_server()) - reactor.listenTCP(WEB_SERVER_PORT, website) - - reactor.run()