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 +4 -4
- data/.gitignore +3 -3
- data/README.md +4 -5
- data/lib/sony_camera_remote_api/client/main.rb +13 -21
- data/lib/sony_camera_remote_api/client/shelf.rb +222 -0
- data/lib/sony_camera_remote_api/scripts.rb +1 -0
- data/lib/sony_camera_remote_api/shelf.rb +206 -0
- data/lib/sony_camera_remote_api/utils.rb +1 -0
- data/lib/sony_camera_remote_api/version.rb +1 -1
- metadata +4 -3
- data/lib/sony_camera_remote_api/client/config.rb +0 -266
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 07641246ad67933b0db1b774054e8370cb2e0a3d
|
4
|
+
data.tar.gz: 53708aaad639d29ab749b946f661627704e13813
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
19
|
-
|
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
|
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/
|
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
|
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
|
-
#
|
44
|
-
if
|
45
|
-
|
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
|
-
|
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
|
-
|
61
|
-
|
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
|
-
|
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
|
-
|
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
|
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.
|
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-
|
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
|