Class: RSMP::SiteProxy

Inherits:
Proxy
  • Object
show all
Includes:
Components, Modules::AggregatedStatus, Modules::Alarms, Modules::Commands, Modules::Status, SiteSxlSelection
Defined in:
lib/rsmp/proxy/site/site_proxy.rb,
lib/rsmp/proxy/site/modules/alarms.rb,
lib/rsmp/proxy/site/modules/status.rb,
lib/rsmp/proxy/site/modules/commands.rb,
lib/rsmp/proxy/site/modules/aggregated_status.rb

Overview

Handles a supervisor-side proxy for a connected site.

Defined Under Namespace

Modules: Modules

Constant Summary

Constants inherited from Proxy

Proxy::WRAPPING_DELIMITER

Instance Attribute Summary collapse

Attributes included from Components

#components, #main

Attributes inherited from Proxy

#accepted_sxls, #archive, #collector, #connection_info, #core_version, #ip, #port, #rejected_sxls, #site_settings, #state, #sxl_interfaces, #sxls

Attributes included from Task

#task

Attributes included from Distributor

#receivers

Attributes included from Logging

#archive, #logger

Instance Method Summary collapse

Methods included from SiteSxlSelection

#check_sxl_version, #rejected_sxl, #select_legacy_sxl, #select_sxl, #select_sxls

Methods included from Modules::Commands

#process_command_response, #send_command, #send_command_and_collect

Methods included from Modules::Alarms

#process_alarm, #resume_alarm, #send_alarm_acknowledgement, #suspend_alarm

Methods included from Modules::AggregatedStatus

#aggregated_status_changed, #process_aggregated_status, #request_aggregated_status, #request_aggregated_status_and_collect, #validate_aggregated_status

Methods included from Modules::Status

#ensure_subscription_path, #process_status_response, #process_status_update, #remove_subscription_item, #request_status, #request_status_and_collect, #subscribe_to_status, #subscribe_to_status_and_collect, #unsubscribe_from_all, #unsubscribe_to_status, #update_subscription

Methods included from Components

#add_component, #aggregated_status_changed, #check_main_component, #clear_alarm_timestamps, #component_list, #find_component, #initialize_components, #natural_sort_key, #setup_components

Methods inherited from Proxy

#author, #build_sxl_interfaces, #clear, #clock, #close, #close_socket, #close_stream, #connected?, #disconnect, #disconnected?, #inspect, #log, #now, #primary_sxl, #ready?, #receive_alarms?, #schemas, #setup, #state_changed, #stop_reader, #stop_subtasks, #stop_task, #stop_timer, #sxl, #sxl_interface, #sxl_interface_for, #sxl_version, #tlc, version_meets_requirement?, #wait_for_reader

Methods included from Proxy::Modules::Tasks

#read_line, #run_reader, #run_timer, #start_reader, #start_timer, #timer

Methods included from Proxy::Modules::Versions

#check_core_version, #component_list_acknowledged, #configured_sxls, #core_3_3?, #core_versions, #extraneous_version, #normalized_core_versions, #primary_configured_sxl, #send_version, #send_version_message, #send_version_request, #send_version_response, #site_id_items, #sxl_request_items, #version_items, version_meets_requirement?, #version_meets_requirement?, #version_message_attributes, #version_request_attributes, #version_response_sxls

Methods included from Proxy::Modules::Receive

#expect_version_message, #handle_fatal_error, #handle_invalid_message, #handle_invalid_packet, #handle_malformed_message, #handle_schema_error, #process_deferred, #process_packet, #should_validate_ingoing_message?, #verify_sequence, #will_not_handle

Methods included from Proxy::Modules::Send

#apply_nts_message_attributes, #buffer_message, #handle_send_schema_error, #log_send, #send_message, #send_message_and_collect

Methods included from Proxy::Modules::Acknowledgements

#acknowledge, #check_ack_timeout, #check_ingoing_acknowledged, #check_outgoing_acknowledged, #dont_acknowledge, #dont_expect_acknowledgement, #expect_acknowledgement, #find_original_for_message, #log_acknowledgement_for_original, #log_acknowledgement_for_unknown, #process_ack, #process_not_ack, #status_subscribe_acknowledged

Methods included from Proxy::Modules::Watchdogs

