rsmp 0.37.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.devcontainer/devcontainer.json +22 -0
- data/.github/workflows/rubocop.yaml +17 -0
- data/.gitignore +5 -6
- data/.rubocop.yml +80 -0
- data/Gemfile +13 -1
- data/Gemfile.lock +34 -1
- data/Rakefile +3 -3
- data/lib/rsmp/cli.rb +147 -124
- data/lib/rsmp/collect/ack_collector.rb +8 -7
- data/lib/rsmp/collect/aggregated_status_collector.rb +4 -4
- data/lib/rsmp/collect/alarm_collector.rb +31 -23
- data/lib/rsmp/collect/alarm_matcher.rb +3 -3
- data/lib/rsmp/collect/collector/logging.rb +17 -0
- data/lib/rsmp/collect/collector/reporting.rb +44 -0
- data/lib/rsmp/collect/collector/status.rb +34 -0
- data/lib/rsmp/collect/collector.rb +69 -150
- data/lib/rsmp/collect/command_matcher.rb +19 -6
- data/lib/rsmp/collect/command_response_collector.rb +7 -7
- data/lib/rsmp/collect/distributor.rb +14 -11
- data/lib/rsmp/collect/filter.rb +31 -15
- data/lib/rsmp/collect/matcher.rb +7 -11
- data/lib/rsmp/collect/queue.rb +4 -4
- data/lib/rsmp/collect/receiver.rb +10 -12
- data/lib/rsmp/collect/state_collector.rb +116 -77
- data/lib/rsmp/collect/status_collector.rb +6 -6
- data/lib/rsmp/collect/status_matcher.rb +17 -7
- data/lib/rsmp/{alarm_state.rb → component/alarm_state.rb} +76 -37
- data/lib/rsmp/{component.rb → component/component.rb} +15 -15
- data/lib/rsmp/component/component_base.rb +89 -0
- data/lib/rsmp/component/component_proxy.rb +75 -0
- data/lib/rsmp/component/components.rb +63 -0
- data/lib/rsmp/convert/export/json_schema.rb +116 -110
- data/lib/rsmp/convert/import/yaml.rb +21 -18
- data/lib/rsmp/{rsmp.rb → helpers/clock.rb} +5 -6
- data/lib/rsmp/{deep_merge.rb → helpers/deep_merge.rb} +2 -1
- data/lib/rsmp/helpers/error.rb +71 -0
- data/lib/rsmp/{inspect.rb → helpers/inspect.rb} +6 -10
- data/lib/rsmp/log/archive.rb +98 -0
- data/lib/rsmp/log/colorization.rb +41 -0
- data/lib/rsmp/log/filtering.rb +54 -0
- data/lib/rsmp/log/logger.rb +206 -0
- data/lib/rsmp/{logging.rb → log/logging.rb} +5 -7
- data/lib/rsmp/message.rb +159 -148
- data/lib/rsmp/{node.rb → node/node.rb} +19 -17
- data/lib/rsmp/{protocol.rb → node/protocol.rb} +5 -3
- data/lib/rsmp/node/site/site.rb +195 -0
- data/lib/rsmp/node/supervisor/modules/configuration.rb +59 -0
- data/lib/rsmp/node/supervisor/modules/connection.rb +140 -0
- data/lib/rsmp/node/supervisor/modules/sites.rb +64 -0
- data/lib/rsmp/node/supervisor/supervisor.rb +72 -0
- data/lib/rsmp/{task.rb → node/task.rb} +12 -14
- data/lib/rsmp/proxy/modules/acknowledgements.rb +144 -0
- data/lib/rsmp/proxy/modules/receive.rb +119 -0
- data/lib/rsmp/proxy/modules/send.rb +76 -0
- data/lib/rsmp/proxy/modules/state.rb +25 -0
- data/lib/rsmp/proxy/modules/tasks.rb +105 -0
- data/lib/rsmp/proxy/modules/versions.rb +69 -0
- data/lib/rsmp/proxy/modules/watchdogs.rb +66 -0
- data/lib/rsmp/proxy/proxy.rb +199 -0
- data/lib/rsmp/proxy/site/modules/aggregated_status.rb +52 -0
- data/lib/rsmp/proxy/site/modules/alarms.rb +27 -0
- data/lib/rsmp/proxy/site/modules/commands.rb +31 -0
- data/lib/rsmp/proxy/site/modules/status.rb +110 -0
- data/lib/rsmp/proxy/site/site_proxy.rb +205 -0
- data/lib/rsmp/proxy/supervisor/modules/aggregated_status.rb +47 -0
- data/lib/rsmp/proxy/supervisor/modules/alarms.rb +73 -0
- data/lib/rsmp/proxy/supervisor/modules/commands.rb +53 -0
- data/lib/rsmp/proxy/supervisor/modules/status.rb +204 -0
- data/lib/rsmp/proxy/supervisor/supervisor_proxy.rb +178 -0
- data/lib/rsmp/tlc/detector_logic.rb +18 -34
- data/lib/rsmp/tlc/input_states.rb +126 -0
- data/lib/rsmp/tlc/modules/detector_logics.rb +50 -0
- data/lib/rsmp/tlc/modules/display.rb +78 -0
- data/lib/rsmp/tlc/modules/helpers.rb +41 -0
- data/lib/rsmp/tlc/modules/inputs.rb +173 -0
- data/lib/rsmp/tlc/modules/modes.rb +253 -0
- data/lib/rsmp/tlc/modules/outputs.rb +30 -0
- data/lib/rsmp/tlc/modules/plans.rb +218 -0
- data/lib/rsmp/tlc/modules/signal_groups.rb +109 -0
- data/lib/rsmp/tlc/modules/startup_sequence.rb +22 -0
- data/lib/rsmp/tlc/modules/system.rb +140 -0
- data/lib/rsmp/tlc/modules/traffic_data.rb +49 -0
- data/lib/rsmp/tlc/signal_group.rb +37 -41
- data/lib/rsmp/tlc/signal_plan.rb +14 -11
- data/lib/rsmp/tlc/signal_priority.rb +39 -35
- data/lib/rsmp/tlc/startup_sequence.rb +59 -0
- data/lib/rsmp/tlc/traffic_controller.rb +38 -1010
- data/lib/rsmp/tlc/traffic_controller_site.rb +58 -57
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +82 -48
- data/rsmp.gemspec +24 -31
- metadata +79 -139
- data/lib/rsmp/archive.rb +0 -76
- data/lib/rsmp/collect/message_matchers.rb +0 -0
- data/lib/rsmp/component_base.rb +0 -87
- data/lib/rsmp/component_proxy.rb +0 -57
- data/lib/rsmp/components.rb +0 -65
- data/lib/rsmp/error.rb +0 -71
- data/lib/rsmp/logger.rb +0 -216
- data/lib/rsmp/proxy.rb +0 -693
- data/lib/rsmp/site.rb +0 -188
- data/lib/rsmp/site_proxy.rb +0 -389
- data/lib/rsmp/supervisor.rb +0 -302
- data/lib/rsmp/supervisor_proxy.rb +0 -510
- data/lib/rsmp/tlc/inputs.rb +0 -134
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Logger
|
|
3
|
+
# Handles filtering logic for log output
|
|
4
|
+
module Filtering
|
|
5
|
+
def level_enabled?(item)
|
|
6
|
+
return false if @settings['info'] == false && item[:level] == :info
|
|
7
|
+
return false if @settings['debug'] != true && item[:level] == :debug
|
|
8
|
+
return false if @settings['statistics'] != true && item[:level] == :statistics
|
|
9
|
+
return false if @settings['test'] != true && item[:level] == :test
|
|
10
|
+
|
|
11
|
+
true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def message_ignored?(item)
|
|
15
|
+
return false unless item[:message]
|
|
16
|
+
|
|
17
|
+
type = item[:message].type
|
|
18
|
+
ack = %w[MessageAck MessageNotAck].include?(type)
|
|
19
|
+
return true unless ignorable?(type, ack, item)
|
|
20
|
+
return true unless acknowledgement_enabled?(ack, item)
|
|
21
|
+
|
|
22
|
+
false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ignorable?(type, ack, item)
|
|
26
|
+
@ignorable.each_pair do |key, types|
|
|
27
|
+
ignore = [types].flatten
|
|
28
|
+
next unless @settings[key] == false
|
|
29
|
+
return false if ignore.include?(type)
|
|
30
|
+
|
|
31
|
+
return false if ack && item[:message].original && ignore.include?(item[:message].original.type)
|
|
32
|
+
end
|
|
33
|
+
true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def acknowledgement_enabled?(ack, item)
|
|
37
|
+
return true unless ack
|
|
38
|
+
return true if @settings['acknowledgements'] != false
|
|
39
|
+
return true if %i[not_acknowledged warning error].include?(item[:level])
|
|
40
|
+
|
|
41
|
+
false
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def output?(item, force: false)
|
|
45
|
+
return false if muted?(item)
|
|
46
|
+
return false if @settings['active'] == false && force != true
|
|
47
|
+
return false unless level_enabled?(item)
|
|
48
|
+
return false if message_ignored?(item)
|
|
49
|
+
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Logger
|
|
3
|
+
include Filtering
|
|
4
|
+
include Colorization
|
|
5
|
+
|
|
6
|
+
attr_accessor :settings
|
|
7
|
+
|
|
8
|
+
def default_output_settings
|
|
9
|
+
{
|
|
10
|
+
'active' => true,
|
|
11
|
+
'path' => nil,
|
|
12
|
+
'stream' => nil,
|
|
13
|
+
'color' => true,
|
|
14
|
+
'debug' => false,
|
|
15
|
+
'statistics' => false,
|
|
16
|
+
'hide_ip_and_port' => false,
|
|
17
|
+
'acknowledgements' => false,
|
|
18
|
+
'watchdogs' => false,
|
|
19
|
+
'alarms' => true,
|
|
20
|
+
'json' => false,
|
|
21
|
+
'tabs' => '-'
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def default_field_settings
|
|
26
|
+
{
|
|
27
|
+
'prefix' => false,
|
|
28
|
+
'index' => false,
|
|
29
|
+
'author' => false,
|
|
30
|
+
'timestamp' => true,
|
|
31
|
+
'ip' => false,
|
|
32
|
+
'port' => false,
|
|
33
|
+
'site_id' => true,
|
|
34
|
+
'component' => true,
|
|
35
|
+
'direction' => false,
|
|
36
|
+
'level' => false,
|
|
37
|
+
'id' => true,
|
|
38
|
+
'text' => true
|
|
39
|
+
}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def default_logger_settings
|
|
43
|
+
default_output_settings.merge(default_field_settings)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def default_field_lengths
|
|
47
|
+
{
|
|
48
|
+
'index' => 7,
|
|
49
|
+
'author' => 13,
|
|
50
|
+
'timestamp' => 24,
|
|
51
|
+
'ip' => 22,
|
|
52
|
+
'port' => 5,
|
|
53
|
+
'site_id' => 19,
|
|
54
|
+
'component' => 19,
|
|
55
|
+
'direction' => 3,
|
|
56
|
+
'level' => 7,
|
|
57
|
+
'id' => 4
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def ignorable_messages
|
|
62
|
+
{
|
|
63
|
+
'versions' => ['Version'],
|
|
64
|
+
'statuses' => %w[StatusRequest StatusSubscribe StatusUnsubscribe StatusResponse StatusUpdate],
|
|
65
|
+
'commands' => %w[CommandRequest CommandResponse],
|
|
66
|
+
'watchdogs' => 'Watchdog',
|
|
67
|
+
'alarms' => ['Alarm'],
|
|
68
|
+
'aggregated_status' => %w[AggregatedStatus AggregatedStatusRequest]
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def apply_default_lengths(settings)
|
|
73
|
+
lengths = default_field_lengths
|
|
74
|
+
settings.to_h do |key, value|
|
|
75
|
+
if value == true && lengths[key]
|
|
76
|
+
[key, lengths[key]]
|
|
77
|
+
else
|
|
78
|
+
[key, value]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def initialize(settings = {})
|
|
84
|
+
@ignorable = ignorable_messages
|
|
85
|
+
@settings = settings ? default_logger_settings.merge(settings) : default_logger_settings
|
|
86
|
+
@settings = apply_default_lengths(@settings)
|
|
87
|
+
@muted = {}
|
|
88
|
+
setup_output_destination
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def setup_output_destination
|
|
92
|
+
@stream = if @settings['stream']
|
|
93
|
+
@settings['stream']
|
|
94
|
+
elsif @settings['path']
|
|
95
|
+
File.open(@settings['path'], 'a') # appending
|
|
96
|
+
else
|
|
97
|
+
$stdout
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def mute(ip, port)
|
|
102
|
+
@muted["#{ip}:#{port}"] = true
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def unmute(ip, port)
|
|
106
|
+
@muted.delete "#{ip}:#{port}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def unmute_all
|
|
110
|
+
@muted = {}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def muted?(item)
|
|
114
|
+
item[:ip] && item[:port] && @muted["#{item[:ip]}:#{item[:port]}"]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def level_enabled?(item)
|
|
118
|
+
return false if @settings['info'] == false && item[:level] == :info
|
|
119
|
+
return false if @settings['debug'] != true && item[:level] == :debug
|
|
120
|
+
return false if @settings['statistics'] != true && item[:level] == :statistics
|
|
121
|
+
return false if @settings['test'] != true && item[:level] == :test
|
|
122
|
+
|
|
123
|
+
true
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def output(level, str)
|
|
127
|
+
return if str.empty? || /^\s+$/.match(str)
|
|
128
|
+
|
|
129
|
+
str = colorize level, str
|
|
130
|
+
@stream.puts str
|
|
131
|
+
@stream.flush
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def log(item, force: false)
|
|
135
|
+
return unless output?(item, force: force)
|
|
136
|
+
|
|
137
|
+
output item[:level], build_output(item)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def self.shorten_message_id(m_id, length = 4)
|
|
141
|
+
if m_id
|
|
142
|
+
m_id[0..(length - 1)].ljust(length)
|
|
143
|
+
else
|
|
144
|
+
' ' * length
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def dump(archive, num: nil)
|
|
149
|
+
num ||= archive.items.size
|
|
150
|
+
log = archive.items.last(num).map do |item|
|
|
151
|
+
str = build_output item
|
|
152
|
+
colorize item[:level], str
|
|
153
|
+
end
|
|
154
|
+
log.join("\n")
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def build_part(parts, item, key, &block)
|
|
158
|
+
skey = key.to_s
|
|
159
|
+
return unless @settings[skey]
|
|
160
|
+
|
|
161
|
+
part = item[key]
|
|
162
|
+
part = yield part if block
|
|
163
|
+
part = part.to_s
|
|
164
|
+
part = part.ljust @settings[skey] if @settings[skey].is_a?(Integer)
|
|
165
|
+
|
|
166
|
+
# replace the first char with a dash if string is all whitespace
|
|
167
|
+
part = @settings['tabs'].ljust(part.length) if @settings['tabs'] && part !~ /\S/
|
|
168
|
+
parts << part
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def add_metadata_parts(parts, item)
|
|
172
|
+
build_part(parts, item, :prefix) { @settings['prefix'] if @settings['prefix'] != false }
|
|
173
|
+
build_part(parts, item, :index)
|
|
174
|
+
build_part(parts, item, :author)
|
|
175
|
+
build_part(parts, item, :timestamp) { |part| Clock.to_s part }
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def add_connection_parts(parts, item)
|
|
179
|
+
build_part(parts, item, :ip)
|
|
180
|
+
build_part(parts, item, :port)
|
|
181
|
+
build_part(parts, item, :site_id)
|
|
182
|
+
build_part(parts, item, :component)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def add_message_parts(parts, item)
|
|
186
|
+
build_part(parts, item, :direction) { |part| { in: 'In', out: 'Out' }[part] }
|
|
187
|
+
build_part(parts, item, :level, &:capitalize)
|
|
188
|
+
build_part(parts, item, :id) { Logger.shorten_message_id(item[:message].m_id, 4) if item[:message] }
|
|
189
|
+
build_part(parts, item, :text)
|
|
190
|
+
build_part(parts, item, :json) { item[:message]&.json }
|
|
191
|
+
build_part(parts, item, :exception) { |e| [e.class, e.backtrace].flatten.join("\n") }
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def add_output_parts(parts, item)
|
|
195
|
+
add_metadata_parts(parts, item)
|
|
196
|
+
add_connection_parts(parts, item)
|
|
197
|
+
add_message_parts(parts, item)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def build_output(item)
|
|
201
|
+
parts = []
|
|
202
|
+
add_output_parts(parts, item)
|
|
203
|
+
parts.join(' ').chomp(@settings['tabs'].to_s).rstrip
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -6,21 +6,19 @@ module RSMP
|
|
|
6
6
|
module Logging
|
|
7
7
|
attr_reader :archive, :logger
|
|
8
8
|
|
|
9
|
-
def initialize_logging
|
|
9
|
+
def initialize_logging(options)
|
|
10
10
|
@archive = options[:archive] || RSMP::Archive.new
|
|
11
11
|
@logger = options[:logger] || RSMP::Logger.new(options[:log_settings])
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def author
|
|
15
|
-
end
|
|
14
|
+
def author; end
|
|
16
15
|
|
|
17
|
-
def log
|
|
18
|
-
default = { text:str, level: :log, author: author, ip: @ip, port: @port }
|
|
16
|
+
def log(str, options = {})
|
|
17
|
+
default = { text: str, level: :log, author: author, ip: @ip, port: @port }
|
|
19
18
|
prepared = RSMP::Archive.prepare_item default.merge(options)
|
|
20
19
|
@archive.add prepared
|
|
21
20
|
@logger.log prepared
|
|
22
21
|
prepared
|
|
23
22
|
end
|
|
24
|
-
|
|
25
23
|
end
|
|
26
|
-
end
|
|
24
|
+
end
|