sony_camera_remote_api 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 784641aee7781cafa88acca41c1fe988a07f3d99
4
- data.tar.gz: dc40db5795ece5ab508ab44e4c32b2142c36e681
3
+ metadata.gz: 07641246ad67933b0db1b774054e8370cb2e0a3d
4
+ data.tar.gz: 53708aaad639d29ab749b946f661627704e13813
5
5
  SHA512:
6
- metadata.gz: 42a7ea2efc0ccac333ad983b314def134a736be087c6cdd791fee181f6c973dcafec850732f02beedb2e16615ec34f02dd14be15e35a2094b0f0c39533e0b04d
7
- data.tar.gz: 94de8273f23ab4d41ad53553d252df9d8bd45c6b9d6a6e1809ceab78f6b019e442ad2f6386fa7fd62b2a7ad3fbe88031e798f9bf721cffec430d2c05f7ea10c4
6
+ metadata.gz: 2e5907a4ce53ecfb1a4ccddee974ae687cc586a42c733c1bc208e05dbff17a5595bae603b5da4381a7a53dad9e0df246bf3aac51a97a62b458903deb496fa663
7
+ data.tar.gz: 82456f6634df3edef58d04bcae163492f9879777ad5e0e5d56b6a28036716019d8be1514e9dcaf2f6bb06b40d2e6efccee06fbf226ca064b653f8acb44ac8293
data/.gitignore CHANGED
@@ -42,9 +42,9 @@ build-iPhoneSimulator/
42
42
 
43
43
  # for a library or gem, you might want to ignore these files since the code is
44
44
  # intended to run in multiple environments; otherwise, check them in:
45
- # Gemfile.lock
46
- # .ruby-version
47
- # .ruby-gemset
45
+ Gemfile.lock
46
+ .ruby-version
47
+ .ruby-gemset
48
48
 
49
49
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
50
50
  .rvmrc
data/README.md CHANGED
@@ -15,8 +15,8 @@ A Ruby Gem that facilitates the use of Sony Remote Camera API.
15
15
  ## Backgrounds
16
16
 
