Class: SonyCameraRemoteAPI::CameraAPIManager

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Logging
Defined in:
lib/sony_camera_remote_api/camera_api.rb

Overview

Camera API layer class, which enables us to handle camera APIs more friendly.

Constant Summary collapse

DEFAULT_API_CALL_TIMEOUT =

Default timeout for waiting camera API becomes available

8
DEFAULT_PARAM_CHANGE_TIMEOUT =

Default timeout for waiting camera parameter changes

15

Instance Method Summary collapse

Methods included from Logging

configure_logger_for, #log, log_file, logger_for, #set_level, #set_output

Constructor Details

#initialize(endpoints, reconnect_by: nil) ⇒ CameraAPIManager

Create CameraAPIManager object.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/sony_camera_remote_api/camera_api.rb', line 29

def initialize(endpoints, reconnect_by: nil)
  @http = HTTPClient.new
  @http.connect_timeout  = @http.send_timeout = @http.receive_timeout = 30

  Retrying.new(reconnect_by, @http).reconnect_and_retry do
    @raw_api_manager = RawAPIManager.new endpoints, @http
  end

  @api_group_manager = CameraAPIGroupManager.new self

  @retrying = Retrying.new(reconnect_by, @http).add_common_hook do
    startRecMode! timeout: 0
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, params = [], *args, **opts) ⇒ Object

Ghost method, which handles almost API calls. You can call an API as a method with the same name. We don’t have to specify service_type and version for almost APIs except some APIs having multiple service types and versions.

When ! is appended to the end of the method name, it does not raise exception even if any error occurred.

Examples:

# Initialize
cam = SonyCameraRemoteAPI::Camera.new
cam.change_function_to_shoot 'still', 'Single'

# Call getMethodTypes API with parameter: ['1.0'], service type: 'camera' and id: 1.
response = cam.getMethodTypes ['1.0'], service_type: 'camera', id: 1
puts response.id
response.results.each do |r|
  puts '----'
  puts r
end

# Call setCurrentTime API if supported (does not raise exception if not supported)
cam.setCurrentTime! [{'dateTime' => Time.now.utc.iso8601,
                    'timeZoneOffsetMinute' => 540,
                    'dstOffsetMinute' => 0}]


139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/sony_camera_remote_api/camera_api.rb', line 139

def method_missing(method, params = [], *args, **opts)
  ignore_error = true if method.to_s.end_with? '!'
  method = method.to_s.delete('!').to_sym
  params = [params] unless params.is_a? Array
  response = nil
  @retrying.reconnect_and_retry do
    begin
      name, service, id, version = @raw_api_manager.search_method(method, **opts)
      log.debug "calling: #{name}"
      if service == 'camera' || name == ''
        if opts[:timeout]
          response = call_api_safe(service, name, params, id, version, opts[:timeout], **opts)
        else
          response = call_api_safe(service, name, params, id, version, **opts)
        end
      else
        response = @raw_api_manager.call_api(service, name, params, id, version)
      end
    rescue APIForbidden, APINotSupported, APINotAvailable, IllegalArgument, HTTPClient::BadResponseError => e
      if ignore_error
        return nil
      else
        raise e
      end
    end
  end
  response
end

Instance Method Details

#getAvailableApiList(params = [], **opts) ⇒ Hash

getAvailableApiList API.



66
67
68
69
70
71
72
# File 'lib/sony_camera_remote_api/camera_api.rb', line 66

def getAvailableApiList(params = [], **opts)
  name, service, id, version = @raw_api_manager.search_method(__method__, **opts)
  log.debug "calling: #{name}"
  @retrying.reconnect_and_retry do
    @raw_api_manager.call_api(service, name, params, id, version)
  end
end

#getEvent(params = [true], **opts) ⇒ Hash

getEvent API. Long polling flag is set true as default.



49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/sony_camera_remote_api/camera_api.rb', line 49

def getEvent(params = [true], **opts)
  params = [params] unless params.is_a? Array
  name, service, id, version = @raw_api_manager.search_method(__method__, **opts)
  response = nil
  @retrying.reconnect_and_retry do
    if params[0]
      response = @raw_api_manager.call_api_async(service, name, params, id, version, opts[:timeout])
    else
      response = @raw_api_manager.call_api(service, name, params, id, version)
    end
  end
  response
end

#support?(api_or_group_name) ⇒ Boolean

Get whether the API or API group is supported by a camera.

Examples:

# Initialize
cam = SonyCameraRemoteAPI::Camera.new
cam.change_function_to_shoot 'still', 'Single'

# Check if actZoom API is supported.
puts cam.support? :actZoom
# Check if ZoomSetting API group is supported.
puts cam.support? :ZoomSetting


181
182
183
# File 'lib/sony_camera_remote_api/camera_api.rb', line 181

def support?(api_or_group_name)
  @raw_api_manager.support?(api_or_group_name) || @api_group_manager.support_group?(api_or_group_name)
end

#wait_event(timeout: DEFAULT_PARAM_CHANGE_TIMEOUT, polling: nil) {|Array<Hash>| ... } ⇒ Object

TODO:

add example

Wait until ‘getEvent’ result response meets the specified condition. This method can be used to wait after calling APIs that change any camera parameters, such as ‘setCameraFunction’.

Yields:

  • (Array<Hash>)

    The block that returns true or false based on the condition of the response of getEvent

Yield Parameters:

  • result (Array<Hash>)

    the result element in the response of getEvent

Raises:

  • EventTimeoutError



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/sony_camera_remote_api/camera_api.rb', line 86

def wait_event(timeout: DEFAULT_PARAM_CHANGE_TIMEOUT, polling: nil, &block)
  start_time = Time.now if timeout
  # Long-polling is disabled only at the first call
  poll = polling.nil? ? false : polling
  while true do
    response = get_event_both(poll, timeout: timeout)
    begin
      break if yield(response.result)
    rescue StandardError => e
      # Catch all exceptions raised by given block, e.g. NoMethodError of '[]' for nil class.
    end
    sleep 0.1
    if timeout
      raise EventTimeoutError, "Timeout expired: #{timeout} sec." if Time.now - start_time > timeout
    end
    poll = polling.nil? ? true : polling
    log.debug "Waiting for #{block} returns true..."
  end
  log.debug "OK. (#{format('%.2f', Time.now-start_time)} sec.)"
  # pp response['result']
  response['result']
end