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)

28
29
30
31
32
# File 'lib/sony_camera_remote_api/camera_api.rb', line 28

def initialize(endpoints, reconnect_by: nil)
  @raw_api_manager = RawAPIManager.new endpoints
  @api_group_manager = CameraAPIGroupManager.new self
  @reconnect_by = reconnect_by
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


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/sony_camera_remote_api/camera_api.rb', line 128

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
  reconnect_and_retry do
    begin
      name, service, id, version = @raw_api_manager.search_method(method, **opts)
      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


56
57
58
59
60
61
# File 'lib/sony_camera_remote_api/camera_api.rb', line 56

def getAvailableApiList(params = [], **opts)
  name, service, id, version = @raw_api_manager.search_method(__method__, **opts)
  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


39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/sony_camera_remote_api/camera_api.rb', line 39

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


169
170
171
# File 'lib/sony_camera_remote_api/camera_api.rb', line 169

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)

    Timeout in seconds for changing parameter

  • polling (Boolean)

    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


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/sony_camera_remote_api/camera_api.rb', line 75

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