procon_bypass_man 0.1.20 → 0.1.21

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.
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
  }