rsmp 0.3.1 → 0.3.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a19b3e748ae4dff7c8f652f7015d8f0b798f78a3d8f07c545638724308f4c819
4
- data.tar.gz: 8353a6b756fa36f45b0c9e8cf33d56cb96f69ef30ab158ebf34ea2cc8a863122
3
+ metadata.gz: d22d8796a378484c9c7a9d50b3bc48386db2e12893c5af07a1ef83825d2f1b0e
4
+ data.tar.gz: ee6a4ebb4fcf094cb45e1f541e6f228e6ea9c3364fca6e1526e4fe46026751f2
5
5
  SHA512:
6
- metadata.gz: 23fb75e6bad681f67be2f04038a6bebec458c5e6e5c29ee5d5333dc5583b490ba8e1841e5304a88a384ac4761edea45818848f2144a97e73a31dbe2ca89090ed
7
- data.tar.gz: cc37d48a622961d41444631cb3543967ccbd926dfcf1314a45294c676270977272e842853a5e1f59a08f1706b26dd85a2494aaea1a12b5dced4917dbaaee9015
6
+ metadata.gz: a1a495ba2c110ebb42db60596516de255b9c9a9cb903fdd66bf77bd27a3f5d5b786b273436b522af3dbf57e983651676b9a9e67aee7387ba134ef89812261618
7
+ data.tar.gz: 21f2e48b596dcca6296da89f687ec46d3845eaafb6cad497a16ac4fabca1cb5574da6df324256f4929b7207eeccd17697bd5021b328b4d265ff7d836d2a5e2c3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.3.1)
4
+ rsmp (0.3.5)
5
5
  async (~> 1.29.1)
6
6
  async-io (~> 1.32.1)
7
7
  colorize (~> 0.8.1)
@@ -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
@@ -13,6 +13,7 @@ module RSMP
13
13
 
14
14
  def setup_components settings
15
15
  return unless settings
16
+ check_main_component settings
16
17
  settings.each_pair do |type,components_by_type|
17
18
  components_by_type.each_pair do |id,settings|
18
19
  @components[id] = build_component(id:id, type:type, settings:settings)
@@ -20,6 +21,15 @@ module RSMP
20
21
  end
21
22
  end
22
23
 
24
+ def check_main_component settings
25
+ unless settings['main'] && settings['main'].size >= 1
26
+ raise ConfigurationError.new("main component must be defined")
27
+ end
28
+ if settings['main'].size > 1
29
+ raise ConfigurationError.new("only one main component can be defined, found #{settings['main'].keys.join(', ')}")
30
+ end
31
+ end
32
+
23
33
  def add_component component
24
34
  @components[component.c_id] = component
25
35
  end
data/lib/rsmp/error.rb CHANGED
@@ -52,4 +52,7 @@ module RSMP
52
52
 
53
53
  class ConfigurationError < Error
54
54
  end
55
+
56
+ class RepeatedAlarmError < Error
57
+ end
55
58
  end
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 = Alarm.new attributes
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 AlarmRequest < Message
227
+ class AlarmIssue < Alarm
199
228
  def initialize attributes = {}
200
229
  super({
201
- "type" => "Alarm",
230
+ "aSp" => "Issue",
202
231
  }.merge attributes)
203
232
  end
204
233
  end
205
234
 
206
- class AlarmAcknowledged < Message
235
+ class AlarmRequest < Alarm
207
236
  def initialize attributes = {}
208
237
  super({
209
- "type" => "Alarm",
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
@@ -302,10 +307,18 @@ module RSMP
302
307
  end
303
308
  end
304
309
 
310
+ def should_validate_ingoing_message? message
311
+ return true unless @site_settings
312
+ skip = @site_settings.dig('skip_validation')
313
+ return true unless skip
314
+ klass = message.class.name.split('::').last
315
+ !skip.include?(klass)
316
+ end
317
+
305
318
  def process_packet json
306
319
  attributes = Message.parse_attributes json
307
320
  message = Message.build attributes, json
308
- message.validate get_schemas
321
+ message.validate(get_schemas) if should_validate_ingoing_message?(message)
309
322
  notify message
310
323
  expect_version_message(message) unless @version_determined
311
324
  process_message message
data/lib/rsmp/site.rb CHANGED
@@ -46,7 +46,11 @@ module RSMP
46
46
  }
47
47
  }
48
48
  }
49
-
49
+ # only one main component can be defined, so replace the default if options define one
50
+ if options.dig(:site_settings,'components','main')
51
+ defaults['components']['main'] = options[:site_settings]['components']['main']
52
+ end
53
+
50
54
  @site_settings = defaults.deep_merge options[:site_settings]
51
55
  check_sxl_version
52
56
  setup_components @site_settings['components']
@@ -79,7 +83,7 @@ module RSMP
79
83
 
80
84
  def aggregated_status_changed component, options={}
81
85
  @proxies.each do |proxy|
82
- proxy.send_aggregated_status component, options
86
+ proxy.send_aggregated_status component, options if proxy.ready?
83
87
  end
84
88
  end
85
89
 
@@ -148,11 +148,17 @@ module RSMP
148
148
  end
149
149
 
150
150
  def process_alarm message
151
+ component = find_component message.attribute("cId")
152
+ status = ["ack","aS","sS"].map { |key| message.attribute(key) }.join(',')
153
+ component.handle_alarm message
151
154
  alarm_code = message.attribute("aCId")
152
155
  asp = message.attribute("aSp")
153
- status = ["ack","aS","sS"].map { |key| message.attribute(key) }.join(',')
154
156
  log "Received #{message.type}, #{alarm_code} #{asp} [#{status}]", message: message, level: :log
155
157
  acknowledge message
158
+ rescue RSMP::RepeatedAlarmError => e
159
+ str = "Rejected #{message.type} message, "
160
+ dont_acknowledge message, str, "#{e}"
161
+ notify_error e.exception("#{str}#{e.message} #{message.json}")
156
162
  end
157
163
 
158
164
  def version_acknowledged
@@ -241,13 +247,8 @@ module RSMP
241
247
 
242
248
  def send_alarm_acknowledgement component, alarm_code, options={}
243
249
  message = RSMP::AlarmAcknowledged.new({
244
- "ntsOId" => '',
245
- "xNId" => '',
246
250
  "cId" => component,
247
251
  "aCId" => alarm_code,
248
- "xACId" => '',
249
- "xNACId" => '',
250
- "aSp" => 'Acknowledge'
251
252
  })
252
253
  send_message message, validate: options[:validate]
253
254
  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/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.5"
3
3
  end
data/lib/rsmp.rb CHANGED
@@ -18,7 +18,6 @@ require 'rsmp/node'
18
18
  require 'rsmp/supervisor'
19
19
  require 'rsmp/components'
20
20
  require 'rsmp/notifier'
21
-
22
21
  require 'rsmp/listener'
23
22
  require 'rsmp/collector'
24
23
  require 'rsmp/matcher'
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.1
4
+ version: 0.3.5
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-18 00:00:00.000000000 Z
11
+ date: 2021-10-22 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
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