procon_bypass_man 0.1.20 → 0.1.21

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +24 -8
  3. data/.github/workflows/ruby.yml +1 -1
  4. data/.rspec +1 -0
  5. data/CHANGELOG.md +24 -1
  6. data/Gemfile.lock +3 -3
  7. data/docs/getting_started.md +38 -5
  8. data/docs/setting/splatoon2_macro_dasei_cancel.md +73 -0
  9. data/lib/procon_bypass_man/background/jobs/report_completed_upgrade_pbm_job.rb +10 -0
  10. data/lib/procon_bypass_man/background.rb +1 -0
  11. data/lib/procon_bypass_man/buttons_setting_configuration/layer.rb +28 -5
  12. data/lib/procon_bypass_man/buttons_setting_configuration.rb +1 -1
  13. data/lib/procon_bypass_man/commands/bypass_command.rb +21 -2
  14. data/lib/procon_bypass_man/commands/connect_device_command.rb +11 -21
  15. data/lib/procon_bypass_man/commands/print_boot_message_command.rb +6 -0
  16. data/lib/procon_bypass_man/configuration.rb +15 -0
  17. data/lib/procon_bypass_man/device_connector.rb +6 -9
  18. data/lib/procon_bypass_man/device_procon_finder.rb +0 -20
  19. data/lib/procon_bypass_man/domains/binary/processing_procon_binary.rb +1 -1
  20. data/lib/procon_bypass_man/domains/bypass_mode.rb +29 -0
  21. data/lib/procon_bypass_man/domains.rb +1 -0
  22. data/lib/procon_bypass_man/plugin/splatoon2/macro/dasei_cancel.rb +21 -0
  23. data/lib/procon_bypass_man/plugin/splatoon2/macro/fast_return.rb +4 -0
  24. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_left_key.rb +4 -0
  25. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_right_key.rb +4 -0
  26. data/lib/procon_bypass_man/plugin/splatoon2/macro/jump_to_up_key.rb +4 -0
  27. data/lib/procon_bypass_man/plugin/splatoon2/macro/sokuwari_for_splash_bomb.rb +4 -0
  28. data/lib/procon_bypass_man/plugin/splatoon2/mode/guruguru.rb +4 -0
  29. data/lib/procon_bypass_man/plugins.rb +1 -0
  30. data/lib/procon_bypass_man/procon/button_collection.rb +0 -8
  31. data/lib/procon_bypass_man/procon/macro.rb +48 -23
  32. data/lib/procon_bypass_man/procon/macro_builder.rb +31 -21
  33. data/lib/procon_bypass_man/procon/macro_registry.rb +7 -2
  34. data/lib/procon_bypass_man/procon/user_operation.rb +1 -1
  35. data/lib/procon_bypass_man/procon/value_objects/analog_stick.rb +9 -5
  36. data/lib/procon_bypass_man/procon.rb +32 -12
  37. data/lib/procon_bypass_man/remote_pbm_action/change_pbm_version_action.rb +4 -1
  38. data/lib/procon_bypass_man/scheduler.rb +1 -1
  39. data/lib/procon_bypass_man/support/analog_stick_hypotenuse_tilting_power_scaler.rb +59 -0
  40. data/lib/procon_bypass_man/{never_exit_accidentally.rb → support/never_exit_accidentally.rb} +0 -0
  41. data/lib/procon_bypass_man/usb_device_controller.rb +53 -0
  42. data/lib/procon_bypass_man/version.rb +1 -1
  43. data/lib/procon_bypass_man/websocket/forever.rb +47 -0
  44. data/lib/procon_bypass_man/websocket/pbm_job_client.rb +14 -7
  45. data/lib/procon_bypass_man/websocket/watchdog.rb +19 -0
  46. data/lib/procon_bypass_man.rb +8 -7
  47. data/procon_bypass_man.gemspec +1 -1
  48. data/project_template/app.rb +11 -1
  49. data/project_template/systemd_units/pbm.service +1 -1
  50. data/sig/main.rbs +20 -0
  51. metadata +13 -5
@@ -10,6 +10,10 @@ module ProconBypassMan
10
10
  def self.steps
11
11
  [:x, :down, :a, :a].freeze
12
12
  end
