rsmp 0.12.2 → 0.13.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 34c922ce1e22f31aabc3b476f1aa3d9a6eeaa4b89e4550255f237c5f5810b4e8
4
- data.tar.gz: 95590c49d1ba70af34dfd913808239cea39b5dae0324003deb921c21a0bf0aa2
3
+ metadata.gz: c1840c079564613302ef539e2c0a502c2cafdabe8c875ab2dfb3b389470becf8
4
+ data.tar.gz: 35eda6efcfabe4624ba58d5150b3c1263a34a2a0b1f363b1a704566acc65cfed
5
5
  SHA512:
6
- metadata.gz: 3d1c8bfd469ae45764292bf3e2615bf95b1904229d34c2df0eb18ad496a7d1b6ecfd0aeff594f07a0bbf59c34d7b6247fc566e1a94d65412f78719e3f4f42b1b
7
- data.tar.gz: 66edc8044373bca92cc52641f49c78f3336d4e5c6caa8615a8da05aad6176d8e2c6161a5d835716fe7feac38948a059b4de6ec1f772de3c1f992d8c7f76bc8e0
6
+ metadata.gz: 32c6bb82731643e24000e2056a19896fa591755b1336ccad74df28b82ee9800cdb16ee96e6d6e1996e09137fa22cfed5c64801d8b131953a4abc94d32ba9ab08
7
+ data.tar.gz: d588d1e92eb16473ee86e25e0a595d6bd03c4744f113860bbe89be6f3c3df6ab19bb522daea617f28e8b32708a048d4a2895700cda8de34fed6fd986de85c6a4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.12.2)
4
+ rsmp (0.13.1)
5
5
  async (~> 1.29.1)
6
6
  async-io (~> 1.32.2)
7
7
  colorize (~> 0.8.1)
@@ -68,7 +68,7 @@ GEM
68
68
  ffi (1.15.5-x64-mingw32)
69
69
  fiber-local (1.0.0)
70
70
  hana (1.3.7)
71
- json_schemer (0.2.19)
71
+ json_schemer (0.2.20)
72
72
  ecma-re-validator (~> 0.3)
73
73
  hana (~> 1.3)
74
74
  regexp_parser (~> 2.0)
@@ -79,8 +79,8 @@ GEM
79
79
  multi_test (0.1.2)
80
80
  nio4r (2.5.8)
81
81
  rake (13.0.6)
82
- regexp_parser (2.2.1)
83
- rsmp_schemer (0.3.2)
82
+ regexp_parser (2.3.1)
83
+ rsmp_schemer (0.4.0)
84
84
  json_schemer (~> 0.2.18)
85
85
  rspec (3.10.0)
86
86
  rspec-core (~> 3.10.0)
@@ -1,33 +1,94 @@
1
1
  module RSMP
2
2
  # class that tracks the state of an alarm
3
3
  class AlarmState
4
- attr_reader :component_id, :code, :acknowledged, :suspended, :active, :timestamp, :category, :priority
4
+ attr_reader :component_id, :code, :acknowledged, :suspended, :active, :timestamp, :category, :priority, :rvs
5
5
 
6
- def initialize component_id:, code:
7
- @component_id = component_id
6
+ def initialize component:, code:
7
+ @component = component
8
+ @component_id = component.c_id
8
9
  @code = code
10
+ @suspended = false
9
11
  @acknowledged = false
10
12
  @suspended = false
11
13
  @active = false
12
14
  @timestamp = nil
13
- @category = nil
14
- @priority = nil
15
+ @category = 'D'
16
+ @priority = 2
17
+ @rvs = []
15
18
  end
16
19
 
17
20
  def suspend
18
- @suspended = true
21
+ change, @suspended = !@suspended, true
22
+ update_timestamp if change
23
+ change
19
24
  end
20
25
 
21
26
  def resume
