sony-camera-remote 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +5 -0
  4. data/CONTRIBUTING.markdown +7 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +12 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.markdown +52 -0
  9. data/Rakefile +9 -0
  10. data/TODO.markdown +73 -0
  11. data/bin/search-nex.py +25 -0
  12. data/bin/sonycam +48 -0
  13. data/lib/sony_camera_remote.rb +5 -0
  14. data/lib/sony_camera_remote/camera.rb +61 -0
  15. data/lib/sony_camera_remote/device.rb +19 -0
  16. data/lib/sony_camera_remote/discovery/client.rb +90 -0
  17. data/lib/sony_camera_remote/discovery/device_info.rb +78 -0
  18. data/lib/sony_camera_remote/discovery/m_search.erb +5 -0
  19. data/lib/sony_camera_remote/discovery/request.rb +20 -0
  20. data/lib/sony_camera_remote/discovery/response.rb +17 -0
  21. data/lib/sony_camera_remote/service.rb +24 -0
  22. data/lib/sony_camera_remote/version.rb +3 -0
  23. data/sony-camera-remote.gemspec +33 -0
  24. data/test/fixtures/DmsRmtDesc.xml +95 -0
  25. data/test/fixtures/discovery_request.txt +6 -0
  26. data/test/fixtures/discovery_response.txt +9 -0
  27. data/test/fixtures/vcr/CameraTest_setup.yml +26 -0
  28. data/test/fixtures/vcr/CameraTest_test_application_info.yml +26 -0
  29. data/test/fixtures/vcr/CameraTest_test_available_methods.yml +26 -0
  30. data/test/fixtures/vcr/CameraTest_test_shoot.yml +26 -0
  31. data/test/fixtures/vcr/CameraTest_test_shootmode_interval_still.yml +26 -0
  32. data/test/fixtures/vcr/CameraTest_test_shootmode_movie.yml +26 -0
  33. data/test/fixtures/vcr/CameraTest_test_shootmode_still.yml +26 -0
  34. data/test/fixtures/vcr/CameraTest_test_supported_shootmodes.yml +26 -0
  35. data/test/fixtures/vcr/DeviceInfoTest_setup.yml +43 -0
  36. data/test/helper.rb +26 -0
  37. data/test/unit/test_camera.rb +41 -0
  38. data/test/unit/test_device_info.rb +71 -0
  39. data/test/unit/test_request.rb +11 -0
  40. data/test/unit/test_response.rb +11 -0
  41. metadata +257 -0
