Class: SonyCameraRemoteAPI::RawAPIManager

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/sony_camera_remote_api/raw_api.rb

Overview

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

Defined Under Namespace

Classes: APIInfo

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logging

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

Constructor Details

#initialize(endpoints, httpclient) ⇒ RawAPIManager

Returns a new instance of RawAPIManager.

Parameters:

  • endpoints (Hash)

    Endpoint URIs



33
34
35
36
37
38
39
40
41
# 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

Instance Attribute Details

#apisObject (readonly)

Returns the value of attribute apis.



29
30
31
# File 'lib/sony_camera_remote_api/raw_api.rb', line 29

def apis
  @apis
end

Instance Method Details

#call_api(service_type, method, params, id, version) ⇒ Hash

Call API by HTTP POST.

Parameters:

  • service_type (String)
  • method (String)
  • params (Array, String)
  • id (Fixnum)
  • version (String)

Returns:

  • (Hash)

    Response of API



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# 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) ⇒ Hash

Asynchronous call API by HTTP POST. Currently only used by ‘getEvent’ API with long polling.

Parameters:

  • service_type (String)
  • method (String)
  • params (Array, String)
  • id (Fixnum)
  • version (String)
  • timeout (Fixnum) (defaults to: nil)

    Timeout in seconds for waiting response

Returns:

  • (Hash)

    Response of API



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# 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_listHash<Symbol, APIInfo>

Make supported API list

Returns:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# 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) ⇒ Object

Search given API from API list.

Parameters:

  • method (Symbol)

    The method name

  • service (String)
  • id (Fixnum)
  • version (String)


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
167
168
169
170
171
172
173
174
175
176
177
178
# 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) ⇒ Boolean

Returns true if the API is supported by this camera. false otherwise.

Parameters:

  • method (Symbol)

    The method name

Returns:

  • (Boolean)

    true if the API is supported by this camera. false otherwise.



183
184
185
# File 'lib/sony_camera_remote_api/raw_api.rb', line 183

def support?(method)
  @apis.key? method
end