rsmp 0.5.6 → 0.6.3

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: 22ab99646f7155eb2bd6cd2f39923f499f7fa5b019f63a5124886bc1ef4cbb15
4
- data.tar.gz: db75cb477bfe945f799f37108a33550b4251d05b3d1a4f225e962dad16a4c827
3
+ metadata.gz: 4072d3e93ef2223bfc9ac2cb1a1e34b3668456e52a622a2b6f059087dd442c2e
4
+ data.tar.gz: 37603275646789fec0db5ec4c85baf731bebe6786693e6ad57eae7be3b3c29ed
5
5
  SHA512:
6
- metadata.gz: c311032b06dab4f4d0aeb3a1ce61c961b87125546116eba2429bce01f3cdb5bcd0a9bf0bbe037dedb6c0cea2e269926cc180be51823bcddddebe89bde55c273f
7
- data.tar.gz: 3121265aa3f49f49131a4afe7fe2479bcad25b2be74bcfaabb89ef8cf485cbae20298a33df456913c5818f160d0fa1e5ce7adf8142cbdac962cd109e8b13fd66
6
+ metadata.gz: 84a5e06ed20c8cb3331cf13ebd9bfc8d2baaf6c81ec14d67e83900d198153d86b89aeb09485f87afa9ef5c2aa7ca4469caa190a745dc9936caedc31bbb14d5a5
7
+ data.tar.gz: 9aa602447f391353632bf59fccd2ca48ab2eea492913cab875614c50279c362f04ebbf89559d1ea6a72878ef22e632a29160379b682356e8411568710a9d8525
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.5.6)
4
+ rsmp (0.6.3)
5
5
  async (~> 1.29.1)
6
6
  async-io (~> 1.32.1)
7
7
  colorize (~> 0.8.1)
@@ -96,7 +96,7 @@ GEM
96
96
  thread_safe
97
97
  rake (13.0.3)
98
98
  regexp_parser (2.1.1)
99
- rsmp_schemer (0.3.1)
99
+ rsmp_schemer (0.3.2)
100
100
  json_schemer (~> 0.2.18)
101
101
  rspec (3.10.0)
102
102
  rspec-core (~> 3.10.0)
@@ -8,16 +8,9 @@ guest:
8
8
  watchdog: 0.2
9
9
  acknowledgement: 0.2
10
10
  log:
11
- active: true
12
- color: true
13
- timestamp: true
14
- id: true
15
- component: true
16
- ip: false
17
11
  port: true
18
12
  site_id: 9
19
- component_id: 3
20
- text: true
13
+ component: 2
21
14
  direction: false
22
15
  level: false
23
16
  debug: true
data/config/tlc.yaml CHANGED
@@ -10,15 +10,27 @@ components:
10
10
  cycle_time: 6
11
11
  signal_group:
12
12
  A1:
13
- plan: '11NBBB'
14
13
  A2:
15
- plan: '1NBBBB'
16
14
  B1:
17
- plan: 'BBB11N'
18
15
  B2:
19
- plan: 'BBB1NB'
20
16
  detector_logic:
21
17
  DL1:
18
+ signal_plans:
19
+ 1:
20
+ dynamic_bands:
21
+ 1: 0
22
+ 2: 5
23
+ states:
24
+ A1: '11NBBB'
25
+ A2: '1NBBBB'
26
+ B1: 'BBB11N'
27
+ B2: 'BBB1NB'
28
+ 2:
29
+ states:
30
+ A1: '111NBB'
31
+ A2: '11NBBB'
32
+ B1: 'BBB11N'
33
+ B2: 'BBB1NB'
22
34
  intervals:
23
35
  timer: 0.1
24
36
  watchdog: 0.1
@@ -30,18 +42,11 @@ security_codes:
30
42
  1: '1111'
31
43
  2: '2222'
32
44
  log:
33
- active: true
34
- color: true
35
- timestamp: true
36
- id: true
37
- component_id: true
38
45
  ip: false
39
46
  site_id: 9
40
- component_id: 3
47
+ component: 2
41
48
  level: false
42
49
  debug: true