13
+
14
+ def self.description
15
+ '試合中にリスポーンにスーパージャンプ'
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -10,6 +10,10 @@ module ProconBypassMan
10
10
  def self.steps
11
11
  [:x, :left, :a, :a].freeze
12
12
  end
13
+
14
+ def self.description
15
+ '試合中に左キーに割り当てられている味方へのスーパージャンプ'
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -10,6 +10,10 @@ module ProconBypassMan
10
10
  def self.steps
11
11
  [:x, :right, :a, :a].freeze
12
12
  end
13
+
14
+ def self.description
15
+ '試合中に右キーに割り当てられている味方へのスーパージャンプ'
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -10,6 +10,10 @@ module ProconBypassMan
10
10
  def self.steps
11
11
  [:x, :up, :a, :a].freeze
12
12
  end
13
+
14
+ def self.description
15
+ '試合中に上キーに割り当てられている味方へのスーパージャンプ'
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -15,6 +15,10 @@ module ProconBypassMan
15
15
  :toggle_r_for_1sec,
16
16
  ].freeze
17
17
  end
18
+
19
+ def self.description
20
+ 'バブル即割'
21
+ end
18
22
  end
19
23
  end
20
24
  end
@@ -3,6 +3,10 @@ module ProconBypassMan
3
3
  module Splatoon2
4
4
  module Mode
5
5
  module Guruguru
6
+ def self.description
7
+ '適当に動きます'
8
+ end
9
+
6
10
  def self.binaries
