| 1 |  |  | """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | Module that contains the command line app. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  | Why does this file exist, and why not put this in __main__? | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |   You might be tempted to import things from __main__ later, but that will cause | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |   problems: the code will get executed twice: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |   - When you run `python -mapex` python will execute | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  |     ``__main__.py`` as a script. That means there won't be any | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |     ``apex.__main__`` in ``sys.modules``. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |   - When you import __main__ it will get executed again (as a module) because | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |     there's no ``apex.__main__`` in ``sys.modules``. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |   Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | """ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | # These imports are for python3 compatability inside python2 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | from __future__ import absolute_import | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | from __future__ import division | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | from __future__ import print_function | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | from __future__ import unicode_literals | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | import signal | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | import sys | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | import threading | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | import time | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | import traceback | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | import cachetools | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | import click | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  | import apex.aprs | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  | from apex.kiss import constants as kissConstants | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | from apex.pluginloader import getPlugins | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  | from apex.pluginloader import loadPlugin | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  | if sys.version_info < (3, 0): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |     import ConfigParser  # noqa: F401 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  | elif sys.version_info >= (3, 0): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     import configparser | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  | __author__ = 'Jeffrey Phillips Freeman (WI2ARD)' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  | __maintainer__ = "Jeffrey Phillips Freeman (WI2ARD)" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  | __email__ = "[email protected]" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  | __license__ = 'Apache License, Version 2.0' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  | __copyright__ = 'Copyright 2016, Syncleus, Inc. and contributors' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  | __credits__ = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  | @click.command() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  | @click.argument('names', nargs=-1) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  | def main(names): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |     click.echo(repr(names)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |     port_map = {} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |     config = configparser.ConfigParser() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |     config.read('apex.cfg') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |     for section in config.sections(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |         if section.startswith("TNC "): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |             tnc_name = section.split(" ")[1] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |             if config.has_option(section, 'com_port') and config.has_option(section, 'baud'): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |                 com_port = config.get(section, 'com_port') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |                 baud = config.get(section, 'baud') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |                 kiss_tnc = apex.aprs.AprsKiss(com_port=com_port, baud=baud) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |             elif config.has_option(section, 'tcp_host') and config.has_option(section, 'tcp_port'): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |                 tcp_host = config.get(section, 'tcp_host') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |                 tcp_port = config.get(section, 'tcp_port') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |                 kiss_tnc = apex.aprs.AprsKiss(host=tcp_host, tcp_port=tcp_port) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |             else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |                 raise Exception( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |                     "Must have either both com_port and baud set or tcp_host and tcp_port set in configuration file") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |             kiss_init_string = config.get(section, 'kiss_init') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |             if kiss_init_string == 'MODE_INIT_W8DED': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |                 kiss_tnc.start(kissConstants.MODE_INIT_W8DED) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |             elif kiss_init_string == 'MODE_INIT_KENWOOD_D710': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |                 kiss_tnc.start(kissConstants.MODE_INIT_KENWOOD_D710) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |             elif kiss_init_string == 'NONE': | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |                 kiss_tnc.start() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |             else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |                 raise Exception("KISS init mode not specified") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |             for port in range(1, 1 + int(config.get(section, 'port_count'))): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |                 port_name = tnc_name + '-' + str(port) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |                 port_section = 'PORT ' + port_name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |                 port_identifier = config.get(port_section, 'identifier') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |                 port_net = config.get(port_section, 'net') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |                 tnc_port = int(config.get(port_section, 'tnc_port')) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |                 port_map[port_name] = {'identifier': port_identifier, 'net': port_net, 'tnc': kiss_tnc, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |                                        'tnc_port': tnc_port} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |     if config.has_section('APRS-IS'): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |         aprsis_callsign = config.get('APRS-IS', 'callsign') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |         if config.has_option('APRS-IS', 'password'): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |             aprsis_password = config.get('APRS-IS', 'password') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |         else: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |             aprsis_password = -1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |         aprsis_server = config.get('APRS-IS', 'server') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |         aprsis_server_port = config.get('APRS-IS', 'server_port') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |         aprsis = apex.aprs.AprsInternetService(aprsis_callsign, aprsis_password) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |         aprsis.connect(aprsis_server, int(aprsis_server_port)) | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 99 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 100 |  |  |     def sigint_handler(signal, frame): | 
            
                                                                        
                            
            
                                    
            
            
                | 101 |  |  |         for port in port_map.values(): | 
            
                                                                        
                            
            
                                    
            
            
                | 102 |  |  |             port['tnc'].close() | 
            
                                                                        
                            
            
                                    
            
            
                | 103 |  |  |         sys.exit(0) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |     signal.signal(signal.SIGINT, sigint_handler) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |     print("Press ctrl + c at any time to exit") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |     packet_cache = cachetools.TTLCache(10000, 5) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |     # start the plugins | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |     plugins = [] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |     try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |         plugin_loaders = getPlugins() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |         for plugin_loader in plugin_loaders: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |             loaded_plugin = loadPlugin(plugin_loader) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |             plugins.append(loaded_plugin) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |             threading.Thread(target=loaded_plugin.start, args=(config, port_map, packet_cache, aprsis)).start() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |     except FileNotFoundError: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |         print("The plugin directory doesnt exist, without plugins this program has nothing to do, so it will exit now.") | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |         return | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |     while 1: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |         something_read = False | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |         try: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |             for port_name in port_map.keys(): | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |                 port = port_map[port_name] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |                 frame = port['tnc'].read() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |                 if frame: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |                     formatted_aprs = apex.aprs.util.format_aprs_frame(frame) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |                     print(port_name + " << " + formatted_aprs) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |                     for plugin in plugins: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |                         something_read = True | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |                         plugin.handle_packet(frame, port, port_name) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |         except Exception as ex: | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |             # We want to keep this thread alive so long as the application runs. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |             traceback.print_exc(file=sys.stdout) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |             print("caught exception while reading packet: " + str(ex)) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |         if something_read is False: | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 140 |  |  |             time.sleep(1) | 
            
                                                        
            
                                    
            
            
                | 141 |  |  |  |