#check_watchdog_timeout, #process_watchdog, #send_watchdog, #start_watchdog, #stop_watchdog, #watchdog_send_timer, #with_watchdog_disabled

Methods included from Proxy::Modules::State

#wait_for_state

Methods included from Task

#initialize_task, #restart, #start, #stop, #stop_subtasks, #stop_task, #task_status, #wait, #wait_for_condition

Methods included from Distributor

#add_receiver, #clear_deferred_distribution, #distribute, #distribute_error, #distribute_immediately, #distribute_queued, #initialize_distributor, #inspect, #remove_receiver, #with_deferred_distribution

Methods included from Logging

#author, #initialize_logging, #log

Constructor Details

#initialize(options) ⇒ SiteProxy

Returns a new instance of SiteProxy.



13
14
15
16
17
18
19
20
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 13

def initialize(options)
  super(options.merge(node: options[:supervisor]))
  initialize_components
  @supervisor = options[:supervisor]
  @settings = @supervisor.supervisor_settings.clone
  @site_id = options[:site_id]
  @status_subscriptions = {}
end

Instance Attribute Details

#site_idObject (readonly)

Returns the value of attribute site_id.



11
12
13
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 11

def site_id
  @site_id
end

#supervisorObject (readonly)

Returns the value of attribute supervisor.



11
12
13
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 11

def supervisor
  @supervisor
end

Instance Method Details

#acknowledged_first_ingoing(message) ⇒ Object



109
110
111
112
113
114
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 109

def acknowledged_first_ingoing(message)
  case message.type
  when 'Watchdog'
    send_watchdog
  end
end

#acknowledged_first_outgoing(message) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 116

def acknowledged_first_outgoing(message)
  case message.type
  when 'Watchdog'
    if core_3_3?
      @outgoing_watchdog_acknowledged = true
      handshake_complete if @component_list_received
    else
      handshake_complete
    end
  end
end

#build_component(id:, type:, settings: {}) ⇒ Object



221
222
223
224
225
226
227
228
229
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 221

def build_component(id:, type:, settings: {})
  settings ||= {}
  if type == 'main'
    ComponentProxy.new id: id, node: self, type: type, name: settings['name'], grouped: true,
                       ntsoid: settings['ntsOId'], xnid: settings['xNId']
  else
    ComponentProxy.new id: id, node: self, type: type, name: settings['name'], grouped: false
  end
end

#check_site_ids(message) ⇒ Object



177
178
179
180
181
182
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 177

def check_site_ids(message)
  # RSMP support multiple site ids. we don't support this yet. instead we use the first id only
  site_id = message.attribute('siteId').map { |item| item['sId'] }.first
  @supervisor.check_site_id site_id
  site_ids_changed
end

#find_site_settings(_site_id) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 184

def find_site_settings(_site_id)
  base = @settings['default'] || {}

  if @settings['sites']
    site_specific = @settings['sites'][@site_id] || @settings['sites']['default']
    if site_specific
      label = @settings['sites'][@site_id] ? "site id #{@site_id}" : 'default'
      log "Using #{label} site settings", level: :debug
      return base.deep_merge(site_specific)
    end
  end

  unless base.empty?
    log 'Using default site settings', level: :debug
    return base
  end

  nil
end

#handle_interface_message(message) ⇒ Object



80
81
82
83
84
85
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 80

def handle_interface_message(message)
  interface = sxl_interface_for message
  interface.validate_message! message
  record_interface_message message
  interface.process_message message
end

#handled_by_parent?(message) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 76

def handled_by_parent?(message)
  message.is_a?(CommandRequest) || message.is_a?(StatusRequest) || message.is_a?(StatusSubscribe)
end

#handshake_completeObject



46
47
48
49
50
51
52
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 46

def handshake_complete
  super
  sxl_summary = accepted_sxls.map { |item| "#{item['name']} #{item['version']}" }.join(', ')
  log "Connection to site #{@site_id} established, using core #{@core_version}, SXLs [#{sxl_summary}]",
      level: :info
  start_watchdog
end

#infer_component_type(_component_id) ⇒ Object



231
232
233
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 231

def infer_component_type(_component_id)
  ComponentProxy
end

#nodeObject



42
43
44
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 42

def node
  supervisor
end

#process_component_list(message) ⇒ Object



