Module: RSMP::SupervisorProxy::Modules::Status

Included in:
RSMP::SupervisorProxy
Defined in:
lib/rsmp/proxy/supervisor/modules/status.rb

Overview

Status request and subscription handling

Instance Method Summary collapse

Instance Method Details

#add_status_subscription(component_id, subs, update_list, arg, now) ⇒ Object



53
54
55
56
57
58
59
60
61
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 53

def add_status_subscription(component_id, subs, update_list, arg, now)
  sci = arg['sCI']
  name = arg['n']
  subcription = { interval: arg['uRt'].to_i, last_sent_at: now }
  subs[sci] ||= {}
  subs[sci][name] = subcription
  update_list[component_id][sci] ||= []
  update_list[component_id][sci] << name
end

#build_status_list(component, by_code) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 167

def build_status_list(component, by_code)
  ss = []
  by_code.each_pair do |code, names|
    names.map do |status_name, value|
      if value
        quality = 'recent'
      else
        value, quality = component.get_status code, status_name
      end
      ss << { 'sCI' => code,
              'n' => status_name,
              's' => rsmpify_value(value, quality),
              'q' => quality }
    end
  end
  ss
end

#build_undefined_statuses(args) ⇒ Object



23
24
25
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 23

def build_undefined_statuses(args)
  args.map { |arg| arg.dup.merge('q' => 'undefined', 's' => nil) }
end

#check_on_change_update(subscription, component, code, name) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 121

def check_on_change_update(subscription, component, code, name)
  return [nil, false] unless subscription[:interval].zero?

  current = nil
  if component
    current, quality = *(component.get_status code, name)
    current = rsmpify_value(current, quality)
  end
  last_sent = fetch_last_sent_status component.c_id, code, name
  [current, current != last_sent]
end

#check_status_subscription(subscription, component, code, name, now) ⇒ Object



139
140
141
142
143
144
145
146
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 139

def check_status_subscription(subscription, component, code, name, now)
  current, should_send = check_on_change_update(subscription, component, code, name)
  should_send ||= interval_update_due?(subscription, now)
  return [nil, false] unless should_send

  subscription[:last_sent_at] = now
  [current, true]
end

#fetch_last_sent_status(component, code, name) ⇒ Object



104
105
106
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 104

def fetch_last_sent_status(component, code, name)
  @last_status_sent&.dig component, code, name
end

#fetch_status_values(component, args) ⇒ Object



16
17
18
19
20
21
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 16

def fetch_status_values(component, args)
  args.map do |arg|
    value, quality = component.get_status arg['sCI'], arg['n'], { sxl_version: sxl_version }
    { 's' => rsmpify_value(value, quality), 'q' => quality.to_s }.merge arg
  end
end

#get_status_subscribe_interval(component_id, sci, name) ⇒ Object



80
81
82
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 80

def get_status_subscribe_interval(component_id, sci, name)
  @status_subscriptions.dig component_id, sci, name
end

#interval_update_due?(subscription, now) ⇒ Boolean

Returns:

  • (Boolean)


133
134
135
136
137
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 133

def interval_update_due?(subscription, now)
  return true if subscription[:last_sent_at].nil?

  (now - subscription[:last_sent_at]) >= subscription[:interval]
end

#process_status_request(message, options = {}) ⇒ Object



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 27

def process_status_request(message, options = {})
  component_id = message.attributes['cId']
  args = message.attributes['sS']

  begin
    component = @site.find_component component_id
    ss = fetch_status_values(component, args)
    log "Received #{message.type}", message: message, level: :log
  rescue UnknownComponent
    log "Received #{message.type} with unknown component id '#{component_id}' and cannot infer type",
        message: message, level: :warning
    ss = build_undefined_statuses(args)
  end

  response = StatusResponse.new({
                                  'cId' => component_id,
                                  'sTs' => clock.to_s,
                                  'sS' => ss,
                                  'mId' => options[:m_id]
                                })

  apply_nts_message_attributes response
  acknowledge message
  send_message response
end

#process_status_subcribe(message) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 63

def process_status_subcribe(message)
  log "Received #{message.type}", message: message, level: :log

  update_list = {}
  component_id = message.attributes['cId']
  @status_subscriptions[component_id] ||= {}
  update_list[component_id] ||= {}
  now = Time.now
  subs = @status_subscriptions[component_id]

  message.attributes['sS'].each do |arg|
    add_status_subscription(component_id, subs, update_list, arg, now)
  end
  acknowledge message
  send_status_updates update_list
end

#process_status_unsubcribe(message) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 92

def process_status_unsubcribe(message)
  log "Received #{message.type}", message: message, level: :log
  component = message.attributes['cId']

  subs = @status_subscriptions[component]
  if subs
    message.attributes['sS'].each { |arg| remove_status_subscription(subs, arg) }
    @status_subscriptions.delete(component) if subs.empty?
  end
  acknowledge message
end

#remove_status_subscription(subs, arg) ⇒ Object



84
85
86
87
88
89
90
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 84

def remove_status_subscription(subs, arg)
  sci = arg['sCI']
  return unless subs[sci]

  subs[sci].delete arg['n']
  subs.delete(sci) if subs[sci].empty?
end

#rsmpify_value(value, quality) ⇒ Object



6
7
8
9
10
11
12
13
14
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 6

def rsmpify_value(value, quality)
  if value.is_a?(Array) || value.is_a?(Set)
    value
  elsif %w[undefined unknown].include?(quality.to_s)
    nil
  else
    value.to_s
  end
end

#send_status_updates(update_list) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 185

def send_status_updates(update_list)
  now = clock.to_s
  update_list.each_pair do |component_id, by_code|
    component = @site.find_component component_id
    ss = build_status_list(component, by_code)
    update = StatusUpdate.new({
                                'cId' => component_id,
                                'sTs' => now,
                                'sS' => ss
                              })
    apply_nts_message_attributes update
    send_message update
    store_last_sent_status update
    component.status_updates_sent
  end
end

#status_update_timer(now) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 148

def status_update_timer(now)
  update_list = {}

  @status_subscriptions.each_pair do |component_id, by_code|
    component = @site.find_component component_id
    by_code.each_pair do |code, by_name|
      by_name.each_pair do |name, subscription|
        current, should_send = check_status_subscription(subscription, component, code, name, now)
        next unless should_send

        update_list[component_id] ||= {}
        update_list[component_id][code] ||= {}
        update_list[component_id][code][name] = current
      end
    end
  end
  send_status_updates update_list
end

#store_last_sent_status(message) ⇒ Object



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/rsmp/proxy/supervisor/modules/status.rb', line 108

def store_last_sent_status(message)
  component_id = message.attribute('cId')
  @last_status_sent ||= {}
  @last_status_sent[component_id] ||= {}
  message.attribute('sS').each do |item|
    sci = item['sCI']
    n = item['n']
    s = item['s']
    @last_status_sent[component_id][sci] ||= {}
    @last_status_sent[component_id][sci][n] = s
  end
end