tesla-api 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +40 -0
- data/Rakefile +10 -0
- data/fixtures/vcr_cassettes/charge_state.yml +134 -0
- data/fixtures/vcr_cassettes/climate_state.yml +134 -0
- data/fixtures/vcr_cassettes/connection.yml +91 -0
- data/fixtures/vcr_cassettes/drive_state.yml +134 -0
- data/fixtures/vcr_cassettes/gui_settings.yml +134 -0
- data/fixtures/vcr_cassettes/vehicle.yml +91 -0
- data/fixtures/vcr_cassettes/vehicle_state.yml +134 -0
- data/lib/tesla-api.rb +16 -0
- data/lib/tesla-api/charge_state.rb +87 -0
- data/lib/tesla-api/climate_state.rb +55 -0
- data/lib/tesla-api/connection.rb +58 -0
- data/lib/tesla-api/data.rb +52 -0
- data/lib/tesla-api/drive_state.rb +37 -0
- data/lib/tesla-api/errors.rb +41 -0
- data/lib/tesla-api/gui_settings.rb +34 -0
- data/lib/tesla-api/private_api.rb +157 -0
- data/lib/tesla-api/tesla_api.rb +4 -0
- data/lib/tesla-api/vehicle.rb +257 -0
- data/lib/tesla-api/vehicle_state.rb +92 -0
- data/lib/tesla-api/version.rb +4 -0
- data/tesla-api.gemspec +23 -0
- data/test/helper.rb +10 -0
- data/test/test_charge_state.rb +72 -0
- data/test/test_climate_state.rb +52 -0
- data/test/test_connection.rb +32 -0
- data/test/test_drive_state.rb +36 -0
- data/test/test_gui_settings.rb +36 -0
- data/test/test_vehicle.rb +32 -0
- data/test/test_vehicle_state.rb +80 -0
- metadata +135 -0
data/lib/tesla-api.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'httpclient'
|
3
|
+
|
4
|
+
require "tesla-api/tesla_api"
|
5
|
+
require "tesla-api/version"
|
6
|
+
require "tesla-api/data"
|
7
|
+
require "tesla-api/private_api"
|
8
|
+
require "tesla-api/connection"
|
9
|
+
require "tesla-api/charge_state"
|
10
|
+
require "tesla-api/climate_state"
|
11
|
+
require "tesla-api/drive_state"
|
12
|
+
require "tesla-api/errors"
|
13
|
+
require "tesla-api/gui_settings"
|
14
|
+
require "tesla-api/vehicle"
|
15
|
+
require "tesla-api/vehicle_state"
|
16
|
+
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module TeslaAPI
|
2
|
+
|
3
|
+
# Defines the current charge state of the vehicle
|
4
|
+
class ChargeState < Data
|
5
|
+
##
|
6
|
+
# :method: charging_state
|
7
|
+
# Charging state ("Complete", "Charging")
|
8
|
+
|
9
|
+
##
|
10
|
+
# :method charging_to_max?
|
11
|
+
# true if currently performing a range charge
|
12
|
+
|
13
|
+
##
|
14
|
+
# :method: battery_range_miles
|
15
|
+
# Rated miles for the current charge
|
16
|
+
|
17
|
+
##
|
18
|
+
# :method: estimated_battry_range_miles
|
19
|
+
# Range estimated from current driving
|
20
|
+
|
21
|
+
##
|
22
|
+
# :method: ideal_battery_range_miles
|
23
|
+
# Ideal range for the current charge
|
24
|
+
|
25
|
+
##
|
26
|
+
# :method: battery_percentage
|
27
|
+
# Percentage of battery charge
|
28
|
+
|
29
|
+
##
|
30
|
+
# :method: battery_current_flow
|
31
|
+
# Current flowing into the battery
|
32
|
+
|
33
|
+
##
|
34
|
+
# :method: charger_voltage
|
35
|
+
# Current voltage being used to charge battery
|
36
|
+
|
37
|
+
##
|
38
|
+
# :method: charger_pilot_amperage
|
39
|
+
# Max amperage allowed by the charger
|
40
|
+
|
41
|
+
##
|
42
|
+
# :method: charger_actual_amperage
|
43
|
+
# Current amperage being drawn into battery
|
44
|
+
|
45
|
+
##
|
46
|
+
# :method: charger_power
|
47
|
+
# Kilowatt of charger (rounded down)
|
48
|
+
|
49
|
+
##
|
50
|
+
# :method: hours_to_full_charge
|
51
|
+
# Hours remaining until the vehicle is fully charged
|
52
|
+
|
53
|
+
##
|
54
|
+
# :method: charge_rate_miles_per_hour
|
55
|
+
# Miles of range being added per hour
|
56
|
+
|
57
|
+
##
|
58
|
+
# :method: charge_port_open?
|
59
|
+
# true if the charge port is open
|
60
|
+
|
61
|
+
##
|
62
|
+
# :method: supercharging?
|
63
|
+
# true if charging via a Tesla SuperCharger
|
64
|
+
|
65
|
+
def initialize(data) # :nodoc:
|
66
|
+
ivar_from_data("charging_state", "charging_state", data)
|
67
|
+
ivar_from_data("charging_to_max", "charge_to_max_range", data)
|
68
|
+
ivar_from_data("battery_range_miles", "battery_range", data)
|
69
|
+
ivar_from_data("estimated_battry_range_miles", "est_battery_range", data)
|
70
|
+
ivar_from_data("ideal_battery_range_miles", "ideal_battery_range", data)
|
71
|
+
ivar_from_data("battery_percentage", "battery_level", data)
|
72
|
+
ivar_from_data("battery_current_flow", "battery_current", data)
|
73
|
+
ivar_from_data("charger_voltage", "charger_voltage", data)
|
74
|
+
ivar_from_data("charger_pilot_amperage", "charger_pilot_current", data)
|
75
|
+
ivar_from_data("charger_actual_amperage", "charger_actual_current", data)
|
76
|
+
ivar_from_data("charger_power", "charger_power", data)
|
77
|
+
ivar_from_data("hours_to_full_charge", "time_to_full_charge", data)
|
78
|
+
ivar_from_data("charge_rate_miles_per_hour", "charge_rate", data)
|
79
|
+
ivar_from_data("charge_port_open", "charge_port_door_open", data)
|
80
|
+
ivar_from_data("supercharging", "fast_charger_present", data)
|
81
|
+
|
82
|
+
@charging = charging_state == "Charging"
|
83
|
+
@charge_complete = charging_state == "Complete"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module TeslaAPI
|
2
|
+
# Defines the climate state of the vehicle.
|
3
|
+
#
|
4
|
+
class ClimateState < Data
|
5
|
+
##
|
6
|
+
# :method: inside_temp_celcius
|
7
|
+
# Temperature (celcius) inside the vehicle
|
8
|
+
|
9
|
+
##
|
10
|
+
# :method: outside_temp_celcius
|
11
|
+
# Temperature (celcius) outside the vehicle
|
12
|
+
|
13
|
+
##
|
14
|
+
# :method: driver_temp_setting_celcius
|
15
|
+
# Temperature (celcius) the driver has set
|
16
|
+
|
17
|
+
##
|
18
|
+
# :method: passenger_temp_setting_celcius
|
19
|
+
# Temperature (celcius) the passenger has set
|
20
|
+
|
21
|
+
##
|
22
|
+
# :method: fan_speed
|
23
|
+
# 0 to 6 (or nil)
|
24
|
+
|
25
|
+
##
|
26
|
+
# :method: auto_conditioning_on?
|
27
|
+
# true if auto air conditioning is on
|
28
|
+
|
29
|
+
##
|
30
|
+
# :method: front_defroster_on?
|
31
|
+
# true if the front defroster is on
|
32
|
+
|
33
|
+
##
|
34
|
+
# :method: rear_defroster_on?
|
35
|
+
# true if the rear defroster is on
|
36
|
+
|
37
|
+
##
|
38
|
+
# :method: fan_on?
|
39
|
+
# true if the fan is on
|
40
|
+
|
41
|
+
def initialize(data) # :nodoc:
|
42
|
+
ivar_from_data("inside_temp_celcius", "inside_temp", data)
|
43
|
+
ivar_from_data("outside_temp_celcius", "outside_temp", data)
|
44
|
+
ivar_from_data("driver_temp_setting_celcius", "driver_temp_setting", data)
|
45
|
+
ivar_from_data("passenger_temp_setting_celcius", "passenger_temp_setting", data)
|
46
|
+
ivar_from_data("fan_speed", "fan_speed", data)
|
47
|
+
|
48
|
+
@auto_conditioning_on = !!data["is_auto_conditioning_on"]
|
49
|
+
@front_defroster_on = !!data["is_front_defroster_on"]
|
50
|
+
@rear_defroster_on = !!data["is_rear_defroster_on"]
|
51
|
+
@fan_on = !data["fan_status"].nil?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module TeslaAPI
|
2
|
+
# Connection object to the Tesla Model S HTTP API endpoint.
|
3
|
+
class Connection
|
4
|
+
include PrivateAPI
|
5
|
+
|
6
|
+
# email address of logged in user
|
7
|
+
attr_reader :email
|
8
|
+
|
9
|
+
# password of logged in user
|
10
|
+
attr_reader :password
|
11
|
+
|
12
|
+
# Host for status/command related API
|
13
|
+
HOST = "https://portal.vn.teslamotors.com"
|
14
|
+
|
15
|
+
# Host for streaming API
|
16
|
+
STREAMING_HOST = "https://streaming.vn.teslamotors.com"
|
17
|
+
|
18
|
+
# Supply the email and password for login to teslamotors.com
|
19
|
+
def initialize(email, password)
|
20
|
+
@email = email
|
21
|
+
@password = password
|
22
|
+
|
23
|
+
@client = HTTPClient.new
|
24
|
+
@client.set_cookie_store("cookie.dat")
|
25
|
+
|
26
|
+
login(email, password)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Call to see all HTTP traffic to and from the API
|
30
|
+
def debug!
|
31
|
+
@client.debug_dev = STDOUT
|
32
|
+
end
|
33
|
+
|
34
|
+
# Convenience method to return the first Vehicle
|
35
|
+
def vehicle
|
36
|
+
vehicles.first
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns Vehicle objects for all vehicles the account contains
|
40
|
+
def vehicles
|
41
|
+
@vehicles ||= begin
|
42
|
+
_, json = get_json("/vehicles")
|
43
|
+
json.map { |data| Vehicle.new(self, data) }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Force the vehicles to reload (in case some of the data has changed)
|
48
|
+
def reload!
|
49
|
+
@vehicles = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Logged into the API
|
53
|
+
def logged_in?
|
54
|
+
@logged_in
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module TeslaAPI
|
2
|
+
# Base class for all data responses from the HTTP API
|
3
|
+
#
|
4
|
+
# Defines an instance_variable? method for each instance_variable defined allowing for
|
5
|
+
# methods such as __________?
|
6
|
+
#
|
7
|
+
# Also overrides #inspect to elimiante the back reference to the connection object
|
8
|
+
class Data
|
9
|
+
def method_missing(method_name, *args, &block) # :nodoc:
|
10
|
+
if has_query_ivar_method?(method_name)
|
11
|
+
instance_variable_get(ivar_for_method_name(method_name))
|
12
|
+
else
|
13
|
+
super(symbol, *args, &block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond_to_missing?(method_name, include_private = false) # :nodoc:
|
18
|
+
has_query_ivar_method?(method_name) || super
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect # :nodoc:
|
22
|
+
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} #{inspect_ivars}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
def ivar_from_data(name, data_key, data) # :nodoc:
|
26
|
+
instance_variable_set("@#{name}".to_sym, data[data_key])
|
27
|
+
|
28
|
+
self.class.send(:attr_reader, name.to_sym)
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def ivar_for_method_name(method_name) # :nodoc:
|
34
|
+
"@#{method_name.to_s.gsub(/\?$/,"")}".to_sym
|
35
|
+
end
|
36
|
+
|
37
|
+
def has_query_ivar_method?(method_name) # :nodoc:
|
38
|
+
method = method_name.to_s
|
39
|
+
|
40
|
+
method =~ /(.+)\?/ && instance_variables.include?(ivar_for_method_name(method_name))
|
41
|
+
end
|
42
|
+
|
43
|
+
def inspect_ivars # :nodoc:
|
44
|
+
ivars_for_inspect.map { |ivar| "#{ivar}=#{instance_variable_get(ivar)}" }.join(" ")
|
45
|
+
end
|
46
|
+
|
47
|
+
def ivars_for_inspect # :nodoc:
|
48
|
+
(instance_variables - [:@tesla])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module TeslaAPI
|
2
|
+
# Data defining the driving state of the the vehicle
|
3
|
+
class DriveState < Data
|
4
|
+
# Time when GPS data was recorded
|
5
|
+
attr_reader :gps_timestamp
|
6
|
+
|
7
|
+
##
|
8
|
+
# :method: shift_state
|
9
|
+
# Unknown
|
10
|
+
|
11
|
+
##
|
12
|
+
# :method: speed
|
13
|
+
# Vehicle speed (units?)
|
14
|
+
|
15
|
+
##
|
16
|
+
# :method: latitude
|
17
|
+
# Lattitude of vehicle
|
18
|
+
|
19
|
+
##
|
20
|
+
# :method: longitude
|
21
|
+
# Longitude of vehicle
|
22
|
+
|
23
|
+
##
|
24
|
+
# :method: heading
|
25
|
+
# Compass heading (0 to 360) degrees
|
26
|
+
|
27
|
+
def initialize(data) # :nodoc:
|
28
|
+
ivar_from_data("shift_state", "shift_state", data)
|
29
|
+
ivar_from_data("speed", "speed", data)
|
30
|
+
ivar_from_data("latitude", "latitude", data)
|
31
|
+
ivar_from_data("longitude", "longitude", data)
|
32
|
+
ivar_from_data("heading", "heading", data)
|
33
|
+
@gps_timestamp = Time.at(data["gps_as_of"])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module TeslaAPI
|
2
|
+
# Exceptions thrown by the TeslaAPI
|
3
|
+
module Errors
|
4
|
+
# JSON cannot be parsed
|
5
|
+
class InvalidJSON < StandardError
|
6
|
+
# JSON parsing error details
|
7
|
+
attr_reader :error
|
8
|
+
|
9
|
+
def initialize(error) # :nodoc:
|
10
|
+
@error = error
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s # :nodoc:
|
14
|
+
error.to_s
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Thrown when the action requires a logged in connection
|
19
|
+
class NotLoggedIn < StandardError
|
20
|
+
end
|
21
|
+
|
22
|
+
# Thrown when the API returns a failure state
|
23
|
+
class APIFailure < StandardError
|
24
|
+
end
|
25
|
+
|
26
|
+
# Thrown when the response is invalid (non 200-OK HTTP result)
|
27
|
+
class InvalidResponse < StandardError
|
28
|
+
# Response object from httpclient
|
29
|
+
attr_reader :response
|
30
|
+
|
31
|
+
def initialize(response) # :nodoc:
|
32
|
+
@response = response
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s # :nodoc:
|
36
|
+
"Invalid Response: #{response.inspect}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module TeslaAPI
|
2
|
+
# Defines the current user settings for the vehicle's graphical display
|
3
|
+
class GUISettings < Data
|
4
|
+
##
|
5
|
+
# :method: gui_distance_units
|
6
|
+
# Units ("mi/hr") for showing range
|
7
|
+
|
8
|
+
##
|
9
|
+
# :method: gui_temperature_units
|
10
|
+
# Units ("F", "C") for showing temperaturs
|
11
|
+
|
12
|
+
##
|
13
|
+
# :method: gui_charge_rate_units
|
14
|
+
# Units ("kW") for showing charge rage
|
15
|
+
|
16
|
+
##
|
17
|
+
# :method: gui_range_display
|
18
|
+
# Units ("Rated", "Ideal") for showing range
|
19
|
+
|
20
|
+
# true if the UI show 24 hour time (e.g. 17:45)
|
21
|
+
def gui_24_hour_time?
|
22
|
+
@gui_24_hour_time
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize(data) # :nodoc:
|
26
|
+
ivar_from_data("gui_distance_units", "gui_distance_units", data)
|
27
|
+
ivar_from_data("gui_temperature_units", "gui_temperature_units", data)
|
28
|
+
ivar_from_data("gui_charge_rate_units", "gui_charge_rate_units", data)
|
29
|
+
ivar_from_data("gui_24_hour_time", "gui_24_hour_time", data)
|
30
|
+
ivar_from_data("gui_range_display", "gui_range_display", data)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module TeslaAPI
|
2
|
+
module PrivateAPI # :nodoc:
|
3
|
+
def login(email, password)
|
4
|
+
params = { "user_session[email]" => email,
|
5
|
+
"user_session[password]" => password }
|
6
|
+
|
7
|
+
response = @client.post(Connection::HOST + "/login", params)
|
8
|
+
|
9
|
+
@logged_in = (response.status_code == HTTP::Status::FOUND)
|
10
|
+
end
|
11
|
+
|
12
|
+
def stream(vehicle)
|
13
|
+
raise "Doesn't work yet"
|
14
|
+
|
15
|
+
client = HTTPClient.new
|
16
|
+
|
17
|
+
uri = Connection::STREAMING_HOST + "/stream/#{vehicle.vehicle_id}/?values=speed,odometer,soc,elevation,est_heading,est_lat,est_lng,power,shift_state"
|
18
|
+
|
19
|
+
client.set_basic_auth(uri, streaming_login, vehicle.tokens.first)
|
20
|
+
client.get_content(uri) do |chunk|
|
21
|
+
p chunk
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_temperature!(vehicle, driver_degrees_celcius, passenger_degrees_celcius)
|
26
|
+
command!(vehicle, "set_temps", :query => { :driver_degrees_celcius => driver_degrees_celcius,
|
27
|
+
:passenger_degrees_celcius => passenger_degrees_celcius })
|
28
|
+
end
|
29
|
+
|
30
|
+
def open_roof!(vehicle, state)
|
31
|
+
command!(vehicle, "sun_roof_control", :query => { :state => state })
|
32
|
+
end
|
33
|
+
|
34
|
+
def auto_conditioning_stop!(vehicle)
|
35
|
+
command!(vehicle, "auto_conditioning_stop")
|
36
|
+
end
|
37
|
+
|
38
|
+
def auto_conditioning_start!(vehicle)
|
39
|
+
command!(vehicle, "auto_conditioning_start")
|
40
|
+
end
|
41
|
+
|
42
|
+
def lock_door!(vehicle)
|
43
|
+
command!(vehicle, "door_lock")
|
44
|
+
end
|
45
|
+
|
46
|
+
def unlock_door!(vehicle)
|
47
|
+
command!(vehicle, "door_unlock")
|
48
|
+
end
|
49
|
+
|
50
|
+
def honk_horn!(vehicle)
|
51
|
+
command!(vehicle, "honk_horn")
|
52
|
+
end
|
53
|
+
|
54
|
+
def flash_lights!(vehicle)
|
55
|
+
command!(vehicle, "flash_lights")
|
56
|
+
end
|
57
|
+
|
58
|
+
def charge_stop!(vehicle)
|
59
|
+
command!(vehicle, "charge_stop")
|
60
|
+
end
|
61
|
+
|
62
|
+
def charge_start!(vehicle)
|
63
|
+
command!(vehicle, "charge_start")
|
64
|
+
end
|
65
|
+
|
66
|
+
def charge_max_range!(vehicle)
|
67
|
+
command!(vehicle, "charge_max_range")
|
68
|
+
end
|
69
|
+
|
70
|
+
def charge_standard!(vehicle)
|
71
|
+
command!(vehicle, "charge_standard")
|
72
|
+
end
|
73
|
+
|
74
|
+
def wake_up!(vehicle)
|
75
|
+
command!(vehicle, "wake_up")
|
76
|
+
end
|
77
|
+
|
78
|
+
def open_charge_port!(vehicle)
|
79
|
+
command!(vehicle, "charge_port_open")
|
80
|
+
end
|
81
|
+
|
82
|
+
def api_mobile_access?(vehicle)
|
83
|
+
_, json = get_json(command_url(vehicle, "mobile_enabled"))
|
84
|
+
|
85
|
+
json["result"] == true
|
86
|
+
end
|
87
|
+
|
88
|
+
def api_get_vehicle_state_for_vehicle(vehicle)
|
89
|
+
_, json = get_json(command_url(vehicle, "vehicle_state"))
|
90
|
+
|
91
|
+
VehicleState.new(json)
|
92
|
+
end
|
93
|
+
|
94
|
+
def api_gui_settings_for_vehicle(vehicle)
|
95
|
+
_, json = get_json(command_url(vehicle, "gui_settings"))
|
96
|
+
|
97
|
+
GUISettings.new(json)
|
98
|
+
end
|
99
|
+
|
100
|
+
def api_drive_state_for_vehicle(vehicle)
|
101
|
+
_, json = get_json(command_url(vehicle, "drive_state"))
|
102
|
+
|
103
|
+
DriveState.new(json)
|
104
|
+
end
|
105
|
+
|
106
|
+
def api_climate_state_for_vehicle(vehicle)
|
107
|
+
_, json = get_json(command_url(vehicle, "climate_state"))
|
108
|
+
|
109
|
+
ClimateState.new(json)
|
110
|
+
end
|
111
|
+
|
112
|
+
def api_charge_state_for_vehicle(vehicle)
|
113
|
+
_, json = get_json(command_url(vehicle, "charge_state"))
|
114
|
+
|
115
|
+
ChargeState.new(json)
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def streaming_login
|
121
|
+
email.gsub("@","%")
|
122
|
+
end
|
123
|
+
|
124
|
+
def check_logged_in!
|
125
|
+
raise Errors::NotLoggedIn unless logged_in?
|
126
|
+
end
|
127
|
+
|
128
|
+
def command_url(vehicle, command_name)
|
129
|
+
"/vehicles/#{vehicle.id}/command/#{command_name}"
|
130
|
+
end
|
131
|
+
|
132
|
+
def command!(vehicle, command_name, options = {})
|
133
|
+
_, json = get_json(command_url(vehicle, command_name), options)
|
134
|
+
|
135
|
+
json["result"] ? json["result"] : raise(Errors::APIFailure.new(json["reason"]))
|
136
|
+
end
|
137
|
+
|
138
|
+
def get_json(uri, options = {})
|
139
|
+
check_logged_in!
|
140
|
+
|
141
|
+
response = get(uri, options)
|
142
|
+
|
143
|
+
[response, JSON.parse(response.body)]
|
144
|
+
rescue JSON::ParserError => e
|
145
|
+
raise Errors::InvalidJSON.new(e)
|
146
|
+
end
|
147
|
+
|
148
|
+
def get(uri, options = {})
|
149
|
+
response = @client.get(Connection::HOST + uri, options)
|
150
|
+
|
151
|
+
raise Errors::InvalidResponse.new(response) unless response.status_code == HTTP::Status::OK
|
152
|
+
|
153
|
+
response
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|