syncwise_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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/syncwise_api/client.rb +47 -0
- data/lib/syncwise_api/errors.rb +93 -0
- data/lib/syncwise_api/ext/core_ext.rb +176 -0
- data/lib/syncwise_api/ext/inflections.rb +66 -0
- data/lib/syncwise_api/ext/inflector/inflections.rb +177 -0
- data/lib/syncwise_api/ext/inflector_methods.rb +62 -0
- data/lib/syncwise_api/ext/string_encoding.rb +12 -0
- data/lib/syncwise_api/mixins/mixins.rb +1 -0
- data/lib/syncwise_api/mixins/request_builder.rb +23 -0
- data/lib/syncwise_api/mixins/request_sender.rb +11 -0
- data/lib/syncwise_api/mixins/request_signer.rb +20 -0
- data/lib/syncwise_api/requests/V1_0/assign_device_create.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/base.rb +115 -0
- data/lib/syncwise_api/requests/V1_0/device_details.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/device_list.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/device_settings_details.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/device_settings_edit.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/device_subscribe.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/device_unsubscribe.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/driver_speed_report.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/obd_vehicle_details.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/trip_event_details.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/user_login.rb +26 -0
- data/lib/syncwise_api/requests/V1_0/user_subscribe_settings_details.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/vehicle_gauge_information.rb +19 -0
- data/lib/syncwise_api/requests/V1_0/vehicle_idling_history.rb +19 -0
- data/lib/syncwise_api/requests/requests.rb +2 -0
- data/lib/syncwise_api/responses/V1_0/base.rb +35 -0
- data/lib/syncwise_api/responses/V1_0/standard.rb +9 -0
- data/lib/syncwise_api/responses/responses.rb +1 -0
- data/lib/syncwise_api/service_utils/crypto/hmac_sha256.rb +15 -0
- data/lib/syncwise_api/service_utils/encoders/base64.rb +16 -0
- data/lib/syncwise_api/service_utils/encoders/json.rb +21 -0
- data/lib/syncwise_api/service_utils/http.rb +34 -0
- data/lib/syncwise_api/service_utils/parsers/json.rb +55 -0
- data/lib/syncwise_api/service_utils/service_utils.rb +2 -0
- data/lib/syncwise_api/service_utils/time_stamper.rb +13 -0
- data/lib/syncwise_api/version.rb +3 -0
- data/lib/syncwise_api.rb +30 -0
- data/syncwise_api.gemspec +27 -0
- data/tester.rb +10 -0
- metadata +162 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require_relative 'inflections'
|
|
2
|
+
|
|
3
|
+
# holds 'inflector methods' (to use a Rails term) to change 'words' from one form to another
|
|
4
|
+
module SyncwiseApi
|
|
5
|
+
module Inflector
|
|
6
|
+
|
|
7
|
+
# downcase words, and replace ' ' with '_'. Example 'Big Bob'.dehumanize => 'big_bob'
|
|
8
|
+
def dehumanize(word)
|
|
9
|
+
# should be OK to remove the respond_to? as long as we ensure we call this only on Strings or things that can be
|
|
10
|
+
# cast to Strings
|
|
11
|
+
#if word.respond_to?(:to_s)
|
|
12
|
+
dh_word = word.to_s.dup
|
|
13
|
+
dh_word.gsub!(/ /, '_')
|
|
14
|
+
dh_word.downcase!
|
|
15
|
+
dh_word
|
|
16
|
+
#end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def underscore(camel_cased_word)
|
|
20
|
+
# should be OK to remove the respond_to? as long as we ensure we call this only on Strings or things that can be
|
|
21
|
+
# cast to Strings
|
|
22
|
+
#if camel_cased_word.respond_to?(:to_s)
|
|
23
|
+
word = camel_cased_word.to_s.dup
|
|
24
|
+
word.gsub!(/::/, '/')
|
|
25
|
+
word.gsub!(/(?:([A-Za-z\d])|^)(#{inflections.acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
|
|
26
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
|
27
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
|
28
|
+
word.tr!("-", "_")
|
|
29
|
+
word.downcase!
|
|
30
|
+
word
|
|
31
|
+
#end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
|
|
35
|
+
# is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
|
|
36
|
+
#
|
|
37
|
+
# +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces.
|
|
38
|
+
#
|
|
39
|
+
# Examples:
|
|
40
|
+
# "active_model".camelize # => "ActiveModel"
|
|
41
|
+
# "active_model".camelize(:lower) # => "activeModel"
|
|
42
|
+
# "active_model/errors".camelize # => "ActiveModel::Errors"
|
|
43
|
+
# "active_model/errors".camelize(:lower) # => "activeModel::Errors"
|
|
44
|
+
#
|
|
45
|
+
# As a rule of thumb you can think of +camelize+ as the inverse of +underscore+,
|
|
46
|
+
# though there are cases where that does not hold:
|
|
47
|
+
#
|
|
48
|
+
# "SSLError".underscore.camelize # => "SslError"
|
|
49
|
+
def camelize(term, uppercase_first_letter = true)
|
|
50
|
+
string = term.to_s
|
|
51
|
+
if uppercase_first_letter
|
|
52
|
+
string = string.sub(/^[a-z\d]*/) { inflections.acronyms[$&] || $&.capitalize }
|
|
53
|
+
else
|
|
54
|
+
string = string.sub(/^(?:#{inflections.acronym_regex}(?=\b|[A-Z_])|\w)/) { $&.downcase }
|
|
55
|
+
end
|
|
56
|
+
string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{inflections.acronyms[$2] || $2.capitalize}" }.gsub('/', '::')
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
module_function :dehumanize, :underscore, :camelize
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Dir["#{File.dirname(__FILE__)}/**/*.rb"].each { |f| require f }
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Currently not used
|
|
2
|
+
#module SyncwiseApi
|
|
3
|
+
# module Mixins
|
|
4
|
+
# module RequestBuilder
|
|
5
|
+
#
|
|
6
|
+
# def extract_header_params
|
|
7
|
+
# # first, we have to make sure that this is mixed into a class that has a @param instance variable
|
|
8
|
+
# # and that has a superclass with a required_header_params method
|
|
9
|
+
# if !self.instance_variable_defined?(:@params)
|
|
10
|
+
# fail SyncwiseApi::Errors::MissingInstanceVariable.new(:@params, SyncwiseApi::Mixins::RequestBuilder, self)
|
|
11
|
+
# elsif !self.superclass.respond_to?(:required_header_params)
|
|
12
|
+
# fail SyncwiseApi::Errors::MissingMethod.new(:required_header_params, SyncwiseApi::Mixins::RequestBuilder, self)
|
|
13
|
+
# else
|
|
14
|
+
# # as crazy as this looks, all it does is pull out the required header params from the @params hash, which holds
|
|
15
|
+
# # any dynamically supplied params, and add them to the @header hash, which holds the header params
|
|
16
|
+
# @header = {}
|
|
17
|
+
# self.superclass.required_header_params.each { |key| @header[key] = @params.delete(key) }
|
|
18
|
+
# end
|
|
19
|
+
# end
|
|
20
|
+
#
|
|
21
|
+
# end
|
|
22
|
+
# end
|
|
23
|
+
#end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Mixins
|
|
3
|
+
module RequestSigner
|
|
4
|
+
|
|
5
|
+
def sign
|
|
6
|
+
if !self.instance_variable_defined?(:@params)
|
|
7
|
+
fail SyncwiseApi::Errors::MissingInstanceVariable.new(:@request, SyncwiseApi::Mixins::RequestSigner, self)
|
|
8
|
+
elsif !self.instance_variable_defined?(:@header)
|
|
9
|
+
fail SyncwiseApi::Errors::MissingInstanceVariable.new(:@header, SyncwiseApi::Mixins::RequestSigner, self)
|
|
10
|
+
else
|
|
11
|
+
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class AssignDeviceCreate < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceList]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'openssl'
|
|
2
|
+
|
|
3
|
+
module SyncwiseApi
|
|
4
|
+
module Requests
|
|
5
|
+
module V1_0
|
|
6
|
+
class Base
|
|
7
|
+
#include SyncwiseApi::Mixins::RequestBuilder
|
|
8
|
+
#include SyncwiseApi::Mixins::RequestSigner
|
|
9
|
+
#include SyncwiseApi::Mixins::RequestSender
|
|
10
|
+
|
|
11
|
+
# @required_header_params represents the keys required by all required for all Syncwise API calls, and CHANGE on a per call basis
|
|
12
|
+
# thus, they must be present (have values) in the paramss passed to #initialize when creating a new object that
|
|
13
|
+
# inherits from this class (Base)
|
|
14
|
+
#TODO: Make this a class constant?
|
|
15
|
+
@required_header_params = [:'API Key', :'Action Code']
|
|
16
|
+
@required_header_params.freeze
|
|
17
|
+
|
|
18
|
+
# @default_header_params holds key/values that are universally required for all Syncwise API calls, and DO NOT CHANGE
|
|
19
|
+
#TODO: Make this a class constant?
|
|
20
|
+
@default_header_params = {:'API Version' => 1.0, :'Signature Version' => 1, :'Signature Method' => 'HmacSHA256', :'Response Format' => 'JSON'}
|
|
21
|
+
@default_header_params.freeze
|
|
22
|
+
|
|
23
|
+
# @required_params represents all the params (both header and payload) that must be passed to #initialize when
|
|
24
|
+
# creating a new object that inherits from this class (Base)
|
|
25
|
+
#TODO: Make this a class constant?
|
|
26
|
+
@required_params = [:secretKey, :accountId]
|
|
27
|
+
@required_params.concat(@required_header_params)
|
|
28
|
+
@required_params.freeze
|
|
29
|
+
|
|
30
|
+
HOST_HEADER = 'api-int.syncwise.com'
|
|
31
|
+
BASE_URL = "https://#{HOST_HEADER}/rest/action"
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
attr_reader :required_header_params, :default_header_params, :required_params, :host_header
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def initialize(params = {})
|
|
38
|
+
# Add the action code to params based on the child class's name
|
|
39
|
+
params[:'Action Code'] = self.unqualified_class
|
|
40
|
+
|
|
41
|
+
# Verify we have all required params by comparing child class's required_params to the passed in params
|
|
42
|
+
param_keys = params.keys.sort
|
|
43
|
+
|
|
44
|
+
fail SyncwiseApi::Errors::InvalidParameters.new(self.class, param_keys, self.class.required_params) unless param_keys & self.class.required_params == self.class.required_params
|
|
45
|
+
# remove the signing key from params and store it for use when building the HMAC signature
|
|
46
|
+
@secret_key = params.delete(:secretKey)
|
|
47
|
+
|
|
48
|
+
# @params now holds the params we need to build the header_hash
|
|
49
|
+
@params = params
|
|
50
|
+
|
|
51
|
+
build_header_hash
|
|
52
|
+
|
|
53
|
+
# after build_header_hash returns, we have @header which holds all values needed to build the request and signature
|
|
54
|
+
# and @params which now only contains the values that will be added to the JSON payload
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def send_request
|
|
58
|
+
request_string = build_api_call
|
|
59
|
+
body = build_body
|
|
60
|
+
# TODO: send POST with Net::Http to request_string with JSON payload body
|
|
61
|
+
SyncwiseApi::ServiceUtils::HTTP.post(request_string, body) do |http_response|
|
|
62
|
+
SyncwiseApi::Responses::V1_0::Standard.new(http_response)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def build_header_hash
|
|
69
|
+
# pull out the required header params from the @params hash, which holds
|
|
70
|
+
# any dynamically supplied params, and add them to the @header hash, which holds the header params
|
|
71
|
+
@header = {}.merge(SyncwiseApi::Requests::V1_0::Base.default_header_params)
|
|
72
|
+
SyncwiseApi::Requests::V1_0::Base.required_header_params.each { |key| @header[key] = @params.delete(key) }
|
|
73
|
+
@header[:Timestamp] = SyncwiseApi::ServiceUtils::Timestamper.stamp
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def build_api_call
|
|
77
|
+
"#{SyncwiseApi::Requests::V1_0::Base::BASE_URL}/#{@header[:'Action Code']}/#{@header[:'API Key']}/#{@header[:'API Version']}/#{@header[:'Signature Version']}/#{@header[:'Signature Method']}/#{create_signature}/#{@header[:Timestamp]}/#{@header[:'Response Format']}"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def build_body
|
|
81
|
+
SyncwiseApi::ServiceUtils::Encoders::JSON.encode(@params)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def create_signature
|
|
85
|
+
bin_hmac = SyncwiseApi::ServiceUtils::Crypto::HmacSha256.crypt(@secret_key, string_to_sign)
|
|
86
|
+
base64_hmac = SyncwiseApi::ServiceUtils::Encoders::Base64.encode(bin_hmac)
|
|
87
|
+
replace_bad_chars(base64_hmac)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def string_to_sign
|
|
91
|
+
"#{self.class.verb}\n#{SyncwiseApi::Requests::V1_0::Base::HOST_HEADER}\n#{canonicalized_query_string}"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def canonicalized_query_string
|
|
95
|
+
sorted_header_array = @header.to_a.sort
|
|
96
|
+
query_string = ''
|
|
97
|
+
sorted_header_array.each do |key_value_array|
|
|
98
|
+
query_string = query_string + "&#{key_value_array[0]}=#{key_value_array[1]}"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
query_string
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def replace_bad_chars(encoded_string)
|
|
105
|
+
encoded_string.gsub!('/', 'A')
|
|
106
|
+
encoded_string.gsub!('+', 'B')
|
|
107
|
+
encoded_string.gsub!('=', 'C')
|
|
108
|
+
encoded_string.gsub!('&', 'D')
|
|
109
|
+
encoded_string
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class DeviceDetails < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceId]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class DeviceList < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = []
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class DeviceSettingsDetails < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceId, :settingsStatus]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class DeviceSettingsEdit < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceId, :appTypeVer, :deviceSettings]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class DeviceSubscribe < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceList]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class DeviceUnsubscribe < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceList]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class DriverSpeedReport < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceId, :endDate, :startDate]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class OBDVehicleDetails < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceId]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class TripEventDetails < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceId, :tripId]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class UserLogin < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:password]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# overrides create_signature in Base, because for this request only, no signature is possible since we
|
|
17
|
+
# don't have a secret key yet. the service still requires a dummy value here, though, so just quickly return a
|
|
18
|
+
# valid, but dummy, signature string
|
|
19
|
+
def create_signature
|
|
20
|
+
'k8NipGDhzthk0EJRmHCBy2NcwSsC'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class UserSubscribeSettingsDetails < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = []
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class VehicleGaugeInformation < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceId, :gaugeMap, :endDate, :startDate]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Requests
|
|
3
|
+
module V1_0
|
|
4
|
+
class VehicleIdlingHistory < Base
|
|
5
|
+
|
|
6
|
+
#TODO: this is janky. Fix it. Class constants? Something in Base? Not sure...
|
|
7
|
+
my_required_params = [:deviceId, :endDate, :startDate]
|
|
8
|
+
@required_params = my_required_params.concat(self.superclass.required_params)
|
|
9
|
+
@required_params.sort!.freeze
|
|
10
|
+
@verb = 'POST'
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
attr_reader :required_params, :verb
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module Responses
|
|
3
|
+
module V1_0
|
|
4
|
+
class Base
|
|
5
|
+
|
|
6
|
+
def initialize(http_response_object)
|
|
7
|
+
@http_response_object = http_response_object
|
|
8
|
+
@body = @http_response_object.body
|
|
9
|
+
@header_hash = @http_response_object.header.to_hash.symbolize_keys
|
|
10
|
+
@body_hash = parse
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
attr_reader :body_hash
|
|
14
|
+
|
|
15
|
+
def valid?
|
|
16
|
+
@body_hash[:sts] == '1'
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def parse
|
|
22
|
+
# if the response has a body, and the body is json, parse and store it in @body_hash; otherwise throw an error
|
|
23
|
+
if @body.blank?
|
|
24
|
+
fail SyncwiseApi::Errors::EmptyResponseBody.new(@http_response_object, @http_response_object.uri, @header_hash)
|
|
25
|
+
elsif !@header_hash[:content_type].include?('application/json')
|
|
26
|
+
fail SyncwiseApi::Errors::InvalidContentType.new(@http_response_object, @http_response_object.uri, @header_hash)
|
|
27
|
+
else
|
|
28
|
+
SyncwiseApi::ServiceUtils::Parsers::JSON.parse(@body).symbolize_keys
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Dir["#{File.dirname(__FILE__)}/**/*.rb"].each { |f| require f }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module SyncwiseApi
|
|
2
|
+
module ServiceUtils
|
|
3
|
+
module Crypto
|
|
4
|
+
module HmacSha256
|
|
5
|
+
|
|
6
|
+
def crypt(secret_key, string_to_sign)
|
|
7
|
+
digest = OpenSSL::Digest::Digest.new('sha256')
|
|
8
|
+
OpenSSL::HMAC.digest(digest, secret_key, string_to_sign)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module_function :crypt
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'yajl'
|
|
2
|
+
|
|
3
|
+
module SyncwiseApi
|
|
4
|
+
module ServiceUtils
|
|
5
|
+
module Encoders
|
|
6
|
+
module JSON
|
|
7
|
+
|
|
8
|
+
def encode(object)
|
|
9
|
+
if object.is_a?(Hash) || object.is_a?(Array)
|
|
10
|
+
Yajl::Encoder.encode(object)
|
|
11
|
+
else
|
|
12
|
+
fail SyncwiseApi::Errors::JSONEncodeError.new(object)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module_function :encode
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|