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.

Parameters:

  • endpoints (Hash)
  • reconnect_by (Proc) (defaults to: nil)


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}]

Parameters:

  • method (String)
  • params (Array, String) (defaults to: [])

    ‘params’ element of the request

  • service_type (String)

    Service type of the API

  • id (Fixnum)

    ID for the request/response pair

  • version (String)

    Version of the API

  • timeout (Fixnum)

    Timeout in seconds for waiting until the API is available



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.

Returns:

  • (Hash)

    Response of 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.

Parameters:

  • params (Array, String) (defaults to: [true])

Returns:

  • (Hash)

    Response of API



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

Parameters:

  • api_or_group_name (Symbol)

    The API or API group name

Returns:

  • (Boolean)

    true if supported, false otherwise.



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’.

Parameters:

  • timeout (Fixnum) (defaults to: DEFAULT_PARAM_CHANGE_TIMEOUT)

    Timeout in seconds for changing parameter

  • polling (Boolean) (defaults to: nil)

    This method has 3 patterns to handle long polling flag by polling argument.

    • default : The first getEvent call doesn’t use long polling, but then later always use long polling.

    • polling = true : Always use long polling in getEvent call

    • polling = false : Never use long polling in getEvent call

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