17
17
  [Sony Camera Remote API](https://developer.sony.com/develop/cameras/) allows us to control a number of Sony cameras, including Sony Action cams, Sony Alpha cameras and Lens Style cameras, wirelessly from another device.
18
- These APIs are quite low-level, so that we have to implement a lot of sequences while considering many pitfalls, which are less documented in their API reference.
19
- The aim of this gem is providing wrapper methods that make it easy to use Sony camera functions for higher-level applications.
18
+ But these APIs are quite low-level, so that we have to implement a lot of sequences while considering many pitfalls, which are less documented in their API reference.
19
+ This gem is a wrapper library that make it easy to use Sony camera functions for high-level applications.
20
20
 
21
21
 
22
22
  ## Features
@@ -52,12 +52,11 @@ Or install it yourself as:
52
52
 
53
53
  ## Usage
54
54
 
55
- 1. Connect to the camera by Direct Wi-Fi
55
+ 1. Connect your PC to the camera by Direct Wi-Fi. If you are using Linux, bundled scripts and its interface method are available.
56
56
  2. Create SonyCameraRemoteAPI::Camera object. It takes a little time because of SSDP search.
57
57
  3. Now you can call not only wrapper methods but also original APIs as a method!
58
58
 
59
- If you are using Linux, you can use bundled scripts and its interface method.
60
- and then If you want to take a picture and save it:
59
+ If you want to take a picture and save it:
61
60
 
62
61
  ```ruby
63
62
  require 'sony_camera_remote_api'
@@ -1,7 +1,7 @@
1
1
  require 'sony_camera_remote_api'
2
2
  require 'sony_camera_remote_api/logging'
3
3
  require 'sony_camera_remote_api/scripts'
4
- require 'sony_camera_remote_api/client/config'
4
+ require 'sony_camera_remote_api/client/shelf'
5
5
  require 'fileutils'
6
6
  require 'thor'
7
7
  require 'highline/import'
@@ -9,7 +9,6 @@ require 'yaml'
9
9
  require 'time'
10
10
  require 'pp'
11
11
 
12
-
13
12
  module SonyCameraRemoteAPI
14
13
  # CLI client module
15
14
  module Client
@@ -20,9 +19,8 @@ module SonyCameraRemoteAPI
20
19
  class Main < Thor
21
20
  include Utils
22
21
  include Scripts
23
- include ConfigUtils
24
22
 
25
- register Config, 'config', 'config [commands] [options]', 'Configure camera connections'
23
+ register ShelfCmd, 'shelf', 'shelf [commands] [options]', 'Managing camera connections'
26
24
 
27
25
  # Global options
28
26
  class_option :setting, type: :boolean, desc: 'Show current camera settings'
@@ -30,8 +28,6 @@ module SonyCameraRemoteAPI
30
28
  class_option :dir, type: :string, desc: 'Output directory', banner: 'DIR'
31
29
  class_option :config, aliases: '-c', type: :string, desc: 'Config file path', banner: 'FILE'
32
30
  class_option :ssid, type: :string, desc: 'SSID of the camera to connect'
33
- class_option :pass, type: :string, desc: 'Password of camera to connect'
34
- class_option :interface, type: :string, desc: 'Interface by which camera is connected'
35
31
  class_option :verbose, type: :numeric, desc: 'Increase verbosity', banner: 'LEVEL'
36
32
 
37
33
  no_tasks do
@@ -40,41 +36,37 @@ module SonyCameraRemoteAPI
40
36
  end
41
37
 
42
38
  def load_camera_config
43
- # Check connection configuration is given by options
44
- if [options[:ssid], options[:pass], options[:interface]].any?
45
- if [options[:ssid], options[:pass], options[:interface]].all?
46
- return { 'ssid' => options[:ssid], 'pass' => options[:pass], 'interface' => options[:interface] }
47
- else
48
- puts "'--ssid', '--pass', '--interface' must be present all at a time!"
49
- return
50
- end
39
+ # If SSID is specified, load the camera config.
40
+ if options[:ssid]
41
+ @shelf.get options[:ssid] || @shelf.get_default
51
42
  else
52
- config = default_camera config_file
53
- config
43
+ @shelf.get_default
54
44
  end
55
45
  end
56
46
 
57
47
  # Load camera config and connect
58
48
  def load_and_connect
59
49
  config = load_camera_config
60
- return if config.nil?
61
- # Connect to camera by external script
50
+ unless config
51
+ puts 'Failed to load camera config!'
52
+ exit 1
53
+ end
62
54
  unless Scripts.connect(config['interface'], config['ssid'], config['pass'])
63
55
  puts 'Failed to connect!'
64
- return
56
+ exit 1
65
57
  end
66
58
  config
67
59
  end
68
60
 
69
61
  # Initialize camera instance
70
62
  def init_camera
63
+ @shelf = Shelf.new config_file
71
64
  config = load_and_connect
72
- exit(1) if config.nil?
73
65
 
74
66
  puts 'Initializing camera...'
75
67
  if config['endpoints'].nil?
76
68
  @cam = SonyCameraRemoteAPI::Camera.new reconnect_by: method(:load_and_connect)
77
- save_ssdp_config config_file, @cam.endpoints
69
+ @shelf.set_endpoints config['ssid'], @cam.endpoints
78
70
  puts 'SSDP configuration saved.'
79
71
  else
80
72
  @cam = SonyCameraRemoteAPI::Camera.new endpoints: config['endpoints'],
@@ -0,0 +1,222 @@
1
+ require 'sony_camera_remote_api'
2
+ require 'sony_camera_remote_api/scripts'
3
+ require 'sony_camera_remote_api/logging'
4
+ require 'sony_camera_remote_api/utils'
5
+ require 'sony_camera_remote_api/shelf'
6
+ require 'fileutils'
7
+ require 'thor'
8
+ require 'highline/import'
9
+
10
+
11
+ module SonyCameraRemoteAPI
12
+ # CLI client module
13
+ module Client
14
+
15
+ # 'shelf' subcommand class for managing camera connection
16
+ class ShelfCmd < Thor
17
+ include Utils
18
+ include Scripts
19
+
20
+ class_option :file, aliases: '-f', type: :string, desc: 'Config file path', banner: 'FILE'
21
+
22
+ no_tasks do
23
+ def config_file
24
+ options[:file] || GLOBAL_CONFIG_FILE
25
+ end
26
+
27
+ def read_or_create_shelf
28
+ @shelf = Shelf.new config_file
29
+ end
30
+
31
+ def get_id_or_ssid(id_or_ssid)
32
+ begin
33
+ id = Integer(id_or_ssid)
34
+ specified = @shelf.get_by_index id
35
+ unless specified
36
+ puts 'ERROR: Specified ID is invalid!'
37
+ return
38
+ end
39
+ rescue ArgumentError
40
+ ssid = id_or_ssid
41
+ specified = @shelf.get(ssid)
42
+ unless specified
43
+ puts 'ERROR: Specified SSID is not found or too ambigous!'
44
+ return
45
+ end
46
+ end
47
+ specified
48
+ end
49
+ end
50
+
51
+
52
+ desc 'add <SSID> <password> <interface>', 'Add a new camera connection'
53
+ def add(ssid, pass, interface)
54
+ read_or_create_shelf
55
+ if @shelf.get_all.find { |c| c['ssid'] == ssid }
56
+ # If SSID is duplicacted, ask user to overwrite or not.
57
+ answer = $terminal.ask('SSID duplicated! Do you want to overwrite? ') { |q| q.validate = /[yn]/i; q.default = 'n' }
58
+ if answer == 'y'
59
+ @shelf.add ssid, pass, interface, overwrite: true
60
+ else
61
+ puts 'Entry not changed.'
62
+ invoke :list, [], options
63
+ return
64
+ end
65
+ else
66
+ @shelf.add ssid, pass, interface
67
+ end
68
+
69
+ # Ask user to set default or not.
70
+ if @shelf.get
71
+ answer = $terminal.ask('Do you want set this camera as default? ') { |q| q.validate = /[yn]/i; q.default = 'y' }
72
+ if answer == 'y'
73
+ @shelf.use ssid
74
+ end
75
+ else
76
+ @shelf.use ssid
77
+ end
78
+
79
+ invoke :list, [], options
80
+ end
81
+
82
+
83
+ desc 'list', 'List added cameras'
84
+ def list
85
+ read_or_create_shelf
86
+ cameras = @shelf.get_all
87
+ default = @shelf.get
88
+
89
+ # No camera has been added, exit with a message.
90
+ if cameras.empty?
91
+ puts 'No camera yet!'
92
+ puts "Use 'sonycam shelf add' to add a new camera config."
93
+ return
94
+ end
95
+
96
+ # If default camera is not set, show message.
97
+ if default
98
+ default_ssid = default['ssid']
99
+ else
100
+ puts 'Default camera is not selected yet!'
101
+ puts "Use 'sonycam shelf use' command to select camera to use as default."
102
+ default_ssid = nil
103
+ end
104
+
105
+ # Selected camera is signed by allow
106
+ cameras.each_with_index do |v, i|
107
+ if v['ssid'] == default_ssid
108
+ puts "=> #{i}: SSID : #{v['ssid']} "
109
+ else
110
+ puts " #{i}: SSID : #{v['ssid']} "
111
+ end
112
+ puts " Password : #{v['pass']} "
113
+ puts " Interface : #{v['interface']} "
114
+ end
115
+ end
116
+
117
+
118
+ desc 'remove <ID or SSID> [options]', 'Remove camera(s) from the shelf'
119
+ option :all, type: :boolean, desc: 'Remove all cameras'
120
+ def remove(id_or_ssid = nil)
121
+ read_or_create_shelf
122
+ if options[:all]
123
+ @shelf.remove_all
124
+ return
125
+ end
126
+
127
+ specified = get_id_or_ssid id_or_ssid
128
+ @shelf.remove specified['ssid'] if specified
129
+
130
+ invoke :list, [], options
131
+ end
132
+
133
+
134
+ desc 'use <ID or SSID>', 'Select a camera as default'
135
+ def use(id_or_ssid)
136
+ read_or_create_shelf
137
+
138
+ specified = get_id_or_ssid id_or_ssid
139
+ @shelf.use specified['ssid'] if specified
140
+
141
+ invoke :list, [], options
142
+ end
143
+
144
+
145
+ desc 'interface <if-name> <ssid>', 'Set interface by which the camera is connected.'
146
+ def interface(if_name, id_or_ssid = nil)
147
+ read_or_create_shelf
148
+
149
+ if id_or_ssid
150
+ specified = get_id_or_ssid id_or_ssid
151
+ else
152
+ specified = @shelf.get
153
+ unless specified
154
+ puts 'ERROR: Default camera is not selected yet!'
155
+ return
156
+ end
157
+ end
158
+ @shelf.set_interface if_name, specified['ssid'] if specified
159
+ invoke :list, [], options
160
+ end
161
+
162
+
163
+ desc 'default', 'Show the default camera currently selected'
164
+ option :json, type: :boolean, desc: 'output in JSON format'
165
+ def default
166
+ read_or_create_shelf
167
+
168
+ default = @shelf.get
169
+ unless default
170
+ puts 'ERROR: Default camera is not selected yet!'
171
+ return
172
+ end
173
+
174
+ if options[:json]
175
+ puts JSON.pretty_generate default
176
+ else
177
+ puts "SSID : #{default['ssid']} "
178
+ puts "Password : #{default['pass']} "
179
+ puts "Interface : #{default['interface']} "
180
+ end
181
+ end
182
+
183
+
184
+ desc 'connect [options]', 'Connect to the default camera'
185
+ option :restart, aliases: '-r', type: :boolean, desc: 'Restart interface', default: false
186
+ option :ssid, aliases: '-s', type: :string, desc: 'Specify camera by SSID'
187
+ def connect
188
+ read_or_create_shelf
189
+
190
+ if options[:ssid]
191
+ camera = @shelf.get(options[:ssid])
192
+ unless camera
193
+ puts 'ERROR: Specified SSID is not found or too ambigous!'
194
+ return
195
+ end
196
+ else
197
+ camera = @shelf.get
198
+ unless camera
199
+ puts 'ERROR: Default camera is not selected yet!'
200
+ return
201
+ end
202
+ end
203
+
204
+ puts 'Camera to connect:'
205
+ puts " - SSID : #{camera['ssid']}"
206
+ puts " - pass : #{camera['pass']}"
207
+ puts " - inteface : #{camera['interface']}"
208
+
209
+ # Connect to camera by external script
210
+ if options[:restart]
211
+ result = Scripts.restart_and_connect(camera['interface'], camera['ssid'], camera['pass'])
212
+ else
213
+ result = Scripts.connect(camera['interface'], camera['ssid'], camera['pass'])
214
+ end
215
+ unless result
216
+ puts 'Failed to connect!'
217
+ exit 1
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
@@ -16,6 +16,7 @@ module SonyCameraRemoteAPI
16
16
  run_external_command "sudo bash #{connection_script} #{interface} #{ssid} #{pass}"
17
17
  end
18
18
 
19
+
19
20
  # Restart the interface and connect to camera by Wi-Fi.
20
21
  # @param [String] interface Interface name, e.g. wlan0
21
22
  # @param [String] ssid SSID of the camera to connect
@@ -0,0 +1,206 @@
1
+ require 'sony_camera_remote_api/utils'
2
+ require 'sony_camera_remote_api/scripts'
3
+ require 'yaml'
4
+
5
+
6
+ module SonyCameraRemoteAPI
7
+ class Shelf
8
+ include Utils
9
+
10
+ # Default config file saved in home directory.
11
+ GLOBAL_CONFIG_FILE = File.expand_path('~/.sonycamconf')
12
+
13
+
14
+ # Create CameraShelf object.
15
+ # @param [String] config_file The path of config file.
16
+ def initialize(config_file = GLOBAL_CONFIG_FILE)
17
+ @config_file = config_file
18
+ read_or_create
19
+ end
20
+
21
+
22
+ # Get a camera config by SSID.
23
+ # You can use a partial string as long as it is unique.
24
+ # If SSID is not given, get the default camera config.
25
+ # @param [String] ssid SSID
26
+ # @return [Hash, nil] A camera config hash
27
+ def get(ssid = nil)
28
+ if ssid.nil?
29
+ get_default
30
+ else
31
+ get_unique(ssid)
32
+ end
33
+ end
34
+
35
+
36
+ # Get a camera config by index.
37
+ # @param [String] index Index
38
+ # @return [Hash, nil] A camera config hash
39
+ def get_by_index(index)
40
+ if index.between? 0, @config['camera'].size - 1
41
+ @config['camera'][index]
42
+ end
43
+ end
44
+
45
+
46
+ # Get all camera configs.
47
+ # @return [Array<Hash>] An array of camera config hashes
48
+ def get_all
49
+ @config['camera']
50
+ end
51
+
52
+
53
+ # Add a camera config.
54
+ # @param [Boolean] overwrite Overwrite if the same SSID's config is already added.
55
+ # @return [Boolean] +true+ if successfully added, +false+ otherwise.
56
+ def add(ssid, pass, interface, overwrite: false)
57
+ # If input SSID is already registered, ask user to overwrite
58
+ same_one = @config['camera'].find { |n| n['ssid'] == ssid }
59
+ if same_one && !overwrite
60
+ false
61
+ else
62
+ @config['camera'].delete_if { |c| c['ssid'] == ssid }
63
+ @config['camera'] << { 'ssid' => ssid, 'pass' => pass, 'interface' => interface }
64
+ if @config['camera'].size == 1
65
+ @config['default'] = ssid
66
+ end
67
+ write
68
+ end
69
+ end
70
+
71
+
72
+ # Remove a camera config.
73
+ # @return [Boolean] +true+ if successfully removed, +false+ otherwise.
74
+ def remove(ssid)
75
+ entry = get_unique(ssid)
76
+ if @config['camera'].delete entry
77
+ write
78
+ else
79
+ false
80
+ end
81
+ end
82
+
83
+
84
+ # Remove a camera config by index.
85
+ # @param [String] index Index
86
+ # @return [Hash, nil] A camera config hash
87
+ def remove_by_index(index)
88
+ if index.between? 0, @config['camera'].size - 1
89
+ @config['camera'].delete_at index
90
+ write
91
+ else
92
+ false
93
+ end
94
+ end
95
+
96
+
97
+ # Remove all camera configs.
98
+ # @return [Boolean] +true+ if successfully removed, +false+ otherwise.
99
+ def remove_all
100
+ create
101
+ end
102
+
103
+
104
+ # Select a camera config as default.
105
+ # @return [Boolean] +true+ if successfully set default camera, +false+ otherwise.
106
+ def use(ssid)
107
+ entry = get(ssid)
108
+ if entry
109
+ @config['default'] = entry['ssid']
110
+ write
111
+ else
112
+ false
113
+ end
114
+ end
115
+
116
+
117
+ # Set endpoint information to a camera config.
118
+ # @return [Boolean] +true+ if successfully set endpoints, +false+ otherwise.
119
+ def set_endpoints(endpoints, ssid = nil)
120
+ entry = get(ssid)
121
+ if entry
122
+ entry['endpoints'] = endpoints
123
+ write
124
+ else
125
+ false
126
+ end
127
+ end
128
+
129
+
130
+ # Set interface by which the camera is connected.
131
+ # @return [Boolean] +true+ if successfully set default camera, +false+ otherwise.
132
+ def set_interface(interface, ssid = nil)
133
+ entry = get(ssid)
134
+ if entry
135
+ entry['interface'] = interface
136
+ write
137
+ else
138
+ false
139
+ end
140
+ end
141
+
142
+
143
+ # Connect to the camera.
144
+ # If SSID is not given, default camera is used.
145
+ # @param [String] ssid SSID
146
+ # @return [Boolean] +true+ if successfully connected, +false+ otherwise.
147
+ def connect(ssid = nil)
148
+ entry = get(ssid)
149
+ if entry
150
+ Scripts.connect entry['interface'], entry['ssid'], entry['pass']
151
+ else
152
+ false
153
+ end
154
+ end
155
+
156
+
157
+ private
158
+
159
+ # Get camera whose SSID uniquely matches with specified string.
160
+ # @param [String] ssid SSID
161
+ # @return [Hash, nil] A camera config hash
162
+ def get_unique(ssid)
163
+ complete_ssid, num = partial_and_unique_match(ssid, @config['camera'].map { |c| c['ssid'] })
164
+ return unless num == 1
165
+ @config['camera'].find { |c| c['ssid'] == complete_ssid }
166
+ end
167
+
168
+
169
+ # Get the default camera config.
170
+ # @return [Hash, nil] A camera config hash
171
+ def get_default
172
+ @config['camera'].find { |c| c['ssid'] == @config['default'] }
173
+ end
174
+
175
+ # @return [Boolean]
176
+ def read_or_create
177
+ unless read
178
+ create
179
+ else
180
+ false
181
+ end
182
+ end
183
+
184
+ # @return [Boolean]
185
+ def create
186
+ @config = { 'camera' => [] }
187
+ write
188
+ end
189
+
190
+ # @return [Boolean]
191
+ def read
192
+ if File.exists? @config_file
193
+ @config = YAML.load_file(@config_file)
194
+ end
195
+ @config.present? ? true : false
196
+ end
197
+
198
+ # @return [Boolean]
199
+ def write
200
+ open(@config_file, 'w') do |e|
201
+ YAML.dump(@config, e)
202
+ end
203
+ true
204
+ end
205
+ end
206
+ end
@@ -67,6 +67,7 @@ module SonyCameraRemoteAPI
67
67
  return nil, result.size
68
68
  end
69
69
 
70
+
70
71
  # Print array.
71
72
  # @param [Array] array
72
73
  # @param [Fixnum] horizon
@@ -1,3 +1,3 @@
1
1
  module SonyCameraRemoteAPI
2
- VERSION = '0.1.2'.freeze
2
+ VERSION = '0.1.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sony_camera_remote_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - kota65535
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-18 00:00:00.000000000 Z
11
+ date: 2016-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -189,13 +189,14 @@ files:
189
189
  - lib/sony_camera_remote_api/camera_api.rb
190
190
  - lib/sony_camera_remote_api/camera_api_group.rb
191
191
  - lib/sony_camera_remote_api/camera_api_group_def.rb
192
- - lib/sony_camera_remote_api/client/config.rb
193
192
  - lib/sony_camera_remote_api/client/main.rb
193
+ - lib/sony_camera_remote_api/client/shelf.rb
194
194
  - lib/sony_camera_remote_api/error.rb
195
195
  - lib/sony_camera_remote_api/logging.rb
196
196
  - lib/sony_camera_remote_api/packet.rb
197
197
  - lib/sony_camera_remote_api/raw_api.rb
198
198
  - lib/sony_camera_remote_api/scripts.rb
199
+ - lib/sony_camera_remote_api/shelf.rb
199
200
  - lib/sony_camera_remote_api/ssdp.rb
200
201
  - lib/sony_camera_remote_api/utils.rb
201
202
  - lib/sony_camera_remote_api/version.rb
@@ -1,266 +0,0 @@
1
- require 'sony_camera_remote_api'
2
- require 'sony_camera_remote_api/scripts'
3
- require 'sony_camera_remote_api/logging'
4
- require 'sony_camera_remote_api/utils'
5
- require 'fileutils'
6
- require 'thor'
7
- require 'highline/import'
8
- require 'yaml'
9
- require 'pp'
10
-
11
- module SonyCameraRemoteAPI
12
- module Client
13
- module ConfigUtils
14
-
15
- module_function
16
-
17
- # Get default selected camera.
18
- def default_camera(file)
19
- # check default camera in configuration file
20
- yaml = read_config_file file
21
- unless yaml.key?('default')
22
- puts 'Default camera is not selected!'
23
- return nil
24
- end
25
- yaml['camera'].find { |n| n['ssid'] == yaml['default'] }
26
- end
27
-
28
- # Save endpoint information to config file if exists
29
- def save_ssdp_config(file, endpoints)
30
- yaml = read_config_file file
31
- config = yaml['camera'].find { |n| n['ssid'] == yaml['default'] }
32
- config['endpoints'] = endpoints
33
- write_config_file file, yaml
34
- end
35
-
36
- # Read config file.
37
- # @param [Boolean] assert If +true+, exit when the config file does not exist.
38
- # @return [Hash] JSON converted from YAML config file.
39
- def read_config_file(file, assert: true)
40
- if File.exists? file
41
- YAML.load_file(file)
42
- else
43
- if assert
44
- puts 'Configuration file not found!'
45
- exit 1
46
- end
47
- end
48
- end
49
-
50
- # Write config file
51
- def write_config_file(file, yaml)
52
- open(file, 'w') do |e|
53
- YAML.dump(yaml, e)
54
- end
55
- end
56
-
57
- end
58
- end
59
- end
60
-
61
-
62
-
63
- module SonyCameraRemoteAPI
64
- # CLI client module
65
- module Client
66
-
67
- # 'config' subcommand class for managing camera connection
68
- class Config < Thor
69
- include Utils
70
- include Scripts
71
- include ConfigUtils
72
-
73
- class_option :file, aliases: '-f', type: :string, desc: 'Config file path', banner: 'FILE'
74
-
75
- no_tasks do
76
- def config_file
77
- options[:file] || GLOBAL_CONFIG_FILE
78
- end
79
- end
80
-
81
-
82
- desc 'add <SSID> <password> <interface>', 'Register a new camera connection'
83
- def add(ssid, pass, interface)
84
- yaml = read_config_file config_file, assert: false
85
- if yaml.nil? || !yaml.key?('camera')
86
- yaml = { 'camera' => [{ 'ssid' => ssid, 'pass' => pass, 'interface' => interface }] }
87
- else
88
- # if input SSID is already registered, ask user to overwrite
89
- index = yaml['camera'].index { |n| n['ssid'] == ssid }
90
- if index
91
- answer = $terminal.ask('SSID duplicated! Do you want to overwrite? ') { |q| q.validate = /[yn]/i; q.default = 'n' }
92
- if answer == 'y'
93
- yaml['camera'][index] = { 'ssid' => ssid, 'pass' => pass, 'interface' => interface }
94
- else
95
- puts 'Entry not changed.'
96
- invoke :list, [], options
97
- return
98
- end
99
- else
100
- yaml['camera'] << { 'ssid' => ssid, 'pass' => pass, 'interface' => interface }
101
- end
102
- end
103
- # ask user to select as default
104
- answer = $terminal.ask('Do you want set this camera as default? ') { |q| q.validate = /[yn]/i; q.default = 'y' }
105
- if answer == 'y'
106
- yaml['default'] = ssid
107
- end
108
- write_config_file config_file, yaml
109
- invoke :list, [], options
110
- end
111
-
112
-
113
- desc 'list', 'List registered cameras'
114
- def list
115
- yaml = read_config_file config_file
116
- if yaml['camera'].uniq! { |v| v['ssid'] }
117
- puts 'Removed duplicated entries.'
118
- write_config_file config_file, yaml
119
- end
120
- if yaml.key? 'camera'
121
- # selected camera is signed by allow
122
- yaml['camera'].each_with_index do |v, i|
123
- if v['ssid'] == yaml['default']
124
- puts "=> #{i}: SSID : #{v['ssid']} "
125
- else
126
- puts " #{i}: SSID : #{v['ssid']} "
127
- end
128
- puts " Password : #{v['pass']} "
129
- puts " Interface : #{v['interface']} "
130
- end
131
- else
132
- # no camera is registered
133
- puts 'No camera!'
134
- puts "To add new camera connection, use 'sonycam config add' command."
135
- end
136
- # default camera is not selected
137
- unless yaml.key? 'default'
138
- puts 'Currently no camera is selected as default!'
139
- puts "To select a camera as default from the list above, use 'sonycam config use' command."
140
- end
141
- end
142
-
143
-
144
- desc 'remove [options]', 'Unregister a camera'
145
- option :all, type: :boolean, desc: 'Remove all cameras'
146
- option :id, aliases: '-i', type: :numeric, desc: "Specify camera by ID, which can be seen by 'config list' command", banner: 'NUMBER'
147
- option :ssid, aliases: '-s', type: :string, desc: 'Specify camera by SSID'
148
- def remove
149
- unless [options[:id], options[:ssid], options[:all]].one?
150
- puts "use either option '--all', '--id', '--ssid' to specify camera"
151
- return
152
- end
153
-
154
- yaml = read_config_file config_file
155
- if options[:all]
156
- # remove all entries
157
- write_config_file config_file, {}
158
- return
159
- end
160
- if options[:id]
161
- # remove ID'th entry
162
- if 0 <= options[:id] && options[:id] < yaml['camera'].size
163
- yaml.delete_if { |k, v| k == 'default' && v == yaml['camera'][options[:id]]['ssid'] }
164
- yaml['camera'].delete_at options[:id]
165
- write_config_file config_file, yaml
166
- else
167
- puts 'ERROR: Specified ID is invalid!'
168
- end
169
- elsif options[:ssid]
170
- # find entry that matches specified SSID exactly
171
- result, num = partial_and_unique_match(options[:ssid], yaml['camera'].map { |e| e['ssid'] })
172
- if result
173
- yaml.delete_if { |k, v| k == 'default' && v == result }
174
- yaml['camera'].delete_if { |e| e['ssid'] == result }
175
- write_config_file config_file, yaml
176
- else
177
- if num > 1
178
- puts 'ERROR: Specified SSID is ambigous!'
179
- elsif num == 0
180
- puts 'ERROR: Specified SSID is not found!'
181
- end
182
- end
183
- end
184
- invoke :list, [], options
185
- end
186
-
187
-
188
- desc 'use <SSID>', 'Select a camera as default'
189
- option :id, aliases: '-i', type: :numeric, desc: "Specify camera by ID, which can be seen by 'config list' command", banner: 'NUMBER'
190
- option :ssid, aliases: '-s', type: :string, desc: 'Specify camera by SSID'
191
- def use
192
- unless [options[:id], options[:ssid]].one?
193
- puts "use either option '--id' or '--ssid' to specify camera"
194
- return
195
- end
196
-
197
- yaml = read_config_file config_file
198
-
199
- if options[:id]
200
- # select ID'th entry
201
- if 0 <= options[:id] && options[:id] < yaml['camera'].size
202
- yaml['default'] = yaml['camera'][options[:id]]['ssid']
203
- write_config_file config_file, yaml
204
- else
205
- puts 'ERROR: Specified ID is invalid!'
206
- end
207
- elsif options[:ssid]
208
- # find entry that matches specified SSID exactly
209
- result, num = partial_and_unique_match(options[:ssid], yaml['camera'].map { |e| e['ssid'] })
210
- if result
211
- yaml['default'] = result
212
- write_config_file config_file, yaml
213
- else
214
- # find entry that matches specified SSID partially but identically
215
- if num > 1
216
- puts 'ERROR: Specified SSID is ambigous!'
217
- elsif num == 0
218
- puts 'ERROR: Specified SSID is not found!'
219
- end
220
- end
221
- end
222
- invoke :list, [], options
223
- end
224
-
225
-
226
- desc 'default', 'Show the current default camera'
227
- option :json, type: :boolean, desc: 'output in JSON format'
228
- def default
229
- config = default_camera config_file
230
- return if config.nil?
231
-
232
- if options[:json]
233
- puts JSON.pretty_generate config
234
- else
235
- puts "SSID : #{config['ssid']} "
236
- puts "Password : #{config['pass']} "
237
- puts "Interface : #{config['interface']} "
238
- end
239
- end
240
-
241
-
242
- desc 'connect', 'Connect to the current default camera'
243
- option :restart, aliases: '-r', type: :boolean, desc: 'Restart interface', default: false
244
- def connect
245
- config = default_camera config_file
246
- return if config.nil?
247
-
248
- puts 'Selected camera:'
249
- puts " - SSID : #{config['ssid']}"
250
- puts " - pass : #{config['pass']}"
251
- puts " - inteface : #{config['interface']}"
252
-
253
- # Connect to camera by external script
254
- if options[:restart]
255
- result = Scripts.restart_and_connect(config['interface'], config['ssid'], config['pass'])
256
- else
257
- result = Scripts.connect(config['interface'], config['ssid'], config['pass'])
258
- end
259
- unless result
260
- puts 'Failed to connect!'
261
- exit 1
262
- end
263
- end
264
- end
265
- end
266
- end