22
- @suspended = false
27
+ change, @suspended = @suspended, false
28
+ update_timestamp if change
29
+ change
23
30
  end
24
31
 
25
32
  def activate
26
- @active = true
33
+ change, @active = !@active, true
34
+ update_timestamp if change
35
+ change
27
36
  end
28
37
 
29
38
  def deactivate
30
- @active = false
39
+ change, @active = @active, false
40
+ update_timestamp if change
41
+ change
42
+ end
43
+
44
+ def update_timestamp
45
+ @timestamp = @component.node.clock.now
46
+ end
47
+
48
+ def to_message specialization:
49
+ Alarm.new(
50
+ 'cId' => @component_id,
51
+ 'aSp' => specialization,
52
+ 'aCId' => @code,
53
+ 'aTs' => Clock.to_s(@timestamp),
54
+ 'ack' => (@acknowledged ? 'Acknowledged' : 'notAcknowledged'),
55
+ 'sS' => (@suspended ? 'suspended' : 'notSuspended'),
56
+ 'aS' => (@active ? 'Active' : 'inActive'),
57
+ 'cat' => @category,
58
+ 'pri' => @priority.to_s,
59
+ 'rvs' => @rvs
60
+ )
31
61
  end
62
+
63
+ def differ_from_message? message
64
+ return true if @timestamp != message.attribute('aTs')
65
+ return true if message.attribute('ack') && @acknowledged != (message.attribute('ack') == 'True')
66
+ return true if message.attribute('sS') && @suspended != (message.attribute('sS') == 'True')
67
+ return true if message.attribute('aS') && @active != (message.attribute('aS') == 'True')
68
+ return true if message.attribute('cat') && @category != message.attribute('cat')
69
+ return true if message.attribute('pri') && @priority != message.attribute('pri').to_i
70
+ #return true @rvs = message.attribute('rvs')
71
+ false
72
+ end
73
+
74
+ # update from rsmp message
75
+ # component id, alarm code and specialization are not updated
76
+ def update_from_message message
77
+ unless differ_from_message? message
78
+ raise RepeatedAlarmError.new("no changes from previous alarm #{message.m_id_short}")
79
+ end
80
+ if Time.parse(message.attribute('aTs')) < Time.parse(message.attribute('aTs'))
81
+ raise TimestampError.new("timestamp is earlier than previous alarm #{message.m_id_short}")
82
+ end
83
+ ensure
84
+ @timestamp = message.attribute('aTs')
85
+ @acknowledged = message.attribute('ack') == 'True'
86
+ @suspended = message.attribute('sS') == 'True'
87
+ @active = message.attribute('aS') == 'True'
88
+ @category = message.attribute('cat')
89
+ @priority = message.attribute('pri').to_i
90
+ @rvs = message.attribute('rvs')
91
+ end
92
+
32
93
  end
33
94
  end
@@ -1,7 +1,5 @@
1
1
  module RSMP
2
-
3
2
  # RSMP component
4
-
5
3
  class Component < ComponentBase
6
4
  def initialize node:, id:, grouped: false
7
5
  super
@@ -15,40 +13,38 @@ module RSMP
15
13
  raise UnknownStatus.new "Status #{status_code}/#{status_name} not implemented by #{self.class}"
16
14
  end
17
15
 
18
- def get_alarm_state alarm_code
19
- alarm = @alarms[alarm_code] ||= RSMP::AlarmState.new component_id: c_id, code: alarm_code
20
- end
21
-
22
16
  def suspend_alarm alarm_code
23
17
  alarm = get_alarm_state alarm_code
24
- return if alarm.suspended
25
- log "Suspending alarm #{alarm_code}", level: :info
26
- alarm.suspend
27
- @node.alarm_changed alarm
18
+ if alarm.suspend
19
+ log "Suspending alarm #{alarm_code}", level: :info
20
+ @node.alarm_suspended_or_resumed alarm
21
+ else
22
+ log "Alarm #{alarm_code} already suspended", level: :info
23
+ end
28
24
  end
