tesla-api 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|