rsmp 0.4.5 → 0.5.2

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: 3bc44d46482f9db419fd057094d14b4291231c572ca67722739e555d71524694
4
- data.tar.gz: 8363b9dc14cbd3b342f727a1343e16dac721faaa160e52f1d103f98dc3220e3c
3
+ metadata.gz: 9551219e8b4223f7d3fc615efe9a6e0c648b930c30e023426a4fafd60e15cdc8
4
+ data.tar.gz: 859c020b24d0065d692cbba2ae1cb8de4a3498a03cd6d888fbdf8dab88e90491
5
5
  SHA512:
6
- metadata.gz: d37d3d4b13f1f896287abaaa6a3deda07bae2e0e2fc6b612413ccf2937cd56531f42045b98f1ebe9ae64e7ce4bae6e13adec07bb3c767e967fd8bb0ddf069890
7
- data.tar.gz: e9806ea30d7747b421844264ad3ab0af79b98a2accc48299372a924a1adee001b6d4dc6f662e714e217d6c29b9aced77a4e0ddfdc7e3a111a7b38a2e2753ca7a
6
+ metadata.gz: 4d5817111ffefe2cef5bc11a66872ef473203eeacd12fbb59c2c001cdb461b8d53cb7965855449083bf7db7225a2390eac4d5f49227c9d8bafa9285a40332837
7
+ data.tar.gz: 85d4bea87373f4d65efd271877627d2be1eb43fc3c75368e312ab2942a3e8db99e512fd2be0351d1add466a43b87c3f8a5477ccb7d72ee9487dd932c43bbaca6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.4.5)
4
+ rsmp (0.5.2)
5
5
  async (~> 1.29.1)
6
6
  async-io (~> 1.32.1)
7
7
  colorize (~> 0.8.1)
@@ -19,6 +19,7 @@ log:
19
19
  text: true
20
20
  direction: true
21
21
  level: false
22
+ debug: true
22
23
  json: true
23
24
  acknowledgements: false
24
25
  watchdogs: false
data/config/tlc.yaml CHANGED
@@ -38,6 +38,7 @@ log:
38
38
  ip: false
39
39
  site_id: true
40
40
  level: false
41
+ debug: true
41
42
  text: true
42
43
  direction: true
43
44
  json: true
@@ -7,7 +7,12 @@ module RSMP
7
7
 
8
8
  def initialize proxy, options={}
9
9
  super proxy, options
10
- @options = options.clone
10
+ @options = {
11
+ cancel: {
12
+ schema_error: true,
13
+ disconnect: false,
14
+ }
15
+ }.deep_merge options
11
16
  @ingoing = options[:ingoing] == nil ? true : options[:ingoing]
12
17
  @outgoing = options[:outgoing] == nil ? false : options[:outgoing]
13
18
  @condition = Async::Notification.new
@@ -82,7 +87,7 @@ module RSMP
82
87
  if message.is_a?(MessageNotAck)
83
88
  if message.attribute('oMId') == @options[:m_id]
84
89
  m_id_short = RSMP::Message.shorten_m_id @options[:m_id], 8
85
- @error = RSMP::MessageRejected.new("#{@title} #{m_id_short} was rejected: #{message.attribute('rea')}")
90
+ @error = RSMP::MessageRejected.new("#{@title} #{m_id_short} was rejected with '#{message.attribute('rea')}'")
86
91
  complete
87
92
  end
88
93
  false
@@ -123,6 +128,43 @@ module RSMP
123
128
  @condition.signal
124
129
  end
125
130
 
131
+ # The proxy experienced some error.
132
+ # Check if this should cause us to cancel.
133
+ def notify_error error, options={}
134
+ case error
135
+ when RSMP::SchemaError
136
+ notify_schema_error error, options
137
+ when RSMP::ConnectionError
138
+ notify_disconnect error, options
139
+ end
140
+ end
141
+
142
+ # Cancel if we received e schema error for a message type we're collecting
143
+ def notify_schema_error error, options
144
+ return unless @options.dig(:cancel,:schema_error)
145
+ message = options[:message]
146
+ return unless message
147
+ klass = message.class.name.split('::').last
148
+ return unless [@options[:type]].flatten.include? klass
149
+ @proxy.log "Collect cancelled due to schema error in #{klass} #{message.m_id_short}", level: :debug
150
+ cancel error
151
+ end
152
+
153
+ # Cancel if we received e notificaiton about a disconnect
154
+ def notify_disconnect error, options
155
+ return unless @options.dig(:cancel,:disconnect)
156
+ @proxy.log "Collect cancelled due to a connection error: #{error.to_s}", level: :debug
157
+ cancel error
158
+ end
159
+
160
+ # Abort collection
161
+ def cancel error
162
+ @error = error if error
163
+ @done = false
164
+ @proxy.remove_listener self
165
+ @condition.signal
166
+ end
167
+
126
168
  # Store a message in the result array