134
135
136
137
138
139
140
141
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 134

def process_component_list(message)
  log "Received #{message.type}", message: message, level: :log
  rebuild_components_from_list message.attributes['components']
  build_sxl_interfaces
  acknowledge message
  @component_list_received = true
  handshake_complete if @outgoing_watchdog_acknowledged
end

#process_message(message) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 54

def process_message(message)
  return super if handled_by_parent?(message)

  case message
  when StatusUnsubscribe, AggregatedStatusRequest
    will_not_handle message
  when ComponentList
    process_component_list message
  when AggregatedStatus
    process_aggregated_status message
  when AlarmIssue, AlarmSuspended, AlarmResumed, AlarmAcknowledged,
       CommandResponse, StatusResponse, StatusUpdate
    handle_interface_message message
  else
    super
  end
rescue RSMP::RepeatedAlarmError, RSMP::RepeatedStatusError, RSMP::TimestampError => e
  str = "Rejected #{message.type} message,"
  dont_acknowledge message, str, e.to_s
  distribute_error e.exception("#{str}#{e.message} #{message.json}")
end

#process_version(message) ⇒ Object



169
170
171
172
173
174
175
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 169

def process_version(message)
  return extraneous_version message if @version_determined

  check_site_ids message
  check_sxl_version message
  version_accepted message
end

#rebuild_components_from_list(items) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 143

def rebuild_components_from_list(items)
  main_id = @site_settings.dig('components', 'main')&.keys&.first
  @components = {}
  @main = nil
  items.each do |item|
    grouped = item['id'] == main_id
    component = ComponentProxy.new(
      id: item['id'],
      node: self,
      type: item['type'],
      name: item['name'],
      grouped: grouped
    )
    @components[component.c_id] = component
    @main = component if grouped
  end
end

#receive_error(error, options = {}) ⇒ Object



216
217
218
219
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 216

def receive_error(error, options = {})
  @supervisor&.receive_error error, options
  distribute_error error, options
end

#record_interface_message(message) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 87

def record_interface_message(message)
  case message
  when AlarmIssue, AlarmSuspended, AlarmResumed, AlarmAcknowledged
    process_alarm message
  when CommandResponse
    process_command_response message
  when StatusResponse
    process_status_response message
  when StatusUpdate
    process_status_update message
  end
end

#revive(options) ⇒ Object



36
37
38
39
40
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 36

def revive(options)
  super
  @supervisor = options[:supervisor]
  @settings = @supervisor.supervisor_settings.clone
end

#runObject

handle communication when we’re created, the socket is already open



24
25
26
27
28
29
30
31
32
33
34
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 24

def run
  self.state = :connected
  start_reader
  wait_for_reader # run until disconnected
rescue RSMP::ConnectionError => e
  log e, level: :error
rescue StandardError => e
  distribute_error e, level: :internal
ensure
  close
end

#setup_site_settingsObject



204
205
206
207
208
209
210
211
212
213
214
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 204

def setup_site_settings
  @site_settings = find_site_settings @site_id
  if @site_settings
    @sxls = configured_sxls
    @accepted_sxls = @sxls.dup
    build_sxl_interfaces
    setup_components @site_settings['components']
  else
    dont_acknowledge message, 'Rejected', "No config found for site #{@site_id}"
  end
end

#site_ids_changedObject



161
162
163
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 161

def site_ids_changed
  @supervisor.site_ids_changed
end

#validate_ready(action) ⇒ Object

Raises:



128
129
130
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 128

def validate_ready(action)
  raise NotReady, "Can't #{action} because connection is not ready. (Currently #{@state})" unless ready?
end

#version_accepted(message) ⇒ Object



100
101
102
103
104
105
106
107
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 100

def version_accepted(message)
  log "Received Version message for site #{@site_id}", message: message, level: :log
  start_timer
  acknowledge message
  response_id = core_3_3? ? (@supervisor.site_id || @site_id) : @site_id
  send_version_response response_id, core_versions
  @version_determined = true
end

#version_acknowledgedObject



132
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 132

def version_acknowledged; end

#watchdog_interval=(interval) ⇒ Object



165
166
167
# File 'lib/rsmp/proxy/site/site_proxy.rb', line 165

def watchdog_interval=(interval)
  @settings['intervals']['watchdog'] = interval
end