Module: Peak

Defined in:
lib/peak.rb,
lib/peak/echo.rb,
lib/peak/app_info.rb,
lib/peak/tnc_port.rb,
lib/peak/plugins/id.rb,
lib/peak/config_loader.rb,
lib/peak/plugin_loader.rb,
lib/peak/routing/route.rb,
lib/peak/plugins/beacon.rb,
lib/peak/plugins/status.rb,
lib/peak/plugins/apex_paradigm.rb,
lib/peak/plugins/plugin_factory.rb

Defined Under Namespace

Modules: Plugins, Routing Classes: TncPort

Constant Summary collapse

VERSION =
"1.0.3"
BUILTIN_PLUGINS =
%w(peak/plugins/apex_paradigm peak/plugins/beacon peak/plugins/id peak/plugins/status)

Class Method Summary collapse

Class Method Details

.all_plugins(extra_plugins = []) ⇒ Object



6
7
8
# File 'lib/peak/plugin_loader.rb', line 6

def self.all_plugins(extra_plugins=[])
    return BUILTIN_PLUGINS + extra_plugins
end

.config_lookup_enforce(config_map, key) ⇒ Object



28
29
30
31
32
33
34
# File 'lib/peak/config_loader.rb', line 28

def self.config_lookup_enforce(config_map, key)
    unless config_map.key?(key)
        echo_colorized_error('Invalid configuration, could not find an ' + key + ' attribute in section')
        return false
    end
    return true
end

.echo_color_frame(frame, port_name, direction_in) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/peak/echo.rb', line 4

def self.echo_color_frame(frame, port_name, direction_in)
    formatted_aprs = [frame[:source].colorize(:green), frame[:destination].colorize(:blue)].join('>')
    paths = []
    frame[:path].each do |path|
        paths << path.colorize(:cyan)
    end
    paths = paths.join(',')
    if frame[:path] and frame[:path].length > 0
        formatted_aprs = [formatted_aprs, paths].join(',')
    end
    formatted_aprs += ':'
    formatted_aprs += frame[:text]
    if direction_in
        puts (port_name + ' << ').colorize(:magenta) + formatted_aprs
    else
        # TODO : make this bold and/or blink
        puts (port_name + ' >> ').colorize(:color => :magenta, :mode => :bold) + formatted_aprs
    end
end

.echo_colorized_error(text) ⇒ Object



24
25
26
# File 'lib/peak/echo.rb', line 24

def self.echo_colorized_error(text)
    puts 'Error: '.colorize(:color => :red, :mode => [:bold, :blink]) + text.colorize(:bold)
end

.echo_colorized_warning(text) ⇒ Object



28
29
30
# File 'lib/peak/echo.rb', line 28

def self.echo_colorized_warning(text)
    puts 'Warning: '.colorize(:color => :yellow) + text
end

.find_config(verbose, config_paths = []) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/peak/config_loader.rb', line 7

def self.find_config(verbose, config_paths=[])
    config_file = 'peak.conf'
    rc_file = '.peakrc'
    cur_path = config_file
    home_path = File.join(Dir.home, rc_file)
    etc_path = File.join('', 'etc', config_file)
    config_paths = [cur_path, home_path, etc_path] + config_paths
    
    if verbose
        puts 'Searching for configuration file in the following locations: ' + config_paths.inspect
    end
    
    config_paths.each do |config_path|
        if File.file?(config_path)
            return YAML::load_file(config_path)
        end
    end
    
    return nil
end

.init_port_map(config) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/peak/config_loader.rb', line 36

