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) ⇒ RawAPIManager

Returns a new instance of RawAPIManager

Parameters:

  • endpoints (Hash)

    Endpoint URIs


33
34
35
36
37
38
39
40
41
42
# File 'lib/sony_camera_remote_api/raw_api.rb', line 33

def initialize(endpoints)
  @endpoints = endpoints
  @cli = HTTPClient.new
  @cli.connect_timeout  = @cli.send_timeout = @cli.receive_timeout = 30

  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


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

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 = @cli.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


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/sony_camera_remote_api/raw_api.rb', line 112

def call_api_async(service_type, method, params, id, version, timeout = nil)
  request = {
    'method' => method,
    'params' => params,
    'id' => id,
    'version' => version
  }
  conn = @cli.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:


47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/sony_camera_remote_api/raw_api.rb', line 47

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

#reset_connectionvoid

This method returns an undefined value.

Reset HTTPClient.


191
192
193
# File 'lib/sony_camera_remote_api/raw_api.rb', line 191

def reset_connection
  @cli.reset_all
end

#search_method(method, **opts) ⇒ Object

Search given API from API list.

Parameters:

  • method (Symbol)

    The method name

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

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
179
# File 'lib/sony_camera_remote_api/raw_api.rb', line 142

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.


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

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