rsmp 0.3.3 → 0.3.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/rsmp/component.rb +14 -4
- data/lib/rsmp/components.rb +16 -3
- data/lib/rsmp/error.rb +3 -0
- data/lib/rsmp/message.rb +60 -5
- data/lib/rsmp/proxy.rb +11 -5
- data/lib/rsmp/site.rb +1 -1
- data/lib/rsmp/site_proxy.rb +12 -17
- data/lib/rsmp/supervisor_proxy.rb +0 -10
- data/lib/rsmp/tlc.rb +4 -2
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +0 -1
- metadata +3 -4
- data/lib/rsmp/alarm.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63163e8e010e001deffd0bba691e343c028ae5edbf3a5c9022529d319c36035e
|
4
|
+
data.tar.gz: 07225c7538b514c3b74dbc307a432f32eb1fe839faaeef4483208206b29e103a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6eed25d057be1a6766b94d1127b41f498b4e3532bf5650d7c888321dfe48bafaf2af69ff2d871cc437fc44ae9286d898da2387bc2e267d451aca332d3695159f
|
7
|
+
data.tar.gz: 011f89ceb76bbfdc521ca0730c2d7f1c48663e4faf35576e4e72bee83831813745bc0ce0c45aab4201c1874f1ee21a5c1f6235dbab0c16feab1e3970acc56d3b
|
data/Gemfile.lock
CHANGED
data/lib/rsmp/component.rb
CHANGED
@@ -13,7 +13,7 @@ module RSMP
|
|
13
13
|
:rest,
|
14
14
|
:not_connected ]
|
15
15
|
|
16
|
-
def initialize node:, id:, grouped:
|
16
|
+
def initialize node:, id:, grouped: false
|
17
17
|
@c_id = id
|
18
18
|
@node = node
|
19
19
|
@grouped = grouped
|
@@ -57,9 +57,6 @@ module RSMP
|
|
57
57
|
def aggregated_status_changed options={}
|
58
58
|
@node.aggregated_status_changed self, options
|
59
59
|
end
|
60
|
-
|
61
|
-
def alarm code:, status:
|
62
|
-
end
|
63
60
|
|
64
61
|
def log str, options
|
65
62
|
@node.log str, options
|
@@ -73,5 +70,18 @@ module RSMP
|
|
73
70
|
raise UnknownStatus.new "Status #{status_code}/#{status_name} not implemented by #{self.class}"
|
74
71
|
end
|
75
72
|
|
73
|
+
def handle_alarm message
|
74
|
+
code = message.attribute('aCId')
|
75
|
+
alarm = @alarms[code]
|
76
|
+
if alarm
|
77
|
+
if alarm.differ? message
|
78
|
+
@alarms[code] = alarm
|
79
|
+
else
|
80
|
+
raise RepeatedAlarmError.new("no changes from previous alarm #{alarm.m_id_short}")
|
81
|
+
end
|
82
|
+
else
|
83
|
+
@alarms[code] = message
|
84
|
+
end
|
85
|
+
end
|
76
86
|
end
|
77
87
|
end
|
data/lib/rsmp/components.rb
CHANGED
@@ -38,10 +38,23 @@ module RSMP
|
|
38
38
|
Component.new id:id, node: self, grouped: type=='main'
|
39
39
|
end
|
40
40
|
|
41
|
-
def
|
41
|
+
def infer_component_type component_id
|
42
|
+
Component
|
43
|
+
end
|
44
|
+
|
45
|
+
def find_component component_id, build: true
|
42
46
|
component = @components[component_id]
|
43
|
-
|
44
|
-
|
47
|
+
return component if component
|
48
|
+
if build
|
49
|
+
inferred = infer_component_type component_id
|
50
|
+
component = inferred.new node: self, id: component_id
|
51
|
+
@components[ component_id] = component
|
52
|
+
class_name = component.class.name.split('::').last
|
53
|
+
log "Inferred #{class_name} component #{component_id}", level: :info
|
54
|
+
component
|
55
|
+
else
|
56
|
+
raise UnknownComponent.new("Component #{component_id} not found") unless component
|
57
|
+
end
|
45
58
|
end
|
46
59
|
|
47
60
|
end
|
data/lib/rsmp/error.rb
CHANGED
data/lib/rsmp/message.rb
CHANGED
@@ -36,7 +36,7 @@ module RSMP
|
|
36
36
|
when "Watchdog"
|
37
37
|
message = Watchdog.new attributes
|
38
38
|
when "Alarm"
|
39
|
-
message =
|
39
|
+
message = self.build_alarm attributes
|
40
40
|
when "CommandRequest"
|
41
41
|
message = CommandRequest.new attributes
|
42
42
|
when "CommandResponse"
|
@@ -59,6 +59,23 @@ module RSMP
|
|
59
59
|
message
|
60
60
|
end
|
61
61
|
|
62
|
+
def self.build_alarm attributes
|
63
|
+
case attributes["aSp"]
|
64
|
+
when 'Issue'
|
65
|
+
AlarmIssue.new attributes
|
66
|
+
when 'Request'
|
67
|
+
AlarmRequest.new attributes
|
68
|
+
when 'Acknowledge'
|
69
|
+
AlarmAcknowledged.new attributes
|
70
|
+
when 'Suspend'
|
71
|
+
AlarmSuspend.new attributes
|
72
|
+
when 'Resume'
|
73
|
+
AlarmResume.new attributes
|
74
|
+
else
|
75
|
+
Alarm.new attributes
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
62
79
|
def type
|
63
80
|
@attributes["type"]
|
64
81
|
end
|
@@ -191,26 +208,64 @@ module RSMP
|
|
191
208
|
def initialize attributes = {}
|
192
209
|
super({
|
193
210
|
"type" => "Alarm",
|
211
|
+
"ntsOId" => '',
|
212
|
+
"xNId" => '',
|
213
|
+
"xACId" => '',
|
214
|
+
"xNACId" => ''
|
194
215
|
}.merge attributes)
|
195
216
|
end
|
217
|
+
|
218
|
+
def differ? from
|
219
|
+
%w{aSp aCId ack aS sS aTs cat pri}.each do |key|
|
220
|
+
return true if attribute(key).downcase != from.attribute(key).downcase
|
221
|
+
end
|
222
|
+
return true if attribute('rvs') != from.attribute('rvs')
|
223
|
+
false
|
224
|
+
end
|
196
225
|
end
|
197
226
|
|
198
|
-
class
|
227
|
+
class AlarmIssue < Alarm
|
199
228
|
def initialize attributes = {}
|
200
229
|
super({
|
201
|
-
"
|
230
|
+
"aSp" => "Issue",
|
202
231
|
}.merge attributes)
|
203
232
|
end
|
204
233
|
end
|
205
234
|
|
206
|
-
class
|
235
|
+
class AlarmRequest < Alarm
|
207
236
|
def initialize attributes = {}
|
208
237
|
super({
|
209
|
-
"
|
238
|
+
"aSp" => "Request",
|
239
|
+
}.merge attributes)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class AlarmAcknowledged < Alarm
|
244
|
+
def initialize attributes = {}
|
245
|
+
super({
|
246
|
+
"aSp" => "Acknowledge",
|
210
247
|
}.merge attributes)
|
211
248
|
end
|
212
249
|
end
|
213
250
|
|
251
|
+
class AlarmSuspend < Alarm
|
252
|
+
def initialize attributes = {}
|
253
|
+
super({
|
254
|
+
"aSp" => "Suspend",
|
255
|
+
}.merge attributes)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
class AlarmResume < Alarm
|
260
|
+
def initialize attributes = {}
|
261
|
+
super({
|
262
|
+
"aSp" => "Resume",
|
263
|
+
}.merge attributes)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
|
214
269
|
class Watchdog < Message
|
215
270
|
def initialize attributes = {}
|
216
271
|
super({
|
data/lib/rsmp/proxy.rb
CHANGED
@@ -73,6 +73,11 @@ module RSMP
|
|
73
73
|
@state == :ready
|
74
74
|
end
|
75
75
|
|
76
|
+
def connected?
|
77
|
+
@state == :starting || @state == :ready
|
78
|
+
end
|
79
|
+
|
80
|
+
|
76
81
|
def start
|
77
82
|
set_state :starting
|
78
83
|
end
|
@@ -118,7 +123,6 @@ module RSMP
|
|
118
123
|
task.annotate "reader"
|
119
124
|
@stream ||= Async::IO::Stream.new(@socket)
|
120
125
|
@protocol ||= Async::IO::Protocol::Line.new(@stream,WRAPPING_DELIMITER) # rsmp messages are json terminated with a form-feed
|
121
|
-
|
122
126
|
while json = @protocol.read_line
|
123
127
|
beginning = Time.now
|
124
128
|
message = process_packet json
|
@@ -267,12 +271,13 @@ module RSMP
|
|
267
271
|
end
|
268
272
|
|
269
273
|
def send_message message, reason=nil, validate: true
|
274
|
+
raise NotReady unless connected?
|
270
275
|
raise IOError unless @protocol
|
271
276
|
message.direction = :out
|
272
277
|
message.generate_json
|
273
278
|
message.validate get_schemas unless validate==false
|
274
|
-
expect_acknowledgement message
|
275
279
|
@protocol.write_lines message.json
|
280
|
+
expect_acknowledgement message
|
276
281
|
notify message
|
277
282
|
log_send message, reason
|
278
283
|
rescue EOFError, IOError
|
@@ -303,10 +308,11 @@ module RSMP
|
|
303
308
|
end
|
304
309
|
|
305
310
|
def should_validate_ingoing_message? message
|
306
|
-
return
|
311
|
+
return true unless @site_settings
|
307
312
|
skip = @site_settings.dig('skip_validation')
|
308
|
-
return true unless skip
|
309
|
-
|
313
|
+
return true unless skip
|
314
|
+
klass = message.class.name.split('::').last
|
315
|
+
!skip.include?(klass)
|
310
316
|
end
|
311
317
|
|
312
318
|
def process_packet json
|
data/lib/rsmp/site.rb
CHANGED
data/lib/rsmp/site_proxy.rb
CHANGED
@@ -125,17 +125,11 @@ module RSMP
|
|
125
125
|
se = message.attribute("se")
|
126
126
|
validate_aggregated_status(message,se) == false
|
127
127
|
c_id = message.attributes["cId"]
|
128
|
-
component =
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
log "Adding component #{c_id} to site #{@site_id}", level: :info
|
134
|
-
else
|
135
|
-
reason = "component #{c_id} not found"
|
136
|
-
dont_acknowledge message, "Ignoring #{message.type}:", reason
|
137
|
-
return
|
138
|
-
end
|
128
|
+
component = find_component c_id
|
129
|
+
unless component
|
130
|
+
reason = "component #{c_id} not found"
|
131
|
+
dont_acknowledge message, "Ignoring #{message.type}:", reason
|
132
|
+
return
|
139
133
|
end
|
140
134
|
|
141
135
|
component.set_aggregated_status_bools se
|
@@ -148,11 +142,17 @@ module RSMP
|
|
148
142
|
end
|
149
143
|
|
150
144
|
def process_alarm message
|
145
|
+
component = find_component message.attribute("cId")
|
146
|
+
status = ["ack","aS","sS"].map { |key| message.attribute(key) }.join(',')
|
147
|
+
component.handle_alarm message
|
151
148
|
alarm_code = message.attribute("aCId")
|
152
149
|
asp = message.attribute("aSp")
|
153
|
-
status = ["ack","aS","sS"].map { |key| message.attribute(key) }.join(',')
|
154
150
|
log "Received #{message.type}, #{alarm_code} #{asp} [#{status}]", message: message, level: :log
|
155
151
|
acknowledge message
|
152
|
+
rescue RSMP::RepeatedAlarmError => e
|
153
|
+
str = "Rejected #{message.type} message, "
|
154
|
+
dont_acknowledge message, str, "#{e}"
|
155
|
+
notify_error e.exception("#{str}#{e.message} #{message.json}")
|
156
156
|
end
|
157
157
|
|
158
158
|
def version_acknowledged
|
@@ -241,13 +241,8 @@ module RSMP
|
|
241
241
|
|
242
242
|
def send_alarm_acknowledgement component, alarm_code, options={}
|
243
243
|
message = RSMP::AlarmAcknowledged.new({
|
244
|
-
"ntsOId" => '',
|
245
|
-
"xNId" => '',
|
246
244
|
"cId" => component,
|
247
245
|
"aCId" => alarm_code,
|
248
|
-
"xACId" => '',
|
249
|
-
"xNACId" => '',
|
250
|
-
"aSp" => 'Acknowledge'
|
251
246
|
})
|
252
247
|
send_message message, validate: options[:validate]
|
253
248
|
message
|
@@ -363,16 +363,6 @@ module RSMP
|
|
363
363
|
end
|
364
364
|
end
|
365
365
|
|
366
|
-
def send_alarm
|
367
|
-
message = Alarm.new({
|
368
|
-
"aSTS"=>clock.to_s,
|
369
|
-
"fP"=>nil,
|
370
|
-
"fS"=>nil,
|
371
|
-
"se"=>@site.aggregated_status_bools
|
372
|
-
})
|
373
|
-
send_message message
|
374
|
-
end
|
375
|
-
|
376
366
|
def sxl_version
|
377
367
|
@site_settings['sxl_version']
|
378
368
|
end
|
data/lib/rsmp/tlc.rb
CHANGED
@@ -5,7 +5,7 @@ module RSMP
|
|
5
5
|
class TrafficController < Component
|
6
6
|
attr_reader :pos, :cycle_time
|
7
7
|
|
8
|
-
def initialize node:, id:, cycle_time:
|
8
|
+
def initialize node:, id:, cycle_time: 10
|
9
9
|
super node: node, id: id, grouped: true
|
10
10
|
@signal_groups = []
|
11
11
|
@detector_logics = []
|
@@ -625,13 +625,15 @@ module RSMP
|
|
625
625
|
class SignalGroup < Component
|
626
626
|
attr_reader :plan, :state
|
627
627
|
|
628
|
-
|
628
|
+
# plan is a string, with each character representing a signal phase at a particular second in the cycle
|
629
|
+
def initialize node:, id:, plan: nil
|
629
630
|
super node: node, id: id, grouped: false
|
630
631
|
@plan = plan
|
631
632
|
move 0
|
632
633
|
end
|
633
634
|
|
634
635
|
def get_state pos
|
636
|
+
return 'a' unless @plan # if no plan, use phase a, which means disabled/dark
|
635
637
|
if pos > @plan.length
|
636
638
|
'.'
|
637
639
|
else
|
data/lib/rsmp/version.rb
CHANGED
data/lib/rsmp.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emil Tin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-10-
|
11
|
+
date: 2021-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -203,7 +203,6 @@ files:
|
|
203
203
|
- documentation/message_distribution.md
|
204
204
|
- exe/rsmp
|
205
205
|
- lib/rsmp.rb
|
206
|
-
- lib/rsmp/alarm.rb
|
207
206
|
- lib/rsmp/archive.rb
|
208
207
|
- lib/rsmp/cli.rb
|
209
208
|
- lib/rsmp/collector.rb
|
@@ -255,7 +254,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
255
254
|
- !ruby/object:Gem::Version
|
256
255
|
version: '0'
|
257
256
|
requirements: []
|
258
|
-
rubygems_version: 3.2.
|
257
|
+
rubygems_version: 3.2.26
|
259
258
|
signing_key:
|
260
259
|
specification_version: 4
|
261
260
|
summary: RoadSide Message Protocol (RSMP) library.
|
data/lib/rsmp/alarm.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# RSMP Alarm. Manages the various states an alarm can be in.
|
2
|
-
|
3
|
-
module RSMP
|
4
|
-
class Alarm
|
5
|
-
|
6
|
-
def initialize code: code, blocked: blocked=false, suspended: suspended=false, acknowledged: acknowledged=false
|
7
|
-
@code = code
|
8
|
-
@code = code
|
9
|
-
@blocked = blocked
|
10
|
-
@suspended = suspended
|
11
|
-
@acknowledged = acknowledged
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|