rsmp 0.12.1 → 0.13.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 278c4df55b2efbff06abd016ab49e09e6dec047cf873ad77a73346d7de08c54f
4
- data.tar.gz: bbd4ee23b200713574c483461be11116c35b7f08be0000e3eb008dbdf7c2c224
3
+ metadata.gz: 39bc5e9f248ab2db6d21e7a3c1e7c9e5ccb7c72e6e2be09dd28cbbaf5f6225d4
4
+ data.tar.gz: 3215d99759e3fb98f97c591ff9c9a3b2f1b1080306284b50429c46b0f677b137
5
5
  SHA512:
6
- metadata.gz: 8373359d1b9401273e6b71cadb0f5eb634c40239bc1054c0602c92fe5de9d1ca70cbd307362278f802369201f68e4d6702c5f962124d88fe9ec80c1cbb1513a9
7
- data.tar.gz: a20bd432dd787c6b50b507dde36b76aff0592fd9a8f97126ab2ce5684c2f8209c8402fd500e9a67e075b99ec35e388abafec40761e59724eb6a4fdd56ceec868
6
+ metadata.gz: 3f1be038f5bee13b83ecc2a5fe9ca79ae4e06ee906aa00d9766874193a24b12bda38752041c8e8fe1436aa98f93f026d9fcd0afbdfcf1b9366e0531a8d5c48f8
7
+ data.tar.gz: c52b47df3b59b30271c81b71b902fb55e2674de58c36e7458df091e39f1158641b98dcf94c840f8ab4673c35b7484b08770c0c8db1de30647f90df38ad590c34
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.12.1)
4
+ rsmp (0.13.0)
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)
@@ -80,7 +80,7 @@ GEM
80
80
  nio4r (2.5.8)
81
81
  rake (13.0.6)
82
82
  regexp_parser (2.2.1)
83
- rsmp_schemer (0.3.2)
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,25 +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
30
+ end
31
+
32
+ def activate
33
+ change, @active = !@active, true
34
+ update_timestamp if change
35
+ change
36
+ end
37
+
38
+ def deactivate
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
23
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
+ )
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
+
24
93
  end
25
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,36 +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
- alarm_state = get_alarm_state alarm_code
24
- if alarm.suspended == false
17
+ alarm = get_alarm_state alarm_code
18
+ if alarm.suspend
25
19
  log "Suspending alarm #{alarm_code}", level: :info
26
- alarm.suspend
27
20
  @node.alarm_suspended_or_resumed alarm
28
21
  else
29
22
  log "Alarm #{alarm_code} already suspended", level: :info
30
- end
23
+ end
31
24
  end
32
25
 
33
26
  def resume_alarm alarm_code
34
- alarm_state = get_alarm_state alarm_code
35
- if alarm.suspended
27
+ alarm = get_alarm_state alarm_code
28
+ if alarm.resume
36
29
  log "Resuming alarm #{alarm_code}", level: :info
37
- alarm.resume
38
30
  @node.alarm_suspended_or_resumed alarm
39
31
  else
40
- log "Alarm #{alarm_code} not suspended", level: :info
32
+ log "Alarm #{alarm_code} already resumed", level: :info
41
33
  end
42
34
  end
43
35
 
44
- # send alarm
45
- def send_alarm code:, status:
46
- @node.alarm_changed self, alarm
36
+ def activate_alarm alarm_code
37
+ alarm = get_alarm_state alarm_code
38
+ return unless alarm.activate
39
+ log "Activating alarm #{alarm_code}", level: :info
40
+ @node.alarm_activated_or_deactivated alarm
47
41
  end
48
42
 
43
+ def deactivate_alarm alarm_code
44
+ alarm = get_alarm_state alarm_code
45
+ return unless alarm.deactivate
46
+ log "Deactivating alarm #{alarm_code}", level: :info
47
+ @node.alarm_activated_or_deactivated alarm
48
+ end
49
49
  end
50
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
+ }
109
108
  end
110
109
 
111
110
  def alarm_suspended_or_resumed alarm_state
112
- alarm = alarm_state_to_message 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
118
+ end
119
+
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
@@ -105,7 +105,7 @@ module RSMP
105
105
  process_status_subcribe message
106
106
  when StatusUnsubscribe
107
107
  process_status_unsubcribe message
108
- when AlarmAcknowledged, AlarmSuspend, AlarmResume, AlarmRequest
108
+ when Alarm, AlarmAcknowledged, AlarmSuspend, AlarmResume, AlarmRequest
109
109
  process_alarm message
110
110
  else
111
111
  super message
@@ -264,10 +264,10 @@ module RSMP
264
264
  alarm_code = actions['raise']
265
265
  if change
266
266
  log "Activating alarm #{alarm_code}, because input #{input} was activated", level: :info
267
- send_alarm code:alarm_code, status:'Active'
267
+ activate_alarm alarm_code
268
268
  else
269
269
  log "Deactivating alarm #{alarm_code}, because input #{input} was deactivated", level: :info
270
- send_alarm code:alarm_code, status:'inActive'
270
+ deactivate_alarm alarm_code
271
271
  end
272
272
  end
273
273
  end
data/lib/rsmp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.12.1"
2
+ VERSION = "0.13.0"
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.1
4
+ version: 0.13.0
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-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async