29
25
 
30
26
  def resume_alarm alarm_code
31
27
  alarm = get_alarm_state alarm_code
32
- return unless alarm.suspended
33
- log "Resuming alarm #{alarm_code}", level: :info
34
- alarm.resume
35
- @node.alarm_changed alarm
28
+ if alarm.resume
29
+ log "Resuming alarm #{alarm_code}", level: :info
30
+ @node.alarm_suspended_or_resumed alarm
31
+ else
32
+ log "Alarm #{alarm_code} already resumed", level: :info
33
+ end
36
34
  end
37
35
 
38
36
  def activate_alarm alarm_code
39
37
  alarm = get_alarm_state alarm_code
40
- return if alarm.active
38
+ return unless alarm.activate
41
39
  log "Activating alarm #{alarm_code}", level: :info
42
- alarm.activate
43
- @node.alarm_changed alarm
40
+ @node.alarm_activated_or_deactivated alarm
44
41
  end
45
42
 
46
43
  def deactivate_alarm alarm_code
47
44
  alarm = get_alarm_state alarm_code
48
- return unless alarm.active
45
+ return unless alarm.deactivate
49
46
  log "Deactivating alarm #{alarm_code}", level: :info
50
- alarm.deactivate
51
- @node.alarm_changed alarm
47
+ @node.alarm_activated_or_deactivated alarm
52
48
  end
53
49
  end
54
50
  end
@@ -20,8 +20,12 @@ module RSMP
20
20
  @c_id = id
21
21
  @node = node
22
22
  @grouped = grouped
23
- @alarms = {}
24
23
  clear_aggregated_status
24
+ @alarms = {}
25
+ end
26
+
27
+ def get_alarm_state alarm_code
28
+ alarm = @alarms[alarm_code] ||= RSMP::AlarmState.new component: self, code: alarm_code
25
29
  end
26
30
 
27
31
  def clear_aggregated_status
@@ -1,10 +1,9 @@
1
1
  module RSMP
2
-
3
2
  # A proxy to a remote RSMP component.
4
-
5
3
  class ComponentProxy < ComponentBase
6
4
  def initialize node:, id:, grouped: false
7
5
  super
6
+ @alarms = {}
8
7
  @statuses = {}
9
8
  @allow_repeat_updates = {}
10
9
  end
@@ -45,23 +44,12 @@ module RSMP
45
44
  @allow_repeat_updates[sCI].delete(n) if @allow_repeat_updates[sCI]
46
45
  end
47
46
  end
48
-
47
+
49
48
  # handle incoming alarm
50
49
  def handle_alarm message
51
- # code = message.attribute('aCId')
52
- # previous = @alarms[code]
53
- # if previous
54
- # unless message.differ?(previous)
55
- # raise RepeatedAlarmError.new("no changes from previous alarm #{previous.m_id_short}")
56
- # end
57
- # if Time.parse(message.attribute('aTs')) < Time.parse(previous.attribute('aTs'))
58
- # raise TimestampError.new("timestamp is earlier than previous alarm #{previous.m_id_short}")
59
- # end
60
- # end
61
- # p message
62
- # ensure
63
- # @alarms[code] = message
50
+ code = message.attribute('aCId')
51
+ alarm = get_alarm_state code
52
+ alarm.update_from_message message
64
53
  end
65
-
66
- end
54
+ end
67
55
  end
data/lib/rsmp/message.rb CHANGED
@@ -68,7 +68,13 @@ module RSMP
68
68
  when /Acknowledge/i
69
69
  AlarmAcknowledged.new attributes
70
70
  when /Suspend/i
71
- AlarmSuspend.new attributes
71
+ if attributes['sS'] =~ /suspended/i
72
+ AlarmSuspended.new attributes
73
+ elsif attributes['sS'] =~ /notSuspended/i
74
+ AlarmResumed.new attributes
75
+ else
76
+ AlarmSuspend.new attributes
77
+ end
72
78
  when /Resume/i