43
- text: true
44
- direction: false
45
50
  json: true
46
51
  acknowledgements: false
47
52
  watchdogs: false
data/lib/rsmp/archive.rb CHANGED
@@ -21,11 +21,11 @@ module RSMP
21
21
  def self.prepare_item item
22
22
  raise ArgumentError unless item.is_a? Hash
23
23
 
24
- cleaned = item.select { |k,v| [:author,:level,:ip,:port,:site_id,:component_id,:str,:message,:exception].include? k }
24
+ cleaned = item.select { |k,v| [:author,:level,:ip,:port,:site_id,:component,:text,:message,:exception].include? k }
25
25
  cleaned[:timestamp] = Clock.now
26
26
  if item[:message]
27
27
  cleaned[:direction] = item[:message].direction
28
- cleaned[:component_id] = item[:message].attributes['cId']
28
+ cleaned[:component] = item[:message].attributes['cId']
29
29
  end
30
30
 
31
31
  cleaned
data/lib/rsmp/cli.rb CHANGED
@@ -51,7 +51,7 @@ module RSMP
51
51
  if options[:type]
52
52
  case options[:type]
53
53
  when 'tlc'
54
- site_class = RSMP::Tlc
54
+ site_class = RSMP::TLC::TrafficControllerSite
55
55
  else
56
56
  site_class = RSMP::Site
57
57
  end
@@ -65,7 +65,8 @@ module RSMP
65
65
  end
66
66
 
67
67
  def log str, options
68
- @node.log str, options
68
+ default = { component: c_id}
69
+ @node.log str, default.merge(options)
69
70
  end
70
71
 
71
72
  def handle_command command_code, arg
@@ -118,7 +119,6 @@ module RSMP
118
119
  @statuses[sCI][n] ||= {}
119
120
  @statuses[sCI][n][:initial] = true
120
121
  end
121
- #pp @subscribes
122
122
  end
123
123
 
124
124
  # Our proxy unsubscribed to status updates.
@@ -15,8 +15,10 @@ module RSMP
15
15
  return unless settings
16
16
  check_main_component settings
17
17
  settings.each_pair do |type,components_by_type|
18
- components_by_type.each_pair do |id,settings|
19
- @components[id] = build_component(id:id, type:type, settings:settings)
18
+ if components_by_type
19
+ components_by_type.each_pair do |id,settings|
20
+ @components[id] = build_component(id:id, type:type, settings:settings)
21
+ end
20
22
  end
21
23
  end
22
24
  end
@@ -50,7 +52,8 @@ module RSMP
50
52
  component = inferred.new node: self, id: component_id
51
53
  @components[ component_id] = component
52
54
  class_name = component.class.name.split('::').last
53
- log "Inferred #{class_name} component #{component_id}", level: :info
55
+ class_name << " compoent" unless class_name == 'Component'
56
+ log "Inferred #{class_name} #{component_id}", level: :debug
54
57
  component
55
58
  else
56
59
  raise UnknownComponent.new("Component #{component_id} not found") unless component
data/lib/rsmp/error.rb CHANGED
@@ -41,6 +41,9 @@ module RSMP
41
41
  class TimeoutError < Error
42
42
  end
43
43
 
44
+ class DisonnectError < Error
45
+ end
46
+
44
47
  class ConnectionError < Error
45
48
  end
46
49
 
data/lib/rsmp/logger.rb CHANGED
@@ -5,7 +5,7 @@ module RSMP
5
5
 
6
6
  def initialize settings={}
7
7
  defaults = {
8
- 'active'=>false,
8
+ 'active'=>true,
9
9
  'path'=>nil,
10
10
  'stream'=>nil,
11
11
  'color'=>true,
@@ -13,6 +13,7 @@ module RSMP
13
13
  'statistics'=>false,
14
14
  'hide_ip_and_port' => false,
15
15
  'acknowledgements' => false,
16
+ 'watchdogs' => false,
16
17
  'json'=>false,
17
18
  'tabs'=>'-',
18
19
 
@@ -23,11 +24,10 @@ module RSMP
23
24
  'ip'=>false,
24
25
  'port'=>false,
25
26
  'site_id'=>true,
26
- 'component_id'=>true,
27
27
  'direction'=>false,
28
28
  'level'=>false,
29
- 'id'=>false,
30
- 'str'=>true,
29
+ 'id'=>true,
30
+ 'text'=>true,
31
31
  }