127
169
  def keep message
128
170
  @messages << message
@@ -12,6 +12,9 @@ module RSMP
12
12
  def notify message
13
13
  end
14
14
 
15
+ def notify_error error, options={}
16
+ end
17
+
15
18
  def listen &block
16
19
  @proxy.add_listener self
17
20
  yield
@@ -102,6 +102,5 @@ module RSMP
102
102
  end
103
103
  @proxy.log "#{@title.capitalize} collect reached #{summary}", level: :debug
104
104
  end
105
-
106
105
  end
107
106
  end
@@ -12,6 +12,22 @@ module RSMP
12
12
 
13
13
  def initialize_distributor
14
14
  @listeners = []
15
+ @defer_notify = false
16
+ @notify_queue = []
17
+ end
18
+
19
+ def deferred_notify &block
20
+ was, @defer_notify = @defer_notify, true
21
+ yield
22
+ dequeue_notify
23
+ ensure
24
+ @defer_notify = was
25
+ end
26
+
27
+ def dequeue_notify
28
+ @notify_queue.each { |message| notify_without_defer message }
29
+ ensure
30
+ @notify_queue = []
15
31
  end
16
32
 
17
33
  def add_listener listener
@@ -25,7 +41,20 @@ module RSMP
25
41
  end
26
42
 
27
43
  def notify message
44
+ raise ArgumentError unless message
45
+ if @defer_notify
46
+ @notify_queue << message
47
+ else
48
+ notify_without_defer message
49
+ end
50
+ end
51
+
52
+ def notify_without_defer message
28
53
  @listeners.each { |listener| listener.notify message }
29
54
  end
55
+
56
+ def distribute_error error, options={}
57
+ @listeners.each { |listener| listener.notify_error error, options }
58
+ end
30
59
  end
31
60
  end
@@ -1,4 +1,9 @@
1
1
  module RSMP
2
+
3
+ # Class that represents an RMSP component.
4
+ # Currently this class is used by both SiteProxy and SupervisorProxy, and can
5
+ # therefore represent either a local or remote (proxy) component.
6
+
2
7
  class Component
3
8
  include Inspect
4
9
 
@@ -19,6 +24,7 @@ module RSMP
19
24
  @grouped = grouped
20
25
  @alarms = {}
21
26
  @statuses = {}
27
+ @subscribes = {}
22
28
  clear_aggregated_status
23
29
  end
24
30
 
@@ -83,5 +89,74 @@ module RSMP
83
89
  @alarms[code] = message
84
90
  end
85
91
  end