73
79
  AlarmResume.new attributes
74
80
  else
@@ -264,7 +270,23 @@ module RSMP
264
270
  end
265
271
  end
266
272
 
273
+ class AlarmSuspended < Alarm
274
+ def initialize attributes = {}
275
+ super({
276
+ "aSp" => "Suspend",
277
+ "sS" => "suspended"
278
+ }.merge attributes)
279
+ end
280
+ end
267
281
 
282
+ class AlarmResumed < Alarm
283
+ def initialize attributes = {}
284
+ super({
285
+ "aSp" => "Suspend",
286
+ "sS" => "notSuspended"
287
+ }.merge attributes)
288
+ end
289
+ end
268
290
 
269
291
  class Watchdog < Message
270
292
  def initialize attributes = {}
data/lib/rsmp/site.rb CHANGED
@@ -93,23 +93,31 @@ module RSMP
93
93
  end
94
94
  end
95
95
 
96
- def alarm_state_to_message alarm_state
97
- Alarm.new(
96
+ def alarm_state_to_hash alarm_state
97
+ {
98
98
  'cId' => alarm_state.component_id,
99
- 'aTs' => clock.to_s,
100
99
  'aCId' => alarm_state.code,
101
- 'aSp' => (alarm_state.suspended ? 'Suspend' : 'Issue'),
100
+ 'aTs' => Clock.to_s(alarm_state.timestamp),
102
101
  'ack' => (alarm_state.acknowledged ? 'Acknowledged' : 'notAcknowledged'),
103
102
  'sS' => (alarm_state.suspended ? 'suspended' : 'notSuspended'),
104
103
  'aS' => (alarm_state.active ? 'Active' : 'inActive'),
105
- 'cat' => (alarm_state.category || 'D'),
106
- 'pri' => (alarm_state.priority || '2'),
107
- 'rvs' => []
108
- )
104
+ 'cat' => alarm_state.category,
105
+ 'pri' => alarm_state.priority.to_s,
106
+ 'rvs' => alarm_state.rvs
107
+ }
108
+ end
109
+
110
+ def alarm_suspended_or_resumed alarm_state
111
+ alarm = AlarmIssue.new( alarm_state_to_hash(alarm_state).merge('aSp' => 'Suspend') )
112
+ send_alarm alarm
113
+ end
114
+
115
+ def alarm_activated_or_deactivated alarm_state
116
+ alarm = AlarmIssue.new( alarm_state_to_hash(alarm_state).merge('aSp' => 'Issue') )
117
+ send_alarm alarm
109
118
  end
110
119
 
111
- def alarm_changed alarm_state
112
- alarm = alarm_state_to_message alarm_state
120
+ def send_alarm alarm
113
121
  @proxies.each do |proxy|
114
122
  proxy.send_message alarm if proxy.ready?
115
123
  end
@@ -63,7 +63,7 @@ module RSMP
63
63
  process_aggregated_status message
64
64
  when AggregatedStatusRequest
65
65
  will_not_handle message
66
- when Alarm
66
+ when AlarmIssue, AlarmSuspended, AlarmResumed
67
67
  process_alarm message
68
68
  when CommandResponse
69
69
  process_command_response message
@@ -116,8 +116,8 @@ module RSMP
116
116
  m_id = options[:m_id] || RSMP::Message.make_m_id
117
117
 
118
118
  message = RSMP::AggregatedStatusRequest.new({
119
- "ntsOId" => '',
120
- "xNId" => '',
119
+ "ntsOId" => @ntsOId,
120
+ "xNId" => @xNId,
121
121
  "cId" => component,
122
122
  "mId" => m_id
123
123
  })
@@ -187,8 +187,8 @@ module RSMP
187
187
  request_list = status_list.map { |item| item.slice('sCI','n') }
