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
|
@@ -8,179 +8,187 @@ module RSMP
|
|
|
8
8
|
module Convert
|
|
9
9
|
module Export
|
|
10
10
|
module JSONSchema
|
|
11
|
-
|
|
12
|
-
@@json_options = {
|
|
11
|
+
JSON_OPTIONS = {
|
|
13
12
|
array_nl: "\n",
|
|
14
13
|
object_nl: "\n",
|
|
15
14
|
indent: ' ',
|
|
16
15
|
space_before: ' ',
|
|
17
16
|
space: ' '
|
|
18
|
-
}
|
|
17
|
+
}.freeze
|
|
19
18
|
|
|
20
|
-
def self.output_json
|
|
21
|
-
JSON.generate(item
|
|
19
|
+
def self.output_json(item)
|
|
20
|
+
JSON.generate(item, JSON_OPTIONS)
|
|
22
21
|
end
|
|
23
22
|
|
|
24
|
-
def self.build_value
|
|
23
|
+
def self.build_value(item)
|
|
25
24
|
out = {}
|
|
26
|
-
|
|
27
|
-
if item['description']
|
|
28
|
-
out["description"] = item['description']
|
|
29
|
-
end
|
|
25
|
+
out['description'] = item['description'] if item['description']
|
|
30
26
|
|
|
31
27
|
if item['list']
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
out["$ref"] = "../../../core/3.1.1/definitions.json#/integer_list"
|
|
37
|
-
else
|
|
38
|
-
raise "Error: List of #{item['type']} is not supported: #{item.inspect}"
|
|
39
|
-
end
|
|
28
|
+
build_list_value(out, item)
|
|
29
|
+
else
|
|
30
|
+
build_single_value(out, item)
|
|
31
|
+
end
|
|
40
32
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
out['pattern'] = /(?-mix:^(#{value_list})(?:,(#{value_list}))*$)/
|
|
44
|
-
end
|
|
33
|
+
out
|
|
34
|
+
end
|
|
45
35
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
def self.build_list_value(out, item)
|
|
37
|
+
case item['type']
|
|
38
|
+
when 'boolean'
|
|
39
|
+
out['$ref'] = '../../../core/3.1.1/definitions.json#/boolean_list'
|
|
40
|
+
when 'integer', 'ordinal', 'unit', 'scale', 'long'
|
|
41
|
+
out['$ref'] = '../../../core/3.1.1/definitions.json#/integer_list'
|
|
49
42
|
else
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
out["type"] = "string"
|
|
53
|
-
when "boolean"
|
|
54
|
-
out["$ref"] = "../../../core/3.1.1/definitions.json#/boolean"
|
|
55
|
-
when "timestamp"
|
|
56
|
-
out["$ref"] = "../../../core/3.1.1/definitions.json#/timestamp"
|
|
57
|
-
when "integer", "ordinal", "unit", "scale", "long"
|
|
58
|
-
out["$ref"] = "../../../core/3.1.1/definitions.json#/integer"
|
|
59
|
-
else
|
|
60
|
-
out["type"] = "string"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
if item["values"]
|
|
64
|
-
out["enum"] = item["values"].keys.sort
|
|
65
|
-
end
|
|
43
|
+
raise "Error: List of #{item['type']} is not supported: #{item.inspect}"
|
|
44
|
+
end
|
|
66
45
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
46
|
+
if item['values']
|
|
47
|
+
value_list = item['values'].keys.join('|')
|
|
48
|
+
out['pattern'] = /(?-mix:^(#{value_list})(?:,(#{value_list}))*$)/
|
|
70
49
|
end
|
|
71
50
|
|
|
51
|
+
puts "Warning: Pattern not support for lists: #{item.inspect}" if item['pattern']
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.build_single_value(out, item)
|
|
55
|
+
case item['type']
|
|
56
|
+
when 'boolean'
|
|
57
|
+
out['$ref'] = '../../../core/3.1.1/definitions.json#/boolean'
|
|
58
|
+
when 'timestamp'
|
|
59
|
+
out['$ref'] = '../../../core/3.1.1/definitions.json#/timestamp'
|
|
60
|
+
when 'integer', 'ordinal', 'unit', 'scale', 'long'
|
|
61
|
+
out['$ref'] = '../../../core/3.1.1/definitions.json#/integer'
|
|
62
|
+
else # includes 'string', 'base64' and any other types
|
|
63
|
+
out['type'] = 'string'
|
|
64
|
+
end
|
|
72
65
|
|
|
73
|
-
out
|
|
66
|
+
out['enum'] = item['values'].keys.sort if item['values']
|
|
67
|
+
out['pattern'] = item['pattern'] if item['pattern']
|
|
74
68
|
end
|
|
75
69
|
|
|
76
|
-
def self.build_item
|
|
77
|
-
json = {
|
|
70
|
+
def self.build_item(item, property_key: 'v')
|
|
71
|
+
json = { 'allOf' => [{ 'description' => item['description'] }] }
|
|
78
72
|
if item['arguments']
|
|
79
|
-
json[
|
|
80
|
-
item['arguments'].each_pair do |key,argument|
|
|
81
|
-
json[
|
|
82
|
-
|
|
83
|
-
|
|
73
|
+
json['allOf'].first['properties'] = { 'n' => { 'enum' => item['arguments'].keys.sort } }
|
|
74
|
+
item['arguments'].each_pair do |key, argument|
|
|
75
|
+
json['allOf'] << {
|
|
76
|
+
'if' => { 'required' => ['n'], 'properties' => { 'n' => { 'const' => key } } },
|
|
77
|
+
'then' => { 'properties' => { property_key => build_value(argument) } }
|
|
84
78
|
}
|
|
85
79
|
end
|
|
86
80
|
end
|
|
87
81
|
json
|
|
88
82
|
end
|
|
89
83
|
|
|
90
|
-
def self.output_alarms
|
|
84
|
+
def self.output_alarms(out, items)
|
|
91
85
|
list = items.keys.sort.map do |key|
|
|
92
86
|
{
|
|
93
|
-
|
|
94
|
-
|
|
87
|
+
'if' => { 'required' => ['aCId'], 'properties' => { 'aCId' => { 'const' => key } } },
|
|
88
|
+
'then' => { '$ref' => "#{key}.json" }
|
|
95
89
|
}
|
|
96
90
|
end
|
|
97
91
|
json = {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
92
|
+
'properties' => {
|
|
93
|
+
'aCId' => { 'enum' => items.keys.sort },
|
|
94
|
+
'rvs' => { 'items' => { 'allOf' => list } }
|
|
101
95
|
}
|
|
102
96
|
}
|
|
103
97
|
out['alarms/alarms.json'] = output_json json
|
|
104
|
-
items.each_pair { |key,item| output_alarm out, key, item }
|
|
98
|
+
items.each_pair { |key, item| output_alarm out, key, item }
|
|
105
99
|
end
|
|
106
100
|
|
|
107
|
-
def self.output_alarm
|
|
101
|
+
def self.output_alarm(out, key, item)
|
|
108
102
|
json = build_item item
|
|
109
103
|
out["alarms/#{key}.json"] = output_json json
|
|
110
104
|
end
|
|
111
105
|
|
|
112
|
-
def self.output_statuses
|
|
113
|
-
list = [
|
|
106
|
+
def self.output_statuses(out, items)
|
|
107
|
+
list = [{ 'properties' => { 'sCI' => { 'enum' => items.keys.sort } } }]
|
|
114
108
|
items.keys.sort.each do |key|
|
|
115
109
|
list << {
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
'if' => { 'required' => ['sCI'], 'properties' => { 'sCI' => { 'const' => key } } },
|
|
111
|
+
'then' => { '$ref' => "#{key}.json" }
|
|
118
112
|
}
|
|
119
113
|
end
|
|
120
|
-
json = {
|
|
114
|
+
json = { 'properties' => { 'sS' => { 'items' => { 'allOf' => list } } } }
|
|
121
115
|
out['statuses/statuses.json'] = output_json json
|
|
122
|
-
items.each_pair { |key,item| output_status out, key, item }
|
|
116
|
+
items.each_pair { |key, item| output_status out, key, item }
|
|
123
117
|
end
|
|
124
118
|
|
|
125
|
-
def self.output_status
|
|
126
|
-
json = build_item item, property_key:'s'
|
|
119
|
+
def self.output_status(out, key, item)
|
|
120
|
+
json = build_item item, property_key: 's'
|
|
127
121
|
out["statuses/#{key}.json"] = output_json json
|
|
128
122
|
end
|
|
129
123
|
|
|
130
|
-
def self.output_commands
|
|
131
|
-
list = [
|
|
124
|
+
def self.output_commands(out, items)
|
|
125
|
+
list = [{ 'properties' => { 'cCI' => { 'enum' => items.keys.sort } } }]
|
|
132
126
|
items.keys.sort.each do |key|
|
|
133
127
|
list << {
|
|
134
|
-
|
|
135
|
-
|
|
128
|
+
'if' => { 'required' => ['cCI'], 'properties' => { 'cCI' => { 'const' => key } } },
|
|
129
|
+
'then' => { '$ref' => "#{key}.json" }
|
|
136
130
|
}
|
|
137
131
|
end
|
|
138
|
-
json = {
|
|
132
|
+
json = { 'items' => { 'allOf' => list } }
|
|
139
133
|
out['commands/commands.json'] = output_json json
|
|
140
134
|
|
|
141
|
-
json = {
|
|
135
|
+
json = { 'properties' => { 'arg' => { '$ref' => 'commands.json' } } }
|
|
142
136
|
out['commands/command_requests.json'] = output_json json
|
|
143
137
|
|
|
144
|
-
json = {
|
|
138
|
+
json = { 'properties' => { 'rvs' => { '$ref' => 'commands.json' } } }
|
|
145
139
|
out['commands/command_responses.json'] = output_json json
|
|
146
140
|
|
|
147
|
-
items.each_pair { |key,item| output_command out, key, item }
|
|
141
|
+
items.each_pair { |key, item| output_command out, key, item }
|
|
148
142
|
end
|
|
149
143
|
|
|
150
|
-
def self.output_command
|
|
144
|
+
def self.output_command(out, key, item)
|
|
151
145
|
json = build_item item
|
|
152
|
-
json[
|
|
146
|
+
json['allOf'].first['properties']['cO'] = { 'const' => item['command'] }
|
|
153
147
|
out["commands/#{key}.json"] = output_json json
|
|
154
148
|
end
|
|
155
149
|
|
|
156
|
-
def self.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
{
|
|
163
|
-
"if" => { "required" => ["type"], "properties" => { "type" => { "const" => "CommandRequest" }}},
|
|
164
|
-
"then" => { "$ref" => "commands/command_requests.json" }
|
|
165
|
-
},
|
|
166
|
-
{
|
|
167
|
-
"if" => { "required" => ["type"], "properties" => { "type" => { "const" => "CommandResponse" }}},
|
|
168
|
-
"then" => { "$ref" => "commands/command_responses.json" }
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
"if" => { "required" => ["type"], "properties" => { "type" => { "enum" => ["StatusRequest","StatusResponse","StatusSubscribe","StatusUnsubscribe","StatusUpdate"] }}},
|
|
172
|
-
"then" => { "$ref" => "statuses/statuses.json" }
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
"if" => { "required" => ["type"], "properties" => { "type" => { "const" => "Alarm" }}},
|
|
176
|
-
"then" => { "$ref" => "alarms/alarms.json" }
|
|
177
|
-
}
|
|
178
|
-
]
|
|
150
|
+
def self.build_root_schema(meta)
|
|
151
|
+
{
|
|
152
|
+
'name' => meta['name'],
|
|
153
|
+
'description' => meta['description'],
|
|
154
|
+
'version' => meta['version'],
|
|
155
|
+
'allOf' => build_root_refs
|
|
179
156
|
}
|
|
180
|
-
out["sxl.json"] = output_json json
|
|
181
157
|
end
|
|
182
158
|
|
|
183
|
-
def self.
|
|
159
|
+
def self.build_root_refs
|
|
160
|
+
[
|
|
161
|
+
{
|
|
162
|
+
'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'CommandRequest' } } },
|
|
163
|
+
'then' => { '$ref' => 'commands/command_requests.json' }
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'CommandResponse' } } },
|
|
167
|
+
'then' => { '$ref' => 'commands/command_responses.json' }
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
'if' => { 'required' => ['type'],
|
|
171
|
+
'properties' => {
|
|
172
|
+
'type' => {
|
|
173
|
+
'enum' => %w[StatusRequest StatusResponse StatusSubscribe
|
|
174
|
+
StatusUnsubscribe StatusUpdate]
|
|
175
|
+
}
|
|
176
|
+
} },
|
|
177
|
+
'then' => { '$ref' => 'statuses/statuses.json' }
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
'if' => { 'required' => ['type'], 'properties' => { 'type' => { 'const' => 'Alarm' } } },
|
|
181
|
+
'then' => { '$ref' => 'alarms/alarms.json' }
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def self.output_root(out, meta)
|
|
187
|
+
json = build_root_schema(meta)
|
|
188
|
+
out['sxl.json'] = output_json json
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def self.generate(sxl)
|
|
184
192
|
out = {}
|
|
185
193
|
output_root out, sxl[:meta]
|
|
186
194
|
output_alarms out, sxl[:alarms]
|
|
@@ -189,18 +197,16 @@ module RSMP
|
|
|
189
197
|
out
|
|
190
198
|
end
|
|
191
199
|
|
|
192
|
-
def self.write
|
|
200
|
+
def self.write(sxl, folder)
|
|
193
201
|
out = generate sxl
|
|
194
|
-
out.each_pair do |relative_path,str|
|
|
202
|
+
out.each_pair do |relative_path, str|
|
|
195
203
|
path = File.join(folder, relative_path)
|
|
196
|
-
FileUtils.mkdir_p File.dirname(path)
|
|
197
|
-
file = File.open(path, 'w+')
|
|
204
|
+
FileUtils.mkdir_p File.dirname(path) # create folders if needed
|
|
205
|
+
file = File.open(path, 'w+') # w+ means truncate or create new file
|
|
198
206
|
file.puts str
|
|
199
207
|
end
|
|
200
208
|
end
|
|
201
|
-
|
|
202
209
|
end
|
|
203
|
-
|
|
204
210
|
end
|
|
205
211
|
end
|
|
206
|
-
end
|
|
212
|
+
end
|
|
@@ -8,34 +8,37 @@ module RSMP
|
|
|
8
8
|
module Convert
|
|
9
9
|
module Import
|
|
10
10
|
module YAML
|
|
11
|
-
|
|
12
|
-
def self.read path
|
|
11
|
+
def self.read(path)
|
|
13
12
|
convert ::YAML.load_file(path)
|
|
14
13
|
end
|
|
15
14
|
|
|
16
|
-
def self.parse
|
|
15
|
+
def self.parse(str)
|
|
17
16
|
convert ::YAML.load(str)
|
|
18
17
|
end
|
|
19
18
|
|
|
20
|
-
def self.convert
|
|
21
|
-
sxl =
|
|
22
|
-
meta: {},
|
|
23
|
-
alarms: {},
|
|
24
|
-
statuses: {},
|
|
25
|
-
commands: {}
|
|
26
|
-
}
|
|
27
|
-
|
|
19
|
+
def self.convert(yaml)
|
|
20
|
+
sxl = build_empty_sxl
|
|
28
21
|
sxl[:meta] = yaml['meta']
|
|
22
|
+
merge_objects(sxl, yaml['objects'])
|
|
23
|
+
sxl
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.build_empty_sxl
|
|
27
|
+
{ meta: {}, alarms: {}, statuses: {}, commands: {} }
|
|
28
|
+
end
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
object["commands"].each { |id,item| sxl[:commands][id] = item } if object["commands"]
|
|
30
|
+
def self.merge_objects(sxl, objects)
|
|
31
|
+
objects.each_pair do |_type, object|
|
|
32
|
+
merge_object_items(sxl, object)
|
|
34
33
|
end
|
|
35
|
-
sxl
|
|
36
34
|
end
|
|
37
|
-
end
|
|
38
35
|
|
|
36
|
+
def self.merge_object_items(sxl, object)
|
|
37
|
+
object['alarms']&.each { |id, item| sxl[:alarms][id] = item }
|
|
38
|
+
object['statuses']&.each { |id, item| sxl[:statuses][id] = item }
|
|
39
|
+
object['commands']&.each { |id, item| sxl[:commands][id] = item }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
39
42
|
end
|
|
40
43
|
end
|
|
41
|
-
end
|
|
44
|
+
end
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
require 'time'
|
|
7
7
|
|
|
8
8
|
module RSMP
|
|
9
|
-
|
|
10
9
|
class Clock
|
|
11
10
|
attr_reader :adjustment
|
|
12
11
|
|
|
@@ -14,7 +13,7 @@ module RSMP
|
|
|
14
13
|
@adjustment = 0
|
|
15
14
|
end
|
|
16
15
|
|
|
17
|
-
def set
|
|
16
|
+
def set(target)
|
|
18
17
|
@adjustment = target - Time.now
|
|
19
18
|
end
|
|
20
19
|
|
|
@@ -34,12 +33,12 @@ module RSMP
|
|
|
34
33
|
Time.now.utc
|
|
35
34
|
end
|
|
36
35
|
|
|
37
|
-
def self.to_s
|
|
38
|
-
(time || now).strftime(
|
|
36
|
+
def self.to_s(time = nil)
|
|
37
|
+
(time || now).strftime('%FT%T.%3NZ')
|
|
39
38
|
end
|
|
40
39
|
|
|
41
|
-
def self.parse
|
|
40
|
+
def self.parse(str)
|
|
42
41
|
Time.parse(str)
|
|
43
42
|
end
|
|
44
43
|
end
|
|
45
|
-
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Error < StandardError
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
class InvalidPacket < Error
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class MalformedMessage < Error
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class SchemaError < Error
|
|
12
|
+
attr_accessor :schemas
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class InvalidMessage < Error
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class UnknownMessage < Error
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class MissingAcknowledgment < Error
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class MissingWatchdog < Error
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class MessageRejected < Error
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
class MissingAttribute < InvalidMessage
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class FatalError < Error
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
class HandshakeError < FatalError
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class NotReady < Error
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class TimeoutError < Error
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
class DisconnectError < Error
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
class ConnectionError < Error
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
class UnknownComponent < Error
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class UnknownCommand < Error
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class UnknownStatus < Error
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class ConfigurationError < Error
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class RepeatedAlarmError < Error
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
class RepeatedStatusError < Error
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
class TimestampError < Error
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -12,23 +12,20 @@
|
|
|
12
12
|
|
|
13
13
|
module RSMP
|
|
14
14
|
module Inspect
|
|
15
|
-
|
|
16
15
|
def inspector *short_items
|
|
17
16
|
instance_variables.map do |var_name|
|
|
18
17
|
var = instance_variable_get(var_name)
|
|
19
18
|
class_name = var.class.name
|
|
20
19
|
|
|
21
20
|
short = short_items.include?(var_name) ||
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
class_name.start_with?('Async') ||
|
|
22
|
+
class_name.start_with?('RSMP')
|
|
24
23
|
|
|
25
24
|
if short
|
|
26
|
-
if var.is_a?
|
|
27
|
-
"#{var_name}: #<#{class_name}:#{class_name.object_id}, #{var.size} items>"
|
|
28
|
-
elsif var.is_a? Hash
|
|
25
|
+
if var.is_a?(Array) || var.is_a?(Hash)
|
|
29
26
|
"#{var_name}: #<#{class_name}:#{class_name.object_id}, #{var.size} items>"
|
|
30
27
|
else
|
|
31
|
-
"#{var_name}: #{var
|
|
28
|
+
"#{var_name}: #{var}"
|
|
32
29
|
end
|
|
33
30
|
else
|
|
34
31
|
"#{var_name}: #{var.inspect}"
|
|
@@ -39,8 +36,7 @@ module RSMP
|
|
|
39
36
|
# override this if you want additional variable to be shown in the short format,
|
|
40
37
|
# or ottherwise change the inspect format
|
|
41
38
|
def inspect
|
|
42
|
-
"#<#{self.class.name}:#{
|
|
39
|
+
"#<#{self.class.name}:#{object_id}, #{inspector}>"
|
|
43
40
|
end
|
|
44
|
-
|
|
45
41
|
end
|
|
46
|
-
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Archive of log items, which can be messages or info items.
|
|
2
|
+
# All items are timestamped, and stored chronologically.
|
|
3
|
+
|
|
4
|
+
module RSMP
|
|
5
|
+
class Archive
|
|
6
|
+
include Inspect
|
|
7
|
+
|
|
8
|
+
attr_reader :items
|
|
9
|
+
|
|
10
|
+
@index = 0
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_accessor :index
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(max = 100)
|
|
17
|
+
@items = []
|
|
18
|
+
@max = max
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def inspect
|
|
22
|
+
"#<#{self.class.name}:#{object_id}, #{inspector(:@items)}>"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.prepare_item(item)
|
|
26
|
+
raise ArgumentError unless item.is_a? Hash
|
|
27
|
+
|
|
28
|
+
cleaned = item.slice(:author, :level, :ip, :port, :site_id, :component, :text, :message, :exception)
|
|
29
|
+
cleaned[:timestamp] = Clock.now
|
|
30
|
+
if item[:message]
|
|
31
|
+
cleaned[:direction] = item[:message].direction
|
|
32
|
+
cleaned[:component] = item[:message].attributes['cId']
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
cleaned
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.increase_index
|
|
39
|
+
self.index += 1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.current_index
|
|
43
|
+
index
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def by_level(levels)
|
|
47
|
+
items.select { |item| levels.include? item[:level] }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def strings
|
|
51
|
+
items.map { |item| item[:str] }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def add(item)
|
|
55
|
+
item[:index] = RSMP::Archive.increase_index
|
|
56
|
+
@items << item
|
|
57
|
+
return unless @items.size > @max
|
|
58
|
+
|
|
59
|
+
@items.shift
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def find(options, &)
|
|
65
|
+
# search backwards from newest to older, stopping once messages
|
|
66
|
+
# are older that options[:earliest]
|
|
67
|
+
out = []
|
|
68
|
+
@items.reverse_each do |item|
|
|
69
|
+
break if too_old?(item, options[:earliest])
|
|
70
|
+
next unless matches_filters?(item, options, &)
|
|
71
|
+
|
|
72
|
+
out.unshift item
|
|
73
|
+
end
|
|
74
|
+
out
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def too_old?(item, earliest)
|
|
78
|
+
earliest && item[:timestamp] < earliest
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def matches_filters?(item, options, &block)
|
|
82
|
+
return false if options[:level] && item[:level] != options[:level]
|
|
83
|
+
return false if options[:type] && !matches_type?(item, options[:type])
|
|
84
|
+
return false if options[:with_message] && !message?(item)
|
|
85
|
+
return false if block_given? && block.call != true
|
|
86
|
+
|
|
87
|
+
true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def matches_type?(item, type)
|
|
91
|
+
item[:message] && item[:message].type == type
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def message?(item)
|
|
95
|
+
item[:direction] && item[:message]
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module RSMP
|
|
2
|
+
class Logger
|
|
3
|
+
# Handles colorization of log output
|
|
4
|
+
module Colorization
|
|
5
|
+
def default_colors
|
|
6
|
+
{
|
|
7
|
+
'info' => 'white',
|
|
8
|
+
'log' => 'light_blue',
|
|
9
|
+
'statistics' => 'light_black',
|
|
10
|
+
'warning' => 'light_yellow',
|
|
11
|
+
'error' => 'red',
|
|
12
|
+
'debug' => 'light_black',
|
|
13
|
+
'collect' => 'light_black'
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def colorize_with_map(level, str, colors)
|
|
18
|
+
color = colors[level.to_s]
|
|
19
|
+
color ? str.colorize(color.to_sym) : str
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def apply_hash_colors(level, str)
|
|
23
|
+
colors = default_colors
|
|
24
|
+
colors.merge! @settings['color'] if @settings['color'].is_a?(Hash)
|
|
25
|
+
colorize_with_map(level, str, colors)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def colorize(level, str)
|
|
29
|
+
return str if @settings['color'] == false || @settings['color'].nil?
|
|
30
|
+
|
|
31
|
+
if @settings['color'] == true || @settings['color'].is_a?(Hash)
|
|
32
|
+
apply_hash_colors(level, str)
|
|
33
|
+
elsif %i[nack warning error].include?(level)
|
|
34
|
+
str.colorize(@settings['color']).bold
|
|
35
|
+
else
|
|
36
|
+
str.colorize @settings['color']
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|