Completed
Pull Request — master (#2)
by Jeffrey
04:10
created

main()   F

Complexity

Conditions 23

Size

Total Lines 91

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 91
rs 2
cc 23

1 Method

Rating   Name   Duplication   Size   Complexity  
A sigint_handler() 0 4 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like main() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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