188
188
 
189
189
  message = RSMP::StatusRequest.new({
190
- "ntsOId" => '',
191
- "xNId" => '',
190
+ "ntsOId" => @ntsOId,
191
+ "xNId" => @xNId,
192
192
  "cId" => component,
193
193
  "sS" => request_list,
194
194
  "mId" => m_id
@@ -232,8 +232,8 @@ module RSMP
232
232
  component.allow_repeat_updates subscribe_list
233
233
 
234
234
  message = RSMP::StatusSubscribe.new({
235
- "ntsOId" => '',
236
- "xNId" => '',
235
+ "ntsOId" => @ntsOId,
236
+ "xNId" => @xNId,
237
237
  "cId" => component_id,
238
238
  "sS" => subscribe_list,
239
239
  'mId' => m_id
@@ -262,8 +262,8 @@ module RSMP
262
262
  end
263
263
 
264
264
  message = RSMP::StatusUnsubscribe.new({
265
- "ntsOId" => '',
266
- "xNId" => '',
265
+ "ntsOId" => @ntsOId,
266
+ "xNId" => @xNId,
267
267
  "cId" => component_id,
268
268
  "sS" => status_list
269
269
  })
@@ -292,8 +292,8 @@ module RSMP
292
292
  validate_ready 'send command'
293
293
  m_id = options[:m_id] || RSMP::Message.make_m_id
294
294
  message = RSMP::CommandRequest.new({
295
- "ntsOId" => '',
296
- "xNId" => '',
295
+ "ntsOId" => @ntsOId,
296
+ "xNId" => @xNId,
297
297
  "cId" => component,
298
298
  "arg" => command_list,
299
299
  "mId" => m_id
@@ -369,6 +369,8 @@ module RSMP
369
369
  @site_settings = find_site_settings @site_id
370
370
  if @site_settings
371
371
  @sxl = @site_settings['sxl']
372
+ @ntsOId = @site_settings['ntsOId']
373
+ @xNId = @site_settings['xNId']
372
374
  setup_components @site_settings['components']
373
375
  else
374
376
  dont_acknowledge message, 'Rejected', "No config found for site #{@site_id}"
@@ -15,6 +15,8 @@ module RSMP
15
15
  @port = options[:port]
16
16
  @status_subscriptions = {}
17
17
  @sxl = @site_settings['sxl']
18
+ @ntsOId = @site_settings['ntsOId']
19
+ @xNId = @site_settings['xNId']
18
20
  @synthetic_id = Supervisor.build_id_from_ip_port @ip, @port
19
21
  end
20
22
 
@@ -105,7 +107,7 @@ module RSMP
105
107
  process_status_subcribe message
106
108
  when StatusUnsubscribe
107
109
  process_status_unsubcribe message
108
- when AlarmAcknowledged, AlarmSuspend, AlarmResume, AlarmRequest
110
+ when Alarm, AlarmAcknowledged, AlarmSuspend, AlarmResume, AlarmRequest
109
111
  process_alarm message
110
112
  else
111
113
  super message
@@ -160,6 +162,8 @@ module RSMP
160
162
  "se" => component.aggregated_status_bools,
161
163
  "mId" => m_id,
162
164
  })
165
+ message.attributes['ntsOId'] = @site_settings['ntsOId'] if @site_settings['ntsOId']
166
+ message.attributes['xNId'] = @site_settings['xNId'] if @site_settings['xNId']
163
167
 
164
168
  send_and_optionally_collect message, options do |collect_options|
165
169
  Collector.new self, collect_options.merge(task:@task, type: 'MessageAck')
data/lib/rsmp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.12.2"
2
+ VERSION = "0.13.1"
3
3
  end
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.12.2
4
+ version: 0.13.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emil Tin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-04-01 00:00:00.000000000 Z
11
+ date: 2022-04-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async