7
11
  [ "309481408000362d684658750968f71cfe2c0e51000001480053f71ffedf0d4b000a013d00caf6ecfd4c0d480003011c00000000000000000000000000000000",
8
12
  "30978140800037dd6748687509fdf6adfded0d6d0081005d00eef68dfdef0d6d00830059001bf791fd140e720090005400000000000000000000000000000000",
@@ -4,6 +4,7 @@ require_relative "plugin/splatoon2/macro/jump_to_right_key"
4
4
  require_relative "plugin/splatoon2/macro/jump_to_up_key"
5
5
  require_relative "plugin/splatoon2/macro/jump_to_left_key"
6
6
  require_relative "plugin/splatoon2/macro/sokuwari_for_splash_bomb"
7
+ require_relative "plugin/splatoon2/macro/dasei_cancel"
7
8
  require_relative "plugin/splatoon2/mode/guruguru"
8
9
 
9
10
  module ProconBypassMan
@@ -37,12 +37,4 @@ class ProconBypassMan::Procon::ButtonCollection
37
37
  BUTTONS = ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP.keys.freeze
38
38
 
39
39
  LEFT_ANALOG_STICK = { byte_position: 6..8 }
40
-
41
- # @param [Array<Symbol>] buttons
42
- # @return [Array<Symbol>]
43
- def self.normalize(buttons)
44
- buttons.select { |x|
45
- !!ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[x]
46
- }
47
- end
48
40
  end
@@ -1,13 +1,51 @@
1
1
  class ProconBypassMan::Procon::Macro
2
- class NestedStep
2
+ class BaseNestedStep
3
3
  def initialize(value)
4
4
  @hash = value
5
+ end
6
+
7
+ private
8
+
9
+ def incr_step_index!
10
+ if step_index
11
+ @hash[:step_index] += 1
12
+ else
13
+ @hash[:step_index] = 0
14
+ end
15
+ end
16
+
17
+ def current_step
18
+ @hash[:steps][step_index]
19
+ end
20
+ end
21
+
22
+ class OnetimeNestedStep < BaseNestedStep
23
+ def over?
24
+ current_step.nil?
25
+ end
26
+
27
+ def next_step
28
+ step = current_step
29
+ incr_step_index!
30
+ step
31
+ end
32
+
33
+ private
34
+
35
+ def step_index
36
+ @hash[:step_index] ||= 0
37
+ end
38
+ end
39
+
40
+ class NestedStep < BaseNestedStep
41
+ def initialize(value)
42
+ super
5
43
  unless @hash[:end_at]
6
44
  @hash[:end_at] = (Time.now + @hash[:continue_for]).round(4)
7
45
  end
8
46
  end
9
47
 
10
- def over_end_at?
48
+ def over?
11
49
  (@hash[:end_at] < Time.now).tap do |result|
12
50
  if result
13
51
  ProconBypassMan.logger.debug { "[Macro] nested step is finished(#{@hash})" }
@@ -17,8 +55,6 @@ class ProconBypassMan::Procon::Macro
17
55
 
18
56
  def next_step
19
57
  incr_step_index!
20
-
21
- debug_incr_called_count!
22
58
  if step = current_step
23
59
  return step
24
60
  else
@@ -29,30 +65,13 @@ class ProconBypassMan::Procon::Macro
29
65
 
30
66
  private
31
67
 
32
- def current_step
33
- @hash[:steps][step_index]
34
- end
35
-
36
68
  def step_index
37
69
  @hash[:step_index]
38
70
  end
39
71
 
40
- def incr_step_index!
41
- if step_index
42
- @hash[:step_index] += 1
43
- else
44
- @hash[:step_index] = 0
45
- end
46
- end
47
-
48
72
  def reset_step_index!
49
73
  @hash[:step_index] = 0
50
74
  end
51
-
52
- def debug_incr_called_count!
53
- @hash[:debug_called_count] ||= 0
54
- @hash[:debug_called_count] += 1
55
- end
56
75
  end
57
76
 
58
77
  attr_accessor :name, :steps
@@ -69,8 +88,14 @@ class ProconBypassMan::Procon::Macro
69
88
  end
70
89
 
71
90
  if step.is_a?(Hash)
72
- nested_step = NestedStep.new(step)
73
- if nested_step.over_end_at?
91
+ nested_step =
92
+ if step[:continue_for]
93
+ NestedStep.new(step)
94
+ else
95
+ OnetimeNestedStep.new(step)
96
+ end
97
+
98
+ if nested_step.over?
74
99
  steps.shift # NestedStepを破棄する
75
100
  return next_step
76
101
  else
@@ -56,7 +56,7 @@ class ProconBypassMan::Procon::MacroBuilder
56
56
 
57
57
  # @return [Arary<Symbol>]
58
58
  def build
59
- steps = @steps.map { |step|
59
+ steps = @steps.flat_map { |step|
60
60
  if is_reserved?(step: step) || v1_format?(step: step)
61
61
  step.to_sym
62
62
  elsif value = build_if_v2_format?(step: step)
@@ -65,7 +65,8 @@ class ProconBypassMan::Procon::MacroBuilder
65
65
  nil
66
66
  end
67
67
  }
68
- steps.compact.flatten
68
+
69
+ steps.compact
69
70
  end
70
71
 
71
72
  private
@@ -81,31 +82,40 @@ class ProconBypassMan::Procon::MacroBuilder
81
82
  end
82
83
 
83
84
  def build_if_v2_format?(step: )
84
- # 時間指定なし
85
- if(match = step.match(%r!\Atoggle_(\w+)\z!)) && (button_candidate = match[1]) && is_button(button_candidate)
86
- button = button_candidate
87
- return [button.to_sym, :none]
88
- end
89
-
90
- # 時間指定あり
91
- if %r!^(pressing_|toggle_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|toggle_[^_]+!)) && (match = step.match(%r!_for_([\d_]+)(sec)?\z!))
92
- sec = match[1]
93
- return [
94
- { continue_for: to_num(sec),
95
- steps: SubjectMerger.merge(subjects.map { |x| Subject.new(x) }),
96
- }
97
- ]
98
- end
99
-
100
85
  # no-op command
101
86
  if(match = step.match(%r!wait_for_([\d_]+)(sec)?\z!))
102
87
  sec = match[1]
103
88
  return [
104
- { continue_for: to_num(sec),
89
+ { continue_for: to_f(sec),
105
90
  steps: [:none],
106
91
  }
107
92
  ]
108
93
  end
94
+
95
+ if %r!^(pressing_|toggle_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|toggle_[^_]+!)) && (match = step.match(%r!_for_([\d_]+)(sec)?\z!))
96
+ if sec = match[1]
97
+ return {
98
+ continue_for: to_f(sec),
99
+ steps: SubjectMerger.merge(subjects.map { |x| Subject.new(x) }).select { |x|
100
+ if x.is_a?(Array)
101
+ x.select { |y| is_button(y) || RESERVED_WORD_NONE == y }
102
+ else
103
+ is_button(x) || RESERVED_WORD_NONE == x
104
+ end
105
+ },
106
+ }
107
+ end
108
+ end
109
+
110
+ if %r!^(pressing_|toggle_)! =~ step && (subjects = step.scan(%r!pressing_[^_]+|toggle_[^_]+!))
111
+ return SubjectMerger.merge(subjects.map { |x| Subject.new(x) }).select { |x|
112
+ if x.is_a?(Array)
113
+ x.select { |y| is_button(y) || RESERVED_WORD_NONE == y }
114
+ else
115
+ is_button(x) || RESERVED_WORD_NONE == x
116
+ end
117
+ }
118
+ end
109
119
  end
110
120
 
111
121
  # @return [Boolean]
@@ -113,11 +123,11 @@ class ProconBypassMan::Procon::MacroBuilder
113
123
  !!ProconBypassMan::Procon::ButtonCollection::BUTTONS_MAP[step.to_sym]
114
124
  end
115
125
 
116
- def to_num(value)
126
+ def to_f(value)
117
127
  if value.include?("_")
118
128
  value.sub("_", ".").to_f
119
129
  else
120
- value.to_i
130
+ value.to_f
121
131
  end
122
132
  end
123
133
  end
@@ -13,9 +13,14 @@ class ProconBypassMan::Procon::MacroRegistry
13
13
  }
