sony_camera_remote_api 0.1.2 → 0.1.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
  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