92
+
93
+ # Handle an incoming status respone, by storing the values
94
+ def handle_status_response message
95
+ store_status message, check_repeated: false
96
+ end
97
+
98
+ # Handle an incoming status update, by storing the values
99
+ def handle_status_update message
100
+ store_status message, check_repeated: true
101
+ end
102
+
103
+ # Our proxy subscribed to status updates
104
+ # Store update rates, so we can check for repeated alarm if we asked for updates only
105
+ # when there's a change, not on a regular interval.
106
+ # After subscribing, an update status us send regarless of whether values changes,
107
+ # and we store that.
108
+ def handle_status_subscribe status_list
109
+ status_list.each do |item|
110
+ sCI, n, uRt = item['sCI'], item['n'], item['uRt']
111
+
112
+ # record the update rate, so we can check for repeated status values if rate is zero
113
+ @subscribes[sCI] ||= {}
114
+ @subscribes[sCI][n] = {'uRt'=>uRt}
115
+
116
+ # record that we expect an upeate, even though the value might not change
117
+ @statuses[sCI] ||= {}
118
+ @statuses[sCI][n] ||= {}
119
+ @statuses[sCI][n][:initial] = true
120
+ end
121
+ #pp @subscribes
122
+ end
123
+
124
+ # Our proxy unsubscribed to status updates.
125
+ # Update our list of update rates.
126
+ def handle_status_unsubscribe status_list
127
+ status_list.each do |item|
128
+ sCI, n = item['sCI'], item['n']
129
+ if @subscribes[sCI]
130
+ @subscribes[sCI].delete n
131
+ end
132
+ if @subscribes[sCI].empty?
133
+ @subscribes.delete sCI
134
+ end
135
+
136
+ # remove any mark that would allow the next update to be a repeat
137
+ item = @statuses.dig sCI, n
138
+ item.delete(:initial) if item
139
+ end
140
+ end
141
+
142
+ # Store the latest status update values, optionally
143
+ # checking that we're not receiving unchanged values if we're subscribed
144
+ # wit updates only on change
145
+ def store_status message, check_repeated:
146
+ message.attribute('sS').each do |item|
147
+ sCI, n, s, q = item['sCI'], item['n'], item['s'], item['q']
148
+ uRt = @subscribes.dig(sCI,n,'uRt')
149
+ new_values = {'s'=>s,'q'=>q}
150
+ old_values = @statuses.dig(sCI,n)
151
+ if check_repeated && uRt.to_i == 0
152
+ if new_values == old_values
153
+ raise RSMP::RepeatedStatusError.new "no change for #{sCI} '#{n}'"
154
+ end
155
+ end
156
+ @statuses[sCI] ||= {}
157
+ @statuses[sCI][n] = new_values
158
+ end
159
+ end
160
+
86
161
  end
87
162
  end
data/lib/rsmp/error.rb CHANGED
@@ -32,6 +32,9 @@ module RSMP
32
32
  class FatalError < Error
33
33
  end
34
34
 
35
+ class HandshakeError < FatalError
36
+ end
37
+
35
38
  class NotReady < Error
36
39
  end
37
40
 
@@ -55,4 +58,7 @@ module RSMP
55
58
 
56
59
  class RepeatedAlarmError < Error
57
60
  end
61
+
62
+ class RepeatedStatusError < Error
63
+ end
58
64
  end
data/lib/rsmp/logger.rb CHANGED
@@ -5,6 +5,7 @@ module RSMP
5
5
 
6
6
  def initialize settings={}
7
7
  defaults = {
8
+ 'prefix'=>nil,
8
9
  'active'=>false,
9
10
  'path'=>nil,
10
11
  'stream'=>nil,
@@ -20,7 +21,8 @@ module RSMP
20
21
  'json'=>false,
21
22
  'debug'=>false,
22
23
  'statistics'=>false,
23
- 'hide_ip_and_port' => false
24
+ 'hide_ip_and_port' => false,
25
+ 'acknowledgements' => false
24
26
  }
25
27
  if settings
26
28
  @settings = defaults.merge settings
@@ -139,6 +141,7 @@ module RSMP
139
141
 
140
142
  def build_output item
141
143
  parts = []
144
+ parts << "#{@settings['prefix']} " if @settings['prefix']
142
145
  parts << item[:index].to_s.ljust(7) if @settings["index"] == true
143
146
  parts << item[:author].to_s.ljust(13) if @settings["author"] == true
144
147
  parts << Clock.to_s(item[:timestamp]).ljust(24) unless @settings["timestamp"] == false
data/lib/rsmp/message.rb CHANGED
@@ -142,7 +142,7 @@ module RSMP
142
142
  def validate schemas
143
143
  errors = RSMP::Schemer.validate attributes, schemas
144
144
  if errors
145
- error_string = errors.compact.join(', ').strip
145
+ error_string = errors.map {|item| item.reject {|e| e=='' } }.compact.join(', ').strip
146
146
  raise SchemaError.new error_string
147
147
  end
148
148
  end
data/lib/rsmp/proxy.rb CHANGED
@@ -86,6 +86,7 @@ module RSMP
86
86
  return if @state == :stopped
87
87
  set_state :stopping
88
88
  stop_tasks
89
+ notify_error ConnectionError.new("Connection was closed")
89
90
  ensure
90
91
  close_socket
91
92
  clear
@@ -237,6 +238,7 @@ module RSMP
237
238
  if now > latest
238
239
  log "No acknowledgements for #{message.type} #{message.m_id_short} within #{timeout} seconds", level: :error
239
240
  stop
241
+ notify_error MissingAcknowledgment.new('No ack')
240
242
  end