14
14
  end
15
15
 
16
+ # @return [ProconBypassMan::Procon::Macro]
16
17
  def self.load(name)
17
- steps = PRESETS[name] || plugins[name].call || raise("unknown macro")
18
- ProconBypassMan::Procon::Macro.new(name: name, steps: steps.dup)
18
+ if(steps = PRESETS[name] || plugins[name]&.call)
19
+ return ProconBypassMan::Procon::Macro.new(name: name, steps: steps.dup)
20
+ else
21
+ warn "installされていないマクロ(#{name})を使うことはできません"
22
+ return self.load(:null)
23
+ end
19
24
  end
20
25
 
21
26
  def self.reset!
@@ -62,7 +62,7 @@ class ProconBypassMan::Procon::UserOperation
62
62
  # @param [Symbol] button
63
63
  # @return [Boolean]
64
64
  def pressing_button?(button)
65
- ProconBypassMan::PressButtonAware.new(@binary.raw).pressing_button?(button)
65
+ pressing_all_buttons?([button])
66
66
  end
67
67
 
68
68
  # @param [Array<Symbol>] buttons
@@ -1,6 +1,6 @@
1
1
  class ProconBypassMan::Procon::AnalogStick
2
2
  attr_accessor :neutral_position
3
- attr_accessor :bin_x, :bin_y
3
+ attr_writer :bin_x, :bin_y
4
4
 
5
5
  def initialize(binary: )
6
6
  @neutral_position = ProconBypassMan::ButtonsSettingConfiguration.instance.neutral_position
@@ -13,18 +13,22 @@ class ProconBypassMan::Procon::AnalogStick
13
13
  end
14
14
 
15
15
  def abs_x
16
- bin_x.to_i(2)
16
+ @bin_x.to_i(2)
17
17
  end
18
18
 
19
19
  def abs_y
20
- bin_y.to_i(2)
20
+ @bin_y.to_i(2)
21
21
  end
22
22
 
23
23
  def relative_x
24
- bin_x.to_i(2) - neutral_position.x
24
+ @bin_x.to_i(2) - neutral_position.x
25
25
  end
26
26
 
27
27
  def relative_y
28
- bin_y.to_i(2) - neutral_position.y
28
+ @bin_y.to_i(2) - neutral_position.y
29
+ end
30
+
31
+ def relative_hypotenuse
32
+ Math.sqrt((relative_x**2) + (relative_y**2)).floor(6)
29
33
  end
30
34
  end
@@ -19,6 +19,7 @@ class ProconBypassMan::Procon
19
19
  ongoing_macro: MacroRegistry.load(:null),
20
20
  ongoing_mode: ModeRegistry.load(:manual),
21
21
  }
22
+ @@left_stick_tilting_power_scaler = ProconBypassMan::AnalogStickTiltingPowerScaler.new
22
23
  end
23
24
  reset!
24
25
 
@@ -38,6 +39,7 @@ class ProconBypassMan::Procon
38
39
  ProconBypassMan::ButtonsSettingConfiguration.instance.layers[current_layer_key]
39
40
  end
