class SonyCameraRemoteAPI::RawAPIManager

Raw API layer class, which call APIs by HTTP POST to endpoint URLs and recieve the response.

Attributes

apis[R]

Public Class Methods

new(endpoints, httpclient) click to toggle source

@param [Hash] endpoints Endpoint URIs

# File lib/sony_camera_remote_api/raw_api.rb, line 33
def initialize(endpoints, httpclient)
  @endpoints = endpoints
  @http = httpclient

  unless call_api('camera', 'getApplicationInfo', [], 1, '1.0').result[1] >= '2.0.0'
    raise ServerNotCompatible, 'API version of the server < 2.0.0.'
  end
  @apis = make_api_list
end

Public Instance Methods

call_api(service_type, method, params, id, version) click to toggle source

Call API by HTTP POST. @param [String] service_type @param [String] method @param [Array, String] params @param [Fixnum] id @param [String] version @return [Hash] Response of API

# File lib/sony_camera_remote_api/raw_api.rb, line 75
def call_api(service_type, method, params, id, version)
  params = [params] unless params.is_a? Array
  request = {
    'method' => method,
    'params' => params,
    'id' => id,
    'version' => version
  }
  # log.debug request
  begin
    raw_response = @http.post_content(@endpoints[service_type], request.to_json)
  rescue HTTPClient::BadResponseError => e
    if e.res.status_code == 403
      raise APIForbidden.new, "Method '#{method}' returned 403 Forbidden error. Maybe this method is not allowed to general users."
    else
      raise e
    end
  end
  response = JSON.parse(raw_response)
  if response.key? 'error'
    raise APIExecutionError.new(method, request, response), "Request:#{request}, Response:#{response}"
  end
  # log.debug response
  response
end
call_api_async(service_type, method, params, id, version, timeout = nil) click to toggle source

Asynchronous call API by HTTP POST. Currently only used by 'getEvent' API with long polling. @param [String] service_type @param [String] method @param [Array, String] params @param [Fixnum] id @param [String] version @param [Fixnum] timeout Timeout in seconds for waiting response @return [Hash] Response of API

# File lib/sony_camera_remote_api/raw_api.rb, line 111
def call_api_async(service_type, method, params, id, version, timeout = nil)
  request = {
    'method' => method,
    'params' => params,
    'id' => id,
    'version' => version
  }
  conn = @http.post_async(@endpoints[service_type], request.to_json)
  start_time = Time.now if timeout
  loop do
    break if conn.finished?
    if timeout
      raise EventTimeoutError, "Timeout expired: #{timeout} sec." if Time.now - start_time > timeout
    end
    sleep 0.1
  end
  raw_response = conn.pop.content.read
  response = JSON.parse(raw_response)
  if response.key? 'error'
    raise APIExecutionError.new(method, request, response), "Request:#{request}, Response:#{response}"
  end
  response
end
make_api_list() click to toggle source

Make supported API list @return [Hash<Symbol, APIInfo>] API list

# File lib/sony_camera_remote_api/raw_api.rb, line 46
def make_api_list
  apis = {}
  @endpoints.keys.each do |s|
    versions = call_api(s, 'getVersions', [], 1, '1.0')['result'][0].sort.reverse
    versions.each do |v|
      results = call_api(s, 'getMethodTypes', [v], 1, '1.0')['results']
      next unless results
      results.each do |r|
        name = r[0].to_sym
        if apis.key?(name)
          apis[name].versions << v unless apis[name].versions.index(v)
          apis[name].service_types << s unless apis[name].service_types.index(s)
        else
          apis[name] = APIInfo.new(r[0], v, s)
        end
      end
    end
  end
  apis
end
search_method(method, **opts) click to toggle source

Search given API from API list. @param [Symbol] method The method name @param [String] service @param [Fixnum] id @param [String] version

# File lib/sony_camera_remote_api/raw_api.rb, line 141
def search_method(method, **opts)
  if @apis && @apis.key?(method)
    api_info = @apis[method]
    # use ID=1 if not given
    id = opts.key?(:id) ? opts[:id] : 1
    if opts.key? :version
      if api_info.versions.include? opts[:version]
        version = opts[:version]
      else
        raise APIVersionInvalid, "The version '#{opts[:version]}' is invalid for method '#{method}'."
      end
    else
      # use newest version if not given
      if api_info.multi_versions?
        # log.debug "Using newest version '#{api_info.versions[0]}' for method '#{method}'."
      end
      version = api_info.versions[0]
    end
    if opts.key? :service_type
      service = opts[:service_type]
      if api_info.service_types.include? opts[:service_type]
        service = opts[:service_type]
      else
        raise ServiceTypeInvalid, "The service type '#{opts[:service_type]}' is invalid for method '#{method}'."
      end
    else
      # raise error if service type is not given for method having multi service types
      if api_info.multi_service_types?
        strs = api_info.service_types.map { |item| "'#{item}'" }
        raise ServiceTypeNotGiven, "The method '#{method}' must be specified service type from #{strs.join(' or ')}."
      end
      service = api_info.service_types[0]
    end
    return api_info.name, service, id, version
  else
    raise APINotSupported.new, "The method '#{method}' is not supported by this camera."
  end
end
support?(method) click to toggle source

@param [Symbol] method The method name @return [Boolean] true if the API is supported by this camera. false otherwise.

# File lib/sony_camera_remote_api/raw_api.rb, line 183
def support?(method)
  @apis.key? method
end