Module: RSMP::TLC::Modules::Inputs

Included in:
TrafficController
Defined in:
lib/rsmp/tlc/modules/inputs.rb

Overview

Input programming, control, and status for traffic controllers Handles input commands and queries

Instance Method Summary collapse

Instance Method Details

#apply_input_changes(set, clear) ⇒ Object

Helper: Apply input changes (activate/deactivate)



115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/rsmp/tlc/modules/inputs.rb', line 115

def apply_input_changes(set, clear)
  log "Activating inputs #{set} and deactivating inputs #{clear}", level: :info

  set.each do |input|
    change = @inputs.set input, true
    input_logic input, change unless change.nil?
  end
  clear.each do |input|
    change = @inputs.set input, false
    input_logic input, change unless change.nil?
  end
end

#extract_input_bits(bits, offset, target_array) ⇒ Object

Helper: Extract individual input bits from a bit pattern



90
91
92
93
94
# File 'lib/rsmp/tlc/modules/inputs.rb', line 90

def extract_input_bits(bits, offset, target_array)
  bits.to_s(2).reverse.each_char.with_index do |bit, i|
    target_array << (i + offset) if bit == '1'
  end
end

#handle_m0006(arg, _options = {}) ⇒ Object

M0006 - Set input

Raises:



43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/rsmp/tlc/modules/inputs.rb', line 43

def handle_m0006(arg, _options = {})
  @node.verify_security_code 2, arg['securityCode']
  input = arg['input'].to_i
  status = string_to_bool arg['status']
  raise MessageRejected, "Input must be in the range 1-#{@inputs.size}" unless input.between?(1, @inputs.size)

  if status
    log "Activating input #{input}", level: :info
  else
    log "Deactivating input #{input}", level: :info
  end
  change = @inputs.set input, status
  input_logic input, change unless change.nil?
end

#handle_m0012(arg, _options = {}) ⇒ Object

M0012 - Set input (simple)



59
60
61
# File 'lib/rsmp/tlc/modules/inputs.rb', line 59

def handle_m0012(arg, _options = {})
  @node.verify_security_code 2, arg['securityCode']
end

#handle_m0013(arg, _options = {}) ⇒ Object

M0013 - Set input (complex bit pattern)



64
65
66
67
68
69
# File 'lib/rsmp/tlc/modules/inputs.rb', line 64

def handle_m0013(arg, _options = {})
  @node.verify_security_code 2, arg['securityCode']
  set, clear = parse_input_status(arg['status'])
  validate_input_ranges(set, clear)
  apply_input_changes(set, clear)
end

#handle_m0019(arg, _options = {}) ⇒ Object

M0019 - Force input

Raises:



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/rsmp/tlc/modules/inputs.rb', line 136

def handle_m0019(arg, _options = {})
  @node.verify_security_code 2, arg['securityCode']
  input = arg['input'].to_i
  force = string_to_bool arg['status']
  forced_value = string_to_bool arg['inputValue']
  raise MessageRejected, "Input must be in the range 1-#{@inputs.size}" unless input.between?(1, @inputs.size)

  if force
    log "Forcing input #{input} to #{forced_value}", level: :info
  else
    log "Releasing input #{input}", level: :info
  end
  change = @inputs.set_forcing input, force: force, forced_value: forced_value

  input_logic input, change unless change.nil?
end

#handle_s0003(_status_code, status_name = nil, _options = {}) ⇒ Object

S0003 - Input status



154
155
156
157
158
159
160
161
# File 'lib/rsmp/tlc/modules/inputs.rb', line 154

def handle_s0003(_status_code, status_name = nil, _options = {})
  case status_name
  when 'inputstatus'
    TrafficControllerSite.make_status @inputs.actual_string
  when 'extendedinputstatus'
    TrafficControllerSite.make_status 0.to_s
  end
end

#handle_s0029(_status_code, status_name = nil, _options = {}) ⇒ Object

S0029 - Forced input status



164
165
166
167
168
169
# File 'lib/rsmp/tlc/modules/inputs.rb', line 164

def handle_s0029(_status_code, status_name = nil, _options = {})
  case status_name
  when 'status'
    TrafficControllerSite.make_status @inputs.forced_string
  end
end

#input_logic(input, change) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/rsmp/tlc/modules/inputs.rb', line 17

def input_logic(input, change)
  return unless @input_programming && !change.nil?

  action = @input_programming[input]
  return unless action

  return unless action['raise_alarm']

  component = if action['component']
                node.find_component action['component']
              else
                node.main
              end
  alarm_code = action['raise_alarm']
  if change
    log "Activating input #{input} is programmed to raise alarm #{alarm_code} on #{component.c_id}",
        level: :info
    component.activate_alarm alarm_code
  else
    log "Deactivating input #{input} is programmed to clear alarm #{alarm_code} on #{component.c_id}",
        level: :info
    component.deactivate_alarm alarm_code
  end
end

#parse_input_status(status_string) ⇒ Object

Helper: Parse input status string into set and clear arrays



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rsmp/tlc/modules/inputs.rb', line 72

def parse_input_status(status_string)
  set = []
  clear = []
  status_string.split(';').each do |part|
    offset, set_bits, clear_bits = part.split(',').map(&:to_i)
    extract_input_bits(set_bits, offset, set)
    extract_input_bits(clear_bits, offset, clear)
  end

  set = set.uniq.sort
  clear = clear.uniq.sort
  # if input is both activated and deactivated, there is no need to activate first
  set -= (set & clear)

  [set, clear]
end

#set_input(input_index, _value) ⇒ Object

Helper: Set a specific input value



129
130
131
132
133
# File 'lib/rsmp/tlc/modules/inputs.rb', line 129

def set_input(input_index, _value)
  return unless input_index >= 0 && input_index < @num_inputs

  @inputs[input_index] = bool_to_digit arg['value']
end

#setup_inputs(inputs) ⇒ Object



7
8
9
10
11
12
13
14
15
# File 'lib/rsmp/tlc/modules/inputs.rb', line 7

def setup_inputs(inputs)
  if inputs
    num_inputs = inputs['total']
    @input_programming = inputs['programming']
  else
    @input_programming = nil
  end
  @inputs = TLC::InputStates.new num_inputs || 8
end

#validate_input_ranges(set, clear) ⇒ Object

Helper: Validate that input indices are in valid range



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/rsmp/tlc/modules/inputs.rb', line 97

def validate_input_ranges(set, clear)
  [set, clear].each do |inputs|
    inputs.each do |input|
      if input < 1
        raise MessageRejected,
              "Cannot activate inputs #{set} and deactivate inputs #{clear}: " \
              "input #{input} is invalid (must be 1 or higher)"
      end
      next unless input > @inputs.size

      raise MessageRejected,
            "Cannot activate inputs #{set} and deactivate inputs #{clear}: " \
            "input #{input} is invalid (only #{@inputs.size} inputs present)"
    end
  end
end