40
41
 
42
+ # 内部ステータスを書き換えるフェーズ
41
43
  def apply!
42
44
  layer_changer = ProconBypassMan::Procon::LayerChanger.new(binary: user_operation.binary)
43
45
  if layer_changer.change_layer?
@@ -46,10 +48,38 @@ class ProconBypassMan::Procon
46
48
  return
47
49
  end
48
50
 
49
- if ongoing_macro.finished?
51
+ analog_stick = ProconBypassMan::Procon::AnalogStick.new(binary: user_operation.binary.raw)
52
+ dumped_tilting_power = @@left_stick_tilting_power_scaler.add_sample(analog_stick.relative_hypotenuse)
53
+
54
+ enable_all_macro = true
55
+ enable_macro_map = Hash.new {|h,k| h[k] = true }
56
+ current_layer.disable_macros.each do |disable_macro|
57
+ if (disable_macro[:if_pressed] == [true] || user_operation.pressing_all_buttons?(disable_macro[:if_pressed]))
58
+ if disable_macro[:name] == :all
59
+ enable_all_macro = false
60
+ else
61
+ enable_macro_map[disable_macro[:name]] = false
62
+ end
63
+ end
64
+ end
65
+
66
+ if ongoing_macro.finished? && enable_all_macro
50
67
  current_layer.macros.each do |macro_name, options|
68
+ next unless enable_macro_map[macro_name]
69
+
70
+ if(if_tilted_left_stick_value = options[:if_tilted_left_stick])
71
+ threshold = (if_tilted_left_stick_value.is_a?(Hash) && if_tilted_left_stick_value[:threshold]) || ProconBypassMan::AnalogStickTiltingPowerScaler::DEFAULT_THRESHOLD
72
+ if dumped_tilting_power&.tilting?(threshold: threshold, current_position_x: analog_stick.relative_x, current_position_y: analog_stick.relative_y) && user_operation.pressing_all_buttons?(options[:if_pressed])
73
+ @@status[:ongoing_macro] = MacroRegistry.load(macro_name)
74
+ break
75
+ end
76
+
77
+ next
78
+ end
79
+
51
80
  if user_operation.pressing_all_buttons?(options[:if_pressed])
52
81
  @@status[:ongoing_macro] = MacroRegistry.load(macro_name)
82
+ break
53
83
  end
54
84
  end
55
85
  end
@@ -88,7 +118,7 @@ class ProconBypassMan::Procon
88
118
  status
89
119
  end
90
120
 
91
- # @return [ProconBypassMan::Domains::ProcessingProconBinary]
121
+ # @return [String]
92
122
  def to_binary
93
123
  if ongoing_mode.name != :manual
94
124
  return user_operation.binary.raw
@@ -143,14 +173,4 @@ class ProconBypassMan::Procon
143
173
 
144
174
  user_operation.binary.raw
145
175
  end
146
-
147
- private
148
-
149
- def method_missing(name)
150
- if name.to_s =~ /\Apressed_[a-z]+\?\z/
151
- user_operation.public_send(name)
152
- else
153
- super
154
- end
155
- end
156
176
  end
@@ -6,8 +6,11 @@ module ProconBypassMan
6
6
  require "pbmenv"
7
7
  ProconBypassMan.logger.info "execute ChangePbmVersionAction!"
8
8
  pbm_version = args["pbm_version"] or raise(ProconBypassMan::RemotePbmAction::NeedPbmVersionError, "pbm_versionが必要です, #{args.inspect}")
9
- Pbmenv.install(pbm_version)
9
+ Pbmenv.uninstall(pbm_version) # 途中でシャットダウンしてしまった、とか状態が途中の状態かもしれないので一旦消す
10
+ Pbmenv.install(pbm_version, enable_pbm_cloud: true)
10
11
  Pbmenv.use(pbm_version)
12
+ ProconBypassMan.logger.info "#{pbm_version}へアップグレードしました"
13
+ ProconBypassMan::ReportCompletedUpgradePbmJob.perform
11
14
  `reboot` # symlinkの参照先が変わるのでrebootする必要がある
12
15
  end
13
16
 
@@ -74,7 +74,7 @@ module ProconBypassMan
74
74
  args: [->{ ProconBypassMan::DeviceStatus.current }],
75
75
  interval: 60,
76
76
  )