241
243
  end
242
244
  end
@@ -266,7 +268,7 @@ module RSMP
266
268
  # TODO
267
269
  # what schema should we use to validate the intial Version and MessageAck messages?
268
270
  schemas = { core: '3.1.5' }
269
- schemas[sxl] = RSMP::Schemer.sanitize_version(sxl_version) if sxl
271
+ schemas[sxl] = RSMP::Schemer.sanitize_version(sxl_version) if sxl && sxl_version
270
272
  schemas
271
273
  end
272
274
 
@@ -315,13 +317,23 @@ module RSMP
315
317
  !skip.include?(klass)
316
318
  end
317
319
 
320
+ def process_deferred
321
+ node.process_deferred
322
+ end
323
+
324
+ def verify_sequence message
325
+ expect_version_message(message) unless @version_determined
326
+ end
327
+
318
328
  def process_packet json
319
329
  attributes = Message.parse_attributes json
320
330
  message = Message.build attributes, json
321
331
  message.validate(get_schemas) if should_validate_ingoing_message?(message)
322
- notify message
323
- expect_version_message(message) unless @version_determined
324
- process_message message
332
+ verify_sequence message
333
+ deferred_notify do
334
+ notify message
335
+ process_message message
336
+ end
325
337
  process_deferred
326
338
  message
327
339
  rescue InvalidPacket => e
@@ -338,17 +350,17 @@ module RSMP
338
350
  rescue SchemaError, RSMP::Schemer::Error => e
339
351
  str = "Received invalid #{message.type}, schema errors: #{e.message}"
340
352
  log str, message: message, level: :warning
341
- notify_error e.exception("#{str} #{message.json}")
353
+ notify_error e.exception("#{str} #{message.json}"), message: message
342
354
  dont_acknowledge message, str
343
355
  message
344
356
  rescue InvalidMessage => e
345
357
  str = "Received", "invalid #{message.type}, #{e.message}"
346
- notify_error e.exception("#{str} #{message.json}")
358
+ notify_error e.exception("#{str} #{message.json}"), message: message
347
359
  dont_acknowledge message, str
348
360
  message
349
361
  rescue FatalError => e
350
362
  str = "Rejected #{message.type},"
351
- notify_error e.exception("#{str} #{message.json}")
363
+ notify_error e.exception("#{str} #{message.json}"), message: message
352
364
  dont_acknowledge message, str, "#{e.message}"
353
365
  stop
354
366
  message
@@ -402,7 +414,7 @@ module RSMP
402
414
  if candidates.any?
403
415
  @rsmp_version = candidates.sort_by { |v| Gem::Version.new(v) }.last # pick latest version
404
416
  else
405
- raise FatalError.new "RSMP versions [#{message.versions.join(',')}] requested, but only [#{versions.join(',')}] supported."
417
+ raise HandshakeError.new "RSMP versions [#{message.versions.join(',')}] requested, but only [#{versions.join(',')}] supported."
406
418
  end
407
419
  end
408
420
 
@@ -546,7 +558,7 @@ module RSMP
546
558
 
547
559
  def expect_version_message message
548
560
  unless message.is_a?(Version) || message.is_a?(MessageAck) || message.is_a?(MessageNotAck)
549
- raise FatalError.new "Version must be received first"
561
+ raise HandshakeError.new "Version must be received first"
550
562
  end
551
563
  end
552
564
 
@@ -578,7 +590,7 @@ module RSMP
578
590
  # will be raised in the parent task, and caught by rspec.
579
591
  # rspec will then show the error and record the test as failed
580
592
  m_id_short = RSMP::Message.shorten_m_id m_id, 8
581
- result = RSMP::MessageRejected.new "Aggregated status request #{m_id_short} was rejected: #{message.attribute('rea')}"
593
+ result = RSMP::MessageRejected.new "Aggregated status request #{m_id_short} was rejected with '#{message.attribute('rea')}'"
582
594
  next true # done, no more messages wanted
583
595
  end
584
596
  elsif message.is_a?(MessageAck)
@@ -587,6 +599,5 @@ module RSMP
587
599
  false
588
600
  end
589
601
  end
590
-
591
602
  end
592
603
  end
@@ -68,6 +68,10 @@ module RSMP
68
68
  else
69
69
  super message
70
70
  end