32
32
 
33
33
  default_lengths = {
@@ -37,8 +37,8 @@ module RSMP
37
37
  'ip'=>22,
38
38
  'port'=>5,
39
39
  'site_id'=>19,
40
- 'component_id'=>19,
41
- 'direction'=>4,
40
+ 'component'=>19,
41
+ 'direction'=>3,
42
42
  'level'=>7,
43
43
  'id'=>4,
44
44
  }
@@ -189,15 +189,15 @@ module RSMP
189
189
  build_part( parts, item, :ip )
190
190
  build_part( parts, item, :port )
191
191
  build_part( parts, item, :site_id )
192
- build_part( parts, item, :component_id )
193
- build_part( parts, item, :direction ) { |part| {in:"-->",out:"<--"}[part] }
192
+ build_part( parts, item, :component )
193
+ build_part( parts, item, :direction ) { |part| {in:"In",out:"Out"}[part] }
194
194
  build_part( parts, item, :level ) { |part| part.capitalize }
195
195
  build_part( parts, item, :id ) { Logger.shorten_message_id(item[:message].m_id,4) if item[:message] }
196
- build_part( parts, item, :str )
196
+ build_part( parts, item, :text )
197
197
  build_part( parts, item, :json ) { item[:message].json if item[:message] }
198
198
  build_part( parts, item, :exception ) { |e| [e.class,e.backtrace].flatten.join("\n") }
199
199
 
200
- parts.join(' ').chomp(@settings['tabs']).rstrip
200
+ parts.join(' ').chomp(@settings['tabs'].to_s).rstrip
201
201
  end
202
202
  end
203
203
  end
data/lib/rsmp/logging.rb CHANGED
@@ -15,7 +15,7 @@ module RSMP
15
15
  end
16
16
 
17
17
  def log str, options={}
18
- default = { str:str, level: :log, author: author, ip: @ip, port: @port }
18
+ default = { text:str, level: :log, author: author, ip: @ip, port: @port }
19
19
  prepared = RSMP::Archive.prepare_item default.merge(options)
20
20
  @archive.add prepared
21
21
  @logger.log prepared
data/lib/rsmp/node.rb CHANGED
@@ -14,9 +14,18 @@ module RSMP
14
14
  @deferred = []
15
15
  @clock = Clock.new
16
16
  @error_queue = Async::Queue.new
17
+ @ignore_errors = []
18
+ end
19
+
20
+ def ignore_errors classes, &block
21
+ was, @ignore_errors = @ignore_errors, [classes].flatten
22
+ yield
23
+ ensure
24
+ @ignore_errors = was
17
25
  end
18
26
 
19
27
  def notify_error e, options={}
28
+ return if @ignore_errors.find { |klass| e.is_a? klass }
20
29
  if options[:level] == :internal
21
30
  log ["#{e.to_s} in task: #{Async::Task.current.to_s}",e.backtrace].flatten.join("\n"), level: :error
22
31
  end
data/lib/rsmp/proxy.rb CHANGED
@@ -86,7 +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
+ notify_error DisonnectError.new("Connection was closed")
90
90
  ensure
91
91
  close_socket
92
92
  clear
@@ -348,20 +348,23 @@ module RSMP
348
348
  # cannot send NotAcknowledged for a malformed message since we can't read it, just ignore it
349
349
  nil
350
350
  rescue SchemaError, RSMP::Schemer::Error => e
351
- str = "Received invalid #{message.type}, schema errors: #{e.message}"
351
+ reason = "schema errors: #{e.message}"
352
+ str = "Received invalid #{message.type}, #{reason}"
352
353
  log str, message: message, level: :warning
353
354
  notify_error e.exception(str), message: message
354
- dont_acknowledge message, str
355
+ dont_acknowledge message, str, reason
355
356
  message
356
357
  rescue InvalidMessage => e