def self.init_port_map(config)
    port_map = {}
    
    config.each do |section_name, section_content|
        if section_name.start_with?('TNC ')
            tnc_name = section_name.strip.split(' ')[1].strip
            if tnc_name == 'IGATE'
                echo_colorized_error('IGATE was used as the name for a TNC in the configuration, this name is reserved')
                return nil
            end
        
            kiss_tnc = nil
            if config_lookup_enforce(section_content, 'com_port') and config_lookup_enforce(section_content, 'baud')
                com_port = section_content['com_port']
                baud = section_content['baud']
                kiss_tnc = Apex::AprsKiss.new(Kiss::KissSerial.new(com_port, baud))
            else
                return nil
            end
            
            if section_content.key?('kiss_init')
                kiss_init_string = section_content['kiss_init']
                if kiss_init_string == 'MODE_INIT_W8DED'
                    kiss_tnc.connect(Kiss::MODE_INIT_W8DED)
                elsif kiss_init_string == 'MODE_INIT_KENWOOD_D710'
                    kiss_tnc.connect(Kiss::MODE_INIT_KENWOOD_D710)
                elsif kiss_init_string == 'NONE'
                    kiss_tnc.connect
                else
                    echo_colorized_error('Invalid configuration, value assigned to kiss_init was not recognized: ' + kiss_init_string)
                    return nil
                end
            else
                kiss_tnc.connect
            end

            unless config_lookup_enforce(section_content, 'port_count')
                return nil
            end
            
            port_count = section_content['port_count']
            
            (1..port_count).each do |port|
                port_name = tnc_name + '-' + port.to_s
                port_section_name = 'PORT ' + port_name
                
                unless config_lookup_enforce(config, port_section_name)
                    return nil
                end
                port_section = config[port_section_name]
                
                unless config_lookup_enforce(port_section, 'identifier')
                    return nil
                end
                port_identifier = port_section['identifier']

                unless config_lookup_enforce(port_section, 'net')
                    return nil
                end
                port_net = port_section['net']

                unless config_lookup_enforce(port_section, 'tnc_port')
                    return nil
                end
                tnc_port = port_section['tnc_port']
                
                unless config_lookup_enforce(port_section, 'echo')
                    return nil
                end
                echo_state = port_section['echo']
                
                port_map[port_name] = TncPort.new(kiss_tnc, port_name, port_identifier, port_net, echo_state, tnc_port)
            end
        end
    end
    
    return port_map
end

.load_plugins(plugins = BUILTIN_PLUGINS) ⇒ Object



10
11
12
13
14
15
# File 'lib/peak/plugin_loader.rb', line 10

def self.load_plugins(plugins=BUILTIN_PLUGINS)
    plugins.each do |plugin|
        require plugin
    end
    return Plugins::PluginFactory.get_registered_plugins
end

.mainObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/peak.rb', line 8

def self.main
    config = find_config(true)
    unless config
        echo_colorized_error('Could not find a valid configuration file in any of the default locations')
        return
    end

    port_map = init_port_map(config)
    unless port_map
        echo_colorized_error('Configuration could not be loaded,  format was invalid.')
        return
    end

    Signal.trap('INT') { throw :sig }
    Signal.trap('TERM') { throw :sig }
    
    active_plugins = {}
    plugins = load_plugins
    plugins.each do |plugin|
        active_plugin = plugin.new(config, port_map, nil)
        active_plugin_thread = Thread.new {
            active_plugin.run
        }
        active_plugins[active_plugin] = active_plugin_thread
    end

    # Handle any packets we read in.
    catch (:sig) do
        while true
            something_read = false
            port_map.values.each do |tnc_port|
                frame = tnc_port.read
                if frame
                    something_read = true
                    routed_frame = Routing::Route.handle_frame(frame, config, true, tnc_port.name)
                    if routed_frame
                        if routed_frame[:output_target]
                            port_map[routed_frame[:output_target]].write(routed_frame[:frame])
                        else
                            active_plugins.each_key do |plugin|
                                plugin.handle_packet(routed_frame[:frame], tnc_port)
                            end
                        end
                    end
                end
            end
            unless something_read
                sleep(1)
            end
        end
    end

    puts
    puts 'Shutdown signal caught, shutting down...'

    # Let's cleanup some stuff before exiting.
    active_plugins.keys.each do |plugin|
        plugin.stop
    end
    active_plugins.values.each do |plugin_thread|
        plugin_thread.join
    end
    port_map.values.each do |port|
        port.close
    end
    
    puts 'Peak successfully shutdown.'
end