71
+ rescue RSMP::RepeatedAlarmError, RSMP::RepeatedStatusError => e
72
+ str = "Rejected #{message.type} message,"
73
+ dont_acknowledge message, str, "#{e}"
74
+ notify_error e.exception("#{str}#{e.message} #{message.json}")
71
75
  end
72
76
 
73
77
  def process_command_response message
@@ -75,10 +79,6 @@ module RSMP
75
79
  acknowledge message
76
80
  end
77
81
 
78
- def process_deferred
79
- supervisor.process_deferred
80
- end
81
-
82
82
  def version_accepted message
83
83
  log "Received Version message for site #{@site_id}", message: message, level: :log
84
84
  start_timer
@@ -149,10 +149,6 @@ module RSMP
149
149
  asp = message.attribute("aSp")
150
150
  log "Received #{message.type}, #{alarm_code} #{asp} [#{status}]", message: message, level: :log
151
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
152
  end
157
153
 
158
154
  def version_acknowledged
@@ -191,6 +187,8 @@ module RSMP
191
187
  end
192
188
 
193
189
  def process_status_response message
190
+ component = find_component message.attribute("cId")
191
+ component.handle_status_response message
194
192
  log "Received #{message.type}", message: message, level: :log
195
193
  acknowledge message
196
194
  end
@@ -202,7 +200,7 @@ module RSMP
202
200
  message
203
201
  end
204
202
 
205
- def subscribe_to_status component, status_list, options={}
203
+ def subscribe_to_status component_id, status_list, options={}
206
204
  validate_ready 'subscribe to status'
207
205
  m_id = options[:m_id] || RSMP::Message.make_m_id
208
206
 
@@ -210,10 +208,13 @@ module RSMP
210
208
  # but must to remove from the subscribe message
211
209
  subscribe_list = status_list.map { |item| item.slice('sCI','n','uRt') }
212
210
 
211
+ component = find_component component_id
212
+ component.handle_status_subscribe subscribe_list
213
+
213
214
  message = RSMP::StatusSubscribe.new({
214
215
  "ntsOId" => '',
215
216
  "xNId" => '',
216
- "cId" => component,
217
+ "cId" => component_id,
217
218
  "sS" => subscribe_list,
218
219
  'mId' => m_id
219
220
  })
@@ -222,12 +223,15 @@ module RSMP
222
223
  end
223
224
  end
224
225
 
225
- def unsubscribe_to_status component, status_list, options={}
226
+ def unsubscribe_to_status component_id, status_list, options={}
227
+ component = find_component component_id
228
+ component.handle_status_subscribe status_list
229
+
226
230
  validate_ready 'unsubscribe to status'
227
231
  message = RSMP::StatusUnsubscribe.new({
228
232
  "ntsOId" => '',
229
233
  "xNId" => '',
230
- "cId" => component,
234
+ "cId" => component_id,
231
235
  "sS" => status_list
232
236
  })
233
237
  send_message message, validate: options[:validate]
@@ -235,6 +239,8 @@ module RSMP
235
239
  end
236
240
 
237
241
  def process_status_update message
242
+ component = find_component message.attribute("cId")
243
+ component.handle_status_update message
238
244
  log "Received #{message.type}", message: message, level: :log
239
245
  acknowledge message
240
246
  end
@@ -333,6 +339,7 @@ module RSMP
333
339
 
334
340
  def notify_error e, options={}
335
341
  @supervisor.notify_error e, options if @supervisor
342
+ distribute_error e, options
336
343
  end
337
344
 
338
345
  def collect_alarms parent_task, options={}
@@ -7,7 +7,7 @@ module RSMP
7
7
  attr_reader :rsmp_versions, :site_id, :supervisor_settings, :proxies, :logger
8
8
 
9
9
  def initialize options={}
10
- handle_supervisor_settings options[:supervisor_settings]
10
+ handle_supervisor_settings( options[:supervisor_settings] || {} )
11
11
  super options
12
12
  @proxies = []
13
13
  @site_id_condition = Async::Notification.new
@@ -17,7 +17,7 @@ module RSMP
17
17
  @supervisor_settings['site_id']
18
18
  end
19
19
 