357
- str = "Received", "invalid #{message.type}, #{e.message}"
358
+ reason = "#{e.message}"
359
+ str = "Received invalid #{message.type},"
358
360
  notify_error e.exception("#{str} #{message.json}"), message: message
359
- dont_acknowledge message, str
361
+ dont_acknowledge message, str, reason
360
362
  message
361
363
  rescue FatalError => e
364
+ reason = e.message
362
365
  str = "Rejected #{message.type},"
363
366
  notify_error e.exception(str), message: message
364
- dont_acknowledge message, str, "#{e.message}"
367
+ dont_acknowledge message, str, reason
365
368
  stop
366
369
  message
367
370
  ensure
@@ -7,6 +7,7 @@ module RSMP
7
7
  attr_reader :rsmp_versions, :site_id, :supervisor_settings, :proxies, :logger
8
8
 
9
9
  def initialize options={}
10
+
10
11
  handle_supervisor_settings( options[:supervisor_settings] || {} )
11
12
  super options
12
13
  @proxies = []
@@ -0,0 +1,101 @@
1
+ module RSMP
2
+ module TLC
3
+ class DetectorLogic < Component
4
+ attr_reader :forced, :value
5
+
6
+ def initialize node:, id:
7
+ super node: node, id: id, grouped: false
8
+ @forced = 0
9
+ @value = 0
10
+ end
11
+
12
+ def get_status code, name=nil
13
+ case code
14
+ when 'S0201', 'S0202', 'S0203', 'S0204'
15
+ return send("handle_#{code.downcase}", code, name)
16
+ else
17
+ raise InvalidMessage.new "unknown status code #{code}"
18
+ end
19
+ end
20
+
21
+ def handle_s0201 status_code, status_name=nil
22
+ case status_name
23
+ when 'starttime'
24
+ TrafficControllerSite.make_status @node.clock.to_s
25
+ when 'vehicles'
26
+ TrafficControllerSite.make_status 0
27
+ end
28
+ end
29
+
30
+ def handle_s0202 status_code, status_name=nil
31
+ case status_name
32
+ when 'starttime'
33
+ TrafficControllerSite.make_status @node.clock.to_s
34
+ when 'speed'
35
+ TrafficControllerSite.make_status 0
36
+ end
37
+ end
38
+
39
+ def handle_s0203 status_code, status_name=nil
40
+ case status_name
41
+ when 'starttime'
42
+ TrafficControllerSite.make_status @node.clock.to_s
43
+ when 'occupancy'
44
+ TrafficControllerSite.make_status 0
45
+ end
46
+ end
47
+
48
+ def handle_s0204 status_code, status_name=nil
49
+ case status_name
50
+ when 'starttime'
51
+ TrafficControllerSite.make_status @node.clock.to_s
52
+ when 'P'
53
+ TrafficControllerSite.make_status 0
54
+ when 'PS'
55
+ TrafficControllerSite.make_status 0
56
+ when 'L'
57
+ TrafficControllerSite.make_status 0
58
+ when 'LS'
59
+ TrafficControllerSite.make_status 0
60
+ when 'B'
61
+ TrafficControllerSite.make_status 0
62
+ when 'SP'
63
+ TrafficControllerSite.make_status 0
64
+ when 'MC'
65
+ TrafficControllerSite.make_status 0
66
+ when 'C'
67
+ TrafficControllerSite.make_status 0
68
+ when 'F'
69
+ TrafficControllerSite.make_status 0
70
+ end
71
+ end
72
+
73
+ def handle_command command_code, arg
74
+ case command_code
75
+ when 'M0008'
76
+ handle_m0008 arg
77
+ else
78
+ raise UnknownCommand.new "Unknown command #{command_code}"
79
+ end
80
+ end
81
+
82
+ def handle_m0008 arg
83
+ @node.verify_security_code 2, arg['securityCode']
84
+ status = arg['status']=='True'
85
+ mode = arg['mode']=='True'
86
+ force_detector_logic status, mode
87
+ arg
88
+ end
89
+
90
+ def force_detector_logic forced, value
91
+ @forced = forced
92
+ @value = value
93
+ if @forced
94
+ log "Forcing to #{value}", level: :info
95
+ else
96
+ log "Releasing", level: :info
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,85 @@
1
+ module RSMP
2
+ module TLC
3
+ class SignalGroup < Component
4
+ attr_reader :plan, :state
5
+
6
+ # plan is a string, with each character representing a signal phase at a particular second in the cycle
7
+ def initialize node:, id:
8
+ super node: node, id: id, grouped: false
9
+ move 0
10
+ end
11
+
12
+ def get_state pos
13
+ default = 'a' # phase a means disabled/dark
14
+ plan = node.main.current_plan
15
+ return default unless plan
16
+ return default unless plan.states
17
+ states = plan.states[c_id]
18
+ return default unless states
19
+ state =states[pos]
20
+ return default unless state =~ /[a-hA-G0-9N-P]/ # valid signal group states
21
+ state
22
+ end
23
+
24
+ def move pos
25
+ @state = get_state pos
26
+ end
27
+
28
+ def handle_command command_code, arg
29
+ case command_code
30
+ when 'M0010', 'M0011'
31
+ return send("handle_#{command_code.downcase}", arg)
32
+ else
33
+ raise UnknownCommand.new "Unknown command #{command_code}"
34
+ end
35
+ end
36
+
37
+ # Start of signal group. Orders a signal group to green
38
+ def handle_m0010 arg
39
+ @node.verify_security_code 2, arg['securityCode']
40
+ if TrafficControllerSite.from_rsmp_bool arg['status']
41
+ log "Start signal group #{c_id}, go to green", level: :info
42
+ end
43
+ end
44
+
45
+ # Stop of signal group. Orders a signal group to red
46
+ def handle_m0011 arg
47
+ @node.verify_security_code 2, arg['securityCode']
48
+ if TrafficControllerSite.from_rsmp_bool arg['status']
49
+ log "Stop signal group #{c_id}, go to red", level: :info
50
+ end
51
+ end
52
+
53
+ def get_status code, name=nil
54
+ case code
55
+ when 'S0025'
56
+ return send("handle_#{code.downcase}", code, name)
57
+ else
58
+ raise InvalidMessage.new "unknown status code #{code}"
59
+ end
60
+ end
61
+
62
+ def handle_s0025 status_code, status_name=nil
63
+ now = @node.clock.to_s
64
+ case status_name
65
+ when 'minToGEstimate'
66
+ TrafficControllerSite.make_status now
67
+ when 'maxToGEstimate'
68
+ TrafficControllerSite.make_status now
69
+ when 'likelyToGEstimate'
70
+ TrafficControllerSite.make_status now
71
+ when 'ToGConfidence'
72
+ TrafficControllerSite.make_status 0
73
+ when 'minToREstimate'
74
+ TrafficControllerSite.make_status now
75
+ when 'maxToREstimate'
76
+ TrafficControllerSite.make_status now
77
+ when 'likelyToREstimate'
78
+ TrafficControllerSite.make_status now
79
+ when 'ToRConfidence'
80
+ TrafficControllerSite.make_status 0
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,29 @@
1
+ module RSMP
2
+ module TLC
3
+ # A Traffic Light Controller Signal Plan.
4
+ # A signal plan is a description of how all signal groups should change
5
+ # state over time.
6
+ class SignalPlan
7
+ attr_reader :nr, :states, :dynamic_bands
8
+ def initialize nr:, states:, dynamic_bands:
9
+ @nr = nr
10
+ @states = states
11
+ @dynamic_bands = dynamic_bands || {}
12
+ end
13
+
14
+ def dynamic_bands_string
15
+ str = @dynamic_bands.map { |band,value| "#{nr}-#{band}-#{value}" }.join(',')
16
+ return nil if str == ''
17
+ str
18
+ end
19
+
20
+ def set_band band, value
21
+ @dynamic_bands[ band.to_i ] = value.to_i
22
+ end
23
+
24
+ def get_band band
25
+ @dynamic_bands[ band.to_i ]
26
+ end
27
+ end
28
+ end
29
+ end