77
- )
77
+ ) if ProconBypassMan.config.has_api_server?
78
78
  end
79
79
 
80
80
  # @param [Schedule] schedule
@@ -0,0 +1,59 @@
1
+ class ProconBypassMan::AnalogStickTiltingPowerScaler
2
+ DEFAULT_THRESHOLD = 500
3
+
4
+ class PowerChunk
5
+ def initialize(list)
6
+ @list = list
7
+ end
8
+
9
+ def moving_power
10
+ max = @list.max
11
+ min = @list.min
12
+ moving_power = (max - min).abs
13
+ end
14
+
15
+ def tilting?(threshold: DEFAULT_THRESHOLD, current_position_x: , current_position_y: )
16
+ # スティックがニュートラルな時
17
+ if (-200..200).include?(current_position_x) && (-200..200).include?(current_position_y)
18
+ return false
19
+ end
20
+
21
+ moving_power >= threshold
22
+ end
23
+ end
24
+
25
+ def initialize
26
+ @map = {}
27
+ end
28
+
29
+ # @return [NilClass, Chunk] ローテトしたらvalueを返す
30
+ def add_sample(value)
31
+ rotated = nil
32
+ current_key = key
33
+ if @map[current_key].nil?
34
+ rotated = rotate
35
+ @map = { current_key => [] } # renew or initialize
36
+ end
37
+
38
+ @map[current_key] << value
39
+ rotated
40
+ end
41
+
42
+ private
43
+
44
+ # 0.1sec刻みで進行する
45
+ def key
46
+ time = Time.now
47
+ m1 = time.strftime('%L')[0]
48
+ [time.to_i, m1].join.to_i
49
+ end
50
+
51
+ def rotate
52
+ list = @map.values.first
53
+ if list
54
+ return PowerChunk.new(list)
55
+ else
56
+ return nil
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,53 @@
1
+ class ProconBypassMan::UsbDeviceController
2
+ class << self
3
+ def reset
4
+ system('echo > /sys/kernel/config/usb_gadget/procon/UDC')
5
+ system('ls /sys/class/udc > /sys/kernel/config/usb_gadget/procon/UDC')
6
+ sleep 0.5
7
+ end
8
+
9
+ def init
10
+ return if initialized?
11
+
12
+ shell = <<~EOH
13
+ #!/bin/bash
14
+
15
+ cd /sys/kernel/config/usb_gadget/
16
+ mkdir -p procon
17
+ cd procon
18
+ echo 0x057e > idVendor
19
+ echo 0x2009 > idProduct
20
+ echo 0x0200 > bcdDevice
21
+ echo 0x0200 > bcdUSB
22
+ echo 0x00 > bDeviceClass
23
+ echo 0x00 > bDeviceSubClass
24
+ echo 0x00 > bDeviceProtocol
25
+
26
+ mkdir -p strings/0x409
27
+ echo "000000000001" > strings/0x409/serialnumber
28
+ echo "Nintendo Co., Ltd." > strings/0x409/manufacturer
29
+ echo "Pro Controller" > strings/0x409/product
30
+
31
+ mkdir -p configs/c.1/strings/0x409
32
+ echo "Nintendo Switch Pro Controller" > configs/c.1/strings/0x409/configuration
33
+ echo 500 > configs/c.1/MaxPower
34
+ echo 0xa0 > configs/c.1/bmAttributes
35
+
36
+ mkdir -p functions/hid.usb0
37
+ echo 0 > functions/hid.usb0/protocol
38
+ echo 0 > functions/hid.usb0/subclass
39
+ echo 64 > functions/hid.usb0/report_length
40
+ echo 050115000904A1018530050105091901290A150025017501950A5500650081020509190B290E150025017501950481027501950281030B01000100A1000B300001000B310001000B320001000B35000100150027FFFF0000751095048102C00B39000100150025073500463B0165147504950181020509190F2912150025017501950481027508953481030600FF852109017508953F8103858109027508953F8103850109037508953F9183851009047508953F9183858009057508953F9183858209067508953F9183C0 | xxd -r -ps > functions/hid.usb0/report_desc
41
+
42
+ ln -s functions/hid.usb0 configs/c.1/
43
+ ls /sys/class/udc > UDC
44
+ EOH
45
+
46
+ `bash -c '#{shell}'`
47
+ end
48
+
49
+ def initialized?
50
+ Dir.exist?("/sys/kernel/config/usb_gadget/procon")
51
+ end
52
+ end
53
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ProconBypassMan
4
- VERSION = "0.1.20"
4
+ VERSION = "0.1.21"
5
5
  end