20
- def handle_supervisor_settings supervisor_settings={}
20
+ def handle_supervisor_settings supervisor_settings
21
21
  defaults = {
22
22
  'port' => 12111,
23
23
  'ips' => 'all',
@@ -172,7 +172,11 @@ module RSMP
172
172
  id = peek_version_message protocol
173
173
  proxy = find_site id
174
174
  if proxy
175
- proxy.revive settings
175
+ if proxy.connected?
176
+ raise ConnectionError.new("Site #{id} alredy connected from port #{proxy.port}")
177
+ else
178
+ proxy.revive settings
179
+ end
176
180
  else
177
181
  check_max_sites
178
182
  proxy = build_proxy settings.merge(site_id:id) # keep the id learned by peeking above
@@ -246,7 +250,7 @@ module RSMP
246
250
 
247
251
  def check_site_already_connected site_id
248
252
  site = find_site(site_id)
249
- raise FatalError.new "Site '#{site_id}' already connected" if site != nil && site != self
253
+ raise HandshakeError.new "Site '#{site_id}' already connected" if site != nil && site != self
250
254
  end
251
255
 
252
256
  def site_id_to_site_setting site_id
@@ -256,7 +260,7 @@ module RSMP
256
260
  return settings
257
261
  end
258
262
  end
259
- raise FatalError.new "site id #{site_id} unknown"
263
+ raise HandshakeError.new "site id #{site_id} unknown"
260
264
  end
261
265
 
262
266
  def ip_to_site_settings ip
@@ -86,10 +86,6 @@ module RSMP
86
86
  dont_acknowledge message, '', e.to_s
87
87
  end
88
88
 
89
- def process_deferred
90
- site.process_deferred
91
- end
92
-
93
89
  def acknowledged_first_ingoing message
94
90
  # TODO
95
91
  # aggregateds status should only be send for later version of rsmp
@@ -229,7 +225,6 @@ module RSMP
229
225
  def process_status_subcribe message
230
226
  log "Received #{message.type}", message: message, level: :log
231
227
 
232
-
233
228
  # @status_subscriptions is organized by component/code/name, for example:
234
229
  #
235
230
  # {"AA+BBCCC=DDDEE002"=>{"S001"=>["number"]}}
@@ -238,21 +233,14 @@ module RSMP
238
233
  # for each component, containing all the requested statuses
239
234
 
240
235
  update_list = {}
241
-
242
236
  component = message.attributes["cId"]
243
-
244
237
  @status_subscriptions[component] ||= {}
245
238
  update_list[component] ||= {}
246
-
247
- subs = @status_subscriptions[component]
248
239
  now = Time.now # internal timestamp
249
240
 
250
241
  message.attributes["sS"].each do |arg|
251
242
  sCI = arg["sCI"]
252
243
  subcription = {interval: arg["uRt"].to_i, last_sent_at: now}
253
- subs[sCI] ||= {}
254
- subs[sCI][arg["n"]] = subcription
255
-
256
244
  update_list[component][sCI] ||= []
257
245
  update_list[component][sCI] << arg["n"]
258
246
  end
@@ -291,11 +279,15 @@ module RSMP
291
279
  end
292
280
  end
293
281
 
294
- def store_last_sent_status component, code, name, value
282
+ def store_last_sent_status message
283
+ component_id = message.attribute('cId')
295
284
  @last_status_sent ||= {}
296
- @last_status_sent[component] ||= {}
297
- @last_status_sent[component][code] ||= {}
298
- @last_status_sent[component][code][name] = value
285
+ @last_status_sent[component_id] ||= {}
286
+ message.attribute('sS').each do |item|
287
+ sCI, n, s = item['sCI'], item['n'], item['s']
288
+ @last_status_sent[component_id][sCI] ||= {}
289
+ @last_status_sent[component_id][sCI][n] = s
290
+ end
299
291
  end
300
292
 
301
293
  def status_update_timer now
@@ -316,7 +308,6 @@ module RSMP
316
308
  last_sent = fetch_last_sent_status component, code, name
317
309
  if current != last_sent
318
310
  should_send = true
319
- store_last_sent_status component, code, name, current
320
311
  end
321
312
  else
322
313
  # send at regular intervals
@@ -360,6 +351,7 @@ module RSMP
360
351
  "sS"=>sS
361
352
  })
362
353
  send_message update
354
+ store_last_sent_status update
363
355
  end
364
356
  end
365
357
 
data/lib/rsmp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.4.5"
2
+ VERSION = "0.5.2"
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.4.5
4
+ version: 0.5.2
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-11-01 00:00:00.000000000 Z
11
+ date: 2021-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async