@@ -0,0 +1,78 @@
1
+ require 'httparty'
2
+
3
+ module SonyCameraRemote
4
+ module Discovery
5
+ class ScalarWebAPIServicesMapper
6
+ class << self
7
+ def map(services_info)
8
+ services_info['X_ScalarWebAPI_Service'].map do |service_info|
9
+ SonyCameraRemote::Services::ScalarWebAPIService.new.tap do |service|
10
+ service.id = service_info['X_ScalarWebAPI_ServiceType']
11
+ service.type = service_info['X_ScalarWebAPI_ServiceType']
12
+ service.actionlist_url = service_info['X_ScalarWebAPI_ActionList_URL']
13
+ service.access_type = service_info['X_ScalarWebAPI_AccessType']
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ class ServicesMapper
21
+ class << self
22
+ def map(services_info)
23
+ services_info['service'].map do |service|
24
+ # urn:upnp-org:serviceId:ContentDirectory => ContentDirectory
25
+ # urn:upnp-org:serviceId:ConnectionManager => ConnectionManager
26
+ # urn:schemas-sony-com:serviceId:ScalarWebAPI => ScalarWebAPI
27
+ service_class = "#{service['serviceId'].split(':').last}Service"
28
+
29
+ SonyCameraRemote::Services.const_get(service_class).new.tap do |s|
30
+ s.id = service['serviceId']
31
+ s.type = service['serviceType']
32
+ s.scpd_url = service['SCPDURL']
33
+ s.control_url = service['controlURL']
34
+ s.event_sub_url = service['eventSubURL']
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ class DeviceMapper
42
+ class << self
43
+ def map(device_info)
44
+ if swadi_device_info = device_info['X_ScalarWebAPI_DeviceInfo']
45
+ device = ScalarWebAPIDevice.new.tap do |swadi|
46
+ swadi.version = swadi_device_info['X_ScalarWebAPI_Version']
47
+ swadi.imaging_device = swadi_device_info['X_ScalarWebAPI_ImagingDevice']
48
+
49
+ ScalarWebAPIServicesMapper.map(swadi_device_info['X_ScalarWebAPI_ServiceList']).each do |service|
50
+ swadi.services[service.id] = service
51
+ end
52
+ end
53
+ else
54
+ device = Device.new
55
+ end
56
+
57
+ device.name = device_info['friendlyName']
58
+ device.manufacturer = Manufacturer.new(device_info['manufacturer'], device_info['manufacturerURL'])
59
+ device.model = Model.new(device_info['modelName'], device_info['modelDescription'], device_info['modelURL'])
60
+
61
+ ServicesMapper.map(device_info['serviceList']).each do |service|
62
+ device.services[service.id] = service
63
+ end
64
+
65
+ device
66
+ end
67
+ end
68
+ end
69
+
70
+ class DeviceInfo
71
+ class << self
72
+ def fetch(location)
73
+ DeviceMapper.map(HTTParty.get(location)['root']['device'])
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,5 @@
1
+ M-SEARCH * HTTP/1.1
2
+ HOST: <%= host %>:<%= port %>
3
+ MAN: ssdp:discover
4
+ MX: <%= timeout %>
5
+ ST: urn:schemas-sony-com:service:ScalarWebAPI:1
@@ -0,0 +1,20 @@
1
+ require 'erb'
2
+
3
+ module SonyCameraRemote
4
+ module Discovery
5
+ class Request
6
+ TEMPLATE = File.read(File.join(File.dirname(__FILE__), 'm_search.erb'))
7
+ attr_reader :host, :port, :timeout
8
+
9
+ def initialize(host, port, timeout)
10
+ @host, @port, @timeout = host, port, timeout
11
+ end
12
+
13
+ def to_s
14
+ b = binding
15
+ result = ERB.new(TEMPLATE, 0, "").result(b)
16
+ result.split("\n").join("\r\n") << ("\r\n" * 2)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ module SonyCameraRemote
2
+ module Discovery
3
+ class Response
4
+ def initialize(raw)
5
+ raw.each_line do |line|
6
+ if match = line.match(/^LOCATION: (.*)/)
7
+ @location, _ = match.captures
8
+ end
9
+ end
10
+ end
11
+
12
+ def location
13
+ @location
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ require 'uri'
2
+
3
+ module SonyCameraRemote
4
+ module Services
5
+ class Service < Struct.new(:id, :type, :scpd_url, :control_url, :event_sub_url)
6
+ end
7
+
8
+ class ContentDirectoryService < Service
9
+
10
+ end
11
+
12
+ class ConnectionManagerService < Service
13
+
14
+ end
15
+
16
+ class ScalarWebAPIService < Service
17
+ attr_accessor :actionlist_url, :access_type
18
+
19
+ def base_uri
20
+ URI([actionlist_url, type].join('/'))
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module SonyCameraRemote
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sony_camera_remote/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'sony-camera-remote'
8
+ spec.version = SonyCameraRemote::VERSION
9
+ spec.authors = ['Nicholas E. Rabenau']
10
+ spec.email = ['nerab@gmx.at']
11
+ spec.description = %q{Provides a wrapper around to API for cameras that support the Sony [Camera Remote API](http://developer.sony.com/develop/cameras/).}
12
+ spec.summary = %q{Ruby API for the Sony Camera Remote API}
13
+ spec.homepage = "https://github.com/nerab/#{spec.name}"
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'json'
22
+ spec.add_dependency 'require_all'
23
+ spec.add_dependency 'system-getifaddrs'
24
+ spec.add_dependency 'httparty'
25
+
26
+ spec.add_development_dependency 'bundler'
27
+ spec.add_development_dependency 'rake'
28
+ spec.add_development_dependency 'guard-bundler'
29
+ spec.add_development_dependency 'guard-minitest'
30
+ spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'vcr', '~> 2.8.0'
32
+ spec.add_development_dependency 'webmock', '~> 1.17.1'
33
+ end
@@ -0,0 +1,95 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <root xmlns="urn:schemas-upnp-org:device-1-0" xmlns:dlna="urn:schemas-dlna-org:device-1-0" xmlns:av="urn:schemas-sony-com:av">
3
+ <specVersion>
4
+ <major>1</major>
5
+ <minor>0</minor>
6
+ </specVersion>
7
+ <device>
8
+ <dlna:X_DLNADOC xmlns:dlna="urn:schemas-dlna-org:device-1-0">DMS-1.50</dlna:X_DLNADOC>
9
+ <deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>
10
+ <friendlyName>HDR-AS30V</friendlyName>
11
+ <manufacturer>Sony Corporation</manufacturer>
12
+ <manufacturerURL>http://www.sony.com/</manufacturerURL>
13
+ <modelDescription>SonyDigitalMediaServer</modelDescription>
14
+ <modelName>SonyImagingDevice</modelName>
15
+ <modelURL>http://www.sony.net/</modelURL>
16
+ <UDN>uuid:00000000-0005-0010-8000-1c994c079994</UDN>
17
+ <serviceList>
18
+ <service>
19
+ <serviceType>urn:schemas-upnp-org:service:ContentDirectory:1</serviceType>
20
+ <serviceId>urn:upnp-org:serviceId:ContentDirectory</serviceId>
21
+ <SCPDURL>/CdsDesc.xml</SCPDURL>
22
+ <controlURL>/upnp/control/ContentDirectory</controlURL>
23
+ <eventSubURL>/upnp/event/ContentDirectory</eventSubURL>
24
+ </service>
25
+ <service>
26
+ <serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType>
27
+ <serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
28
+ <SCPDURL>/CmsDesc.xml</SCPDURL>
29
+ <controlURL>/upnp/control/ConnectionManager</controlURL>
30
+ <eventSubURL>/upnp/event/ConnectionManager</eventSubURL>
31
+ </service>
32
+ <service>
33
+ <serviceType>urn:schemas-sony-com:service:ScalarWebAPI:1</serviceType>
34
+ <serviceId>urn:schemas-sony-com:serviceId:ScalarWebAPI</serviceId>
35
+ <SCPDURL>/ScalarWebApiDesc.xml</SCPDURL>
36
+ <controlURL/>
37
+ <eventSubURL/>
38
+ </service>
39
+ </serviceList>
40
+ <iconList>
41
+ <icon>
42
+ <mimetype>image/jpeg</mimetype>
43
+ <width>48</width>
44
+ <height>48</height>
45
+ <depth>24</depth>
46
+ <url>/DLNA_camera_48.jpg</url>
47
+ </icon>
48
+ <icon>
49
+ <mimetype>image/jpeg</mimetype>
50
+ <width>120</width>
51
+ <height>120</height>
52
+ <depth>24</depth>
53
+ <url>/DLNA_camera_120.jpg</url>
54
+ </icon>
55
+ <icon>
56
+ <mimetype>image/png</mimetype>
57
+ <width>48</width>
58
+ <height>48</height>
59
+ <depth>24</depth>
60
+ <url>/DLNA_camera_48.png</url>
61
+ </icon>
62
+ <icon>
63
+ <mimetype>image/png</mimetype>
64
+ <width>120</width>
65
+ <height>120</height>
66
+ <depth>24</depth>
67
+ <url>/DLNA_camera_120.png</url>
68
+ </icon>
69
+ </iconList>
70
+ <av:X_ScalarWebAPI_DeviceInfo xmlns:av="urn:schemas-sony-com:av">
71
+ <av:X_ScalarWebAPI_Version>1.0</av:X_ScalarWebAPI_Version>
72
+ <av:X_ScalarWebAPI_ServiceList>
73
+ <av:X_ScalarWebAPI_Service>
74
+ <av:X_ScalarWebAPI_ServiceType>guide</av:X_ScalarWebAPI_ServiceType>
75
+ <av:X_ScalarWebAPI_ActionList_URL>http://10.0.0.1:10000/sony</av:X_ScalarWebAPI_ActionList_URL>
76
+ <av:X_ScalarWebAPI_AccessType/>
77
+ </av:X_ScalarWebAPI_Service>
78
+ <av:X_ScalarWebAPI_Service>
79
+ <av:X_ScalarWebAPI_ServiceType>accessControl</av:X_ScalarWebAPI_ServiceType>
80
+ <av:X_ScalarWebAPI_ActionList_URL>http://10.0.0.1:10000/sony</av:X_ScalarWebAPI_ActionList_URL>
81
+ <av:X_ScalarWebAPI_AccessType/>
82
+ </av:X_ScalarWebAPI_Service>
83
+ <av:X_ScalarWebAPI_Service>
84
+ <av:X_ScalarWebAPI_ServiceType>camera</av:X_ScalarWebAPI_ServiceType>
85
+ <av:X_ScalarWebAPI_ActionList_URL>http://10.0.0.1:10000/sony</av:X_ScalarWebAPI_ActionList_URL>
86
+ <av:X_ScalarWebAPI_AccessType/>
87
+ </av:X_ScalarWebAPI_Service>
88
+ </av:X_ScalarWebAPI_ServiceList>
89
+ <av:X_ScalarWebAPI_ImagingDevice>
90
+ <av:X_ScalarWebAPI_LiveView_URL>http://10.0.0.1:60152/liveview.JPG?%211234%21http%2dget%3a%2a%3aimage%2fjpeg%3a%2a%21%21%21%21%21</av:X_ScalarWebAPI_LiveView_URL>
91
+ <av:X_ScalarWebAPI_DefaultFunction>RemoteShooting</av:X_ScalarWebAPI_DefaultFunction>
92
+ </av:X_ScalarWebAPI_ImagingDevice>
93
+ </av:X_ScalarWebAPI_DeviceInfo>
94
+ </device>
95
+ </root>
@@ -0,0 +1,6 @@
1
+ M-SEARCH * HTTP/1.1
2
+ HOST: 239.255.255.250:1900
3
+ MAN: ssdp:discover
4
+ MX: 1
5
+ ST: urn:schemas-sony-com:service:ScalarWebAPI:1
6
+
@@ -0,0 +1,9 @@
1
+ HTTP/1.1 200 OK
2
+ CACHE-CONTROL: max-age=1800
3
+ EXT:
4
+ LOCATION: http://10.0.0.1:64321/DmsRmtDesc.xml
5
+ SERVER: UPnP/1.0 SonyImagingDevice/1.0
6
+ ST: urn:schemas-sony-com:service:ScalarWebAPI:1
7
+ USN: uuid:00000000-0005-0010-8000-1c994c079994::urn:schemas-sony-com:service:ScalarWebAPI:1
8
+ X-AV-Physical-Unit-Info: pa=""; pl=;
9
+ X-AV-Server-Info: av=5.0; hn=""; cn="Sony Corporation"; mn="SonyImagingDevice"; mv="1.0";
@@ -0,0 +1,26 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://10.0.0.1:10000/sony/camera
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"version":"1.0","params":[],"id":1,"method":"getApplicationInfo"}'
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Connection:
16
+ - close
17
+ Content-Length:
18
+ - '50'
19
+ Content-Type:
20
+ - application/json
21
+ body:
22
+ encoding: UTF-8
23
+ string: '{"id":1,"result":["Smart Remote Control","2.0.0"]}'
24
+ http_version:
25
+ recorded_at: Sun, 19 Jan 2014 18:14:29 GMT
26
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,26 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://10.0.0.1:10000/sony/camera
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"version":"1.0","params":[],"id":1,"method":"getApplicationInfo"}'
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Connection:
16
+ - close
17
+ Content-Length:
18
+ - '50'
19
+ Content-Type:
20
+ - application/json
21
+ body:
22
+ encoding: UTF-8
23
+ string: '{"id":1,"result":["Smart Remote Control","2.0.0"]}'
24
+ http_version:
25
+ recorded_at: Sun, 19 Jan 2014 18:14:30 GMT
26
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,26 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://10.0.0.1:10000/sony/camera
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"version":"1.0","params":[],"id":1,"method":"getAvailableApiList"}'
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Connection:
16
+ - close
17
+ Content-Length:
18
+ - '682'
19
+ Content-Type:
20
+ - application/json
21
+ body:
22
+ encoding: UTF-8
23
+ string: '{"id":1,"result":[["getMethodTypes","getAvailableApiList","setShootMode","getShootMode","getSupportedShootMode","getAvailableShootMode","setSteadyMode","getSteadyMode","getSupportedSteadyMode","getAvailableSteadyMode","setViewAngle","getViewAngle","getSupportedViewAngle","getAvailableViewAngle","setMovieQuality","getMovieQuality","getSupportedMovieQuality","getAvailableMovieQuality","startLiveview","stopLiveview","actTakePicture","startMovieRec","stopMovieRec","startIntervalStillRec","stopIntervalStillRec","setCameraFunction","getCameraFunction","getSupportedCameraFunction","getAvailableCameraFunction","getStorageInformation","getApplicationInfo","getVersions","getEvent"]]}'
24
+ http_version:
25
+ recorded_at: Sun, 19 Jan 2014 15:47:36 GMT
26
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,26 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://10.0.0.1:10000/sony/camera
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"version":"1.0","params":[],"id":1,"method":"actTakePicture"}'
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Connection:
16
+ - close
17
+ Content-Length:
18
+ - '134'
19
+ Content-Type:
20
+ - application/json
21
+ body:
22
+ encoding: UTF-8
23
+ string: '{"id":1,"result":[["http://10.0.0.1:60152/pict140119_1918300000.JPG?%211234%21http%2dget%3a%2a%3aimage%2fjpeg%3a%2a%21%21%21%21%21"]]}'
24
+ http_version:
25
+ recorded_at: Sun, 19 Jan 2014 18:18:30 GMT
26
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,26 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://10.0.0.1:10000/sony/camera
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"version":"1.0","params":[],"id":1,"method":"getShootMode"}'
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Connection:
16
+ - close
17
+ Content-Length:
18
+ - '35'
19
+ Content-Type:
20
+ - application/json
21
+ body:
22
+ encoding: UTF-8
23
+ string: '{"id":1,"result":["intervalstill"]}'
24
+ http_version:
25
+ recorded_at: Sun, 19 Jan 2014 14:10:26 GMT
26
+ recorded_with: VCR 2.8.0
@@ -0,0 +1,26 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: post
5
+ uri: http://10.0.0.1:10000/sony/camera
6
+ body:
7
+ encoding: UTF-8
8
+ string: '{"version":"1.0","params":[],"id":1,"method":"getShootMode"}'
9
+ headers: {}
10
+ response:
11
+ status:
12
+ code: 200
13
+ message: OK
14
+ headers:
15
+ Connection:
16
+ - close
17
+ Content-Length:
18
+ - '27'
19
+ Content-Type:
20
+ - application/json
21
+ body:
22
+ encoding: UTF-8
23
+ string: '{"id":1,"result":["movie"]}'
24
+ http_version:
25
+ recorded_at: Sun, 19 Jan 2014 14:09:34 GMT
26
+ recorded_with: VCR 2.8.0