@@ -0,0 +1,47 @@
1
+ module ProconBypassMan
2
+ module Websocket
3
+ class Forever
4
+ # 動作確認方法
5
+ # - 10秒ごとにrefreshするのでタイムアウトは起きない
6
+ # - ProconBypassMan::Websocket::Forever.run { loop { puts(:hi); sleep(10); ProconBypassMan::Websocket::Watchdog.active! } }
7
+ # - タイムアウトが起きること
8
+ # - ProconBypassMan::Websocket::Forever.run { puts(:hi); sleep(3000); }
9
+ # - ブロックを1回評価するとThreadが死ぬので100秒後にタイムアウトが起きること
10
+ # - ProconBypassMan::Websocket::Forever.run { puts(:hi); sleep(10); ProconBypassMan::Websocket::Watchdog.active! }
11
+ def self.run(&block)
12
+ loop do
13
+ new.run(&block)
14
+ end
15
+ end
16
+
17
+ def run(&block)
18
+ raise("need a block") unless block_given?
19
+
20
+ ws_thread = work_one(callable: block)
21
+ wait_and_kill_if_outdated(ws_thread)
22
+ end
23
+
24
+ # @return [Thread]
25
+ def work_one(callable: )
26
+ Thread.start do
27
+ callable.call
28
+ rescue => e
29
+ ProconBypassMan.logger.error("websocket client with forever: #{e.full_message}")
30
+ end
31
+ end
32
+
33
+ def wait_and_kill_if_outdated(thread)
34
+ loop do
35
+ if Watchdog.outdated?
36
+ Watchdog.active!
37
+ ProconBypassMan.logger.error("watchdog timeout!!")
38
+ thread.kill
39
+ return
40
+ end
41
+
42
+ sleep(10)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -7,11 +7,7 @@ module ProconBypassMan
7
7
  return unless ProconBypassMan.config.enable_ws?
8
8
 
9
9
  Thread.start do
10
- loop do
11
- run
12
- rescue
13
- retry
14
- end
10
+ Forever.run { run }
15
11
  end
16
12
  end
17
13
 
@@ -24,14 +20,16 @@ module ProconBypassMan
24
20
  )
25
21
 
26
22
  client.connected {
27
- ProconBypassMan.logger.info('successfully connected in ProconBypassMan::Websocket::PbmJobClient')
23
+ ProconBypassMan.logger.info('websocket client: successfully connected in ProconBypassMan::Websocket::PbmJobClient')
28
24
  }
29
25
  client.subscribed { |msg|
26
+ ProconBypassMan.logger.info('websocket client: subscribed')
30
27
  puts({ event: :subscribed, msg: msg })
31
28
  ProconBypassMan::SyncDeviceStatsJob.perform(ProconBypassMan::DeviceStatus.current)
32
29
  }
33
30
 
34
31
  client.received do |data|
32
+ ProconBypassMan.logger.info('websocket client: received!!')
35
33
  ProconBypassMan.logger.info(data)
36
34
 
37
35
  dispatch(data: data, client: client)
@@ -40,13 +38,22 @@ module ProconBypassMan
40
38
  end
41
39
 
42
40
  client.disconnected {
41
+ ProconBypassMan.logger.info('websocket client: disconnected!!')
43
42
  puts :disconnected
44
43
  client.reconnect!
45
44
  sleep 2
46
45
  }
47
- client.errored { |msg| puts :errored; puts msg }
46
+ client.errored { |msg|
47
+ ProconBypassMan.logger.error("websocket client: errored!!, #{msg}")
48
+ puts :errored
49
+ client.reconnect!
50
+ sleep 2
51
+ }
48
52
  client.pinged { |msg|
53
+ Watchdog.active!
54
+
49
55
  ProconBypassMan.cache.fetch key: 'ws_pinged', expires_in: 10 do
56
+ ProconBypassMan.logger.info('websocket client: pinged!!')
50
57
  ProconBypassMan.logger.info(msg)
51
58
  end
52
59
  }