comma-api-rb 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c5a3762b9cae821798872f7f1454bd2fa50af41d
4
+ data.tar.gz: 4005e58e30f8b6ba112f9febc07601bdc9c2746d
5
+ SHA512:
6
+ metadata.gz: 5fbc0183d97c3fb4a0ac31ccb2a37c6c7be5d640f36e17b47303e52cf3110bcccee750adddad8d035c6f44c730932e40bc72a2e7495c629802e14647f9ea87d3
7
+ data.tar.gz: 7c329c8fc03fbc10dae2f226653a1ae6d00ae8abfb884806eccb1c1f6aef967d29c9e79194e60db8916018ef2d46b66437afef0aae4780f6e1f2cc6458bcd89e
@@ -0,0 +1,52 @@
1
+ module CommaAPI
2
+
3
+ class RPCError < Exception; end
4
+ class RPCError404 < RPCError; end
5
+
6
+ module HTTP
7
+
8
+ def request(url:)
9
+ uri = URI url
10
+ req = Net::HTTP::Get.new uri.request_uri
11
+ req["Authorization"] = "JWT #{::JWT_TOKEN}"
12
+ resp = http(uri: uri).request req
13
+ return RPCError404.new if resp.code == "404"
14
+ JSON.parse resp.body
15
+ end
16
+
17
+ def post_request(url:, data:)
18
+ uri = URI url
19
+ req = Net::HTTP::Post.new uri.request_uri
20
+ req["Authorization"] = "JWT #{::JWT_TOKEN}"
21
+ req.body = data
22
+ resp = http(uri: uri).request req
23
+ JSON.parse resp.body
24
+ end
25
+
26
+ def http(uri:)
27
+ http = Net::HTTP.new uri.host, uri.port
28
+ http.use_ssl = true
29
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
30
+ http
31
+ end
32
+
33
+ end
34
+
35
+
36
+ # TODO: move (and refactor with refinements)
37
+
38
+ module Monkeypatches
39
+ class ::Hash
40
+ alias :f :fetch
41
+
42
+ def sym_keys
43
+ Hash[self.map{ |key,value| [key.to_sym, value] }]
44
+ end
45
+
46
+ def str_keys
47
+ Hash[self.map{ |key,value| [key.to_s, value] }]
48
+ end
49
+ end
50
+ end
51
+
52
+ end
data/lib/athena_api.rb ADDED
@@ -0,0 +1,93 @@
1
+ module CommaAPI
2
+
3
+ class Athena
4
+
5
+ extend ConfigAthena
6
+ extend HTTP
7
+
8
+ STATE = {
9
+ rpc_id: 0
10
+ }
11
+
12
+ RpcId = -> {
13
+ STATE[:rpc_id] += 1
14
+ }
15
+
16
+ class << self
17
+
18
+ def health
19
+ post_rpc m: "getMessage", service: "health"
20
+ end
21
+
22
+ def carState
23
+ post_rpc m: "getMessage", service: "carState"
24
+ end
25
+
26
+ def logMessage
27
+ post_rpc m: "getMessage", service: "logMessage"
28
+ end
29
+
30
+ def androidLog
31
+ post_rpc m: "getMessage", service: "androidLog"
32
+ end
33
+
34
+ def procLog
35
+ post_rpc m: "getMessage", service: "procLog"
36
+ end
37
+
38
+ def gpsLocation
39
+ post_rpc m: "getMessage", service: "gpsLocation"
40
+ end
41
+
42
+ def thermal
43
+ data = post_rpc m: "getMessage", service: "thermal"
44
+ data[:cpu] = thermal_cpu_avg(data: data)
45
+ data
46
+ end
47
+
48
+ # ---
49
+
50
+ def thermal_cpu_avg(data:)
51
+ temps = [data.f(:cpu0), data.f(:cpu1), data.f(:cpu2), data.f(:cpu3)]
52
+ (temps.reduce(:+).to_f / temps.size).round
53
+ end
54
+
55
+ # ---
56
+
57
+ def rpc_msg(m:, service:)
58
+ {
59
+ method: m,
60
+ params: { service: service, timeout: 3000 },
61
+ jsonrpc: "2.0",
62
+ id: RpcId.(),
63
+ }.str_keys.to_json
64
+ end
65
+
66
+ def post_rpc(m:, service:)
67
+ puts "-> rpc message: m: #{m.inspect}, service: #{service.inspect}"
68
+ url = "#{API_HOST}/#{DONGLE_ID_DEFAULT}"
69
+ data = rpc_msg(m: m, service: service)
70
+ begin
71
+ resp = post_request url: url, data: data
72
+ rescue
73
+ return RPCError.new "JSON Parse Error"
74
+ end
75
+ parse_rpc resp, service: service
76
+ end
77
+
78
+ def parse_rpc(resp, service:)
79
+ return RPCError.new if resp["error"] == "Timed out"
80
+ return RPCError.new if resp["error"] && resp["error"]["message"] == "Server error"
81
+ result = resp.fetch "result"
82
+ result = result[service] if result[service]
83
+ result = result["androidLogEntry"] if service == "androidLog"
84
+ # TODO: use inflecto gem to snakecase keys
85
+ result = JSON.parse result if result.is_a? String # TODO: do this only for `logMessage` service
86
+ result.sym_keys
87
+ end
88
+
89
+ end
90
+
91
+ end
92
+
93
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'env'
2
+
3
+ require_relative 'athena_api'
4
+
5
+ require_relative 'comma_api'
data/lib/comma_api.rb ADDED
@@ -0,0 +1,122 @@
1
+ module CommaAPI
2
+ class API
3
+
4
+ extend Config
5
+ extend HTTP
6
+
7
+ class << self
8
+
9
+ # user
10
+
11
+ def me
12
+ get "/v1/me/"
13
+ end
14
+
15
+ # devices
16
+
17
+ def devices
18
+ get "/v1/me/devices/"
19
+ end
20
+
21
+ def device(id:)
22
+ get "/v1.1/devices/#{id}/"
23
+ end
24
+
25
+ def deviceLocation(id:)
26
+ get "/v1/devices/#{id}/location"
27
+ end
28
+
29
+ def deviceDefaultLocation
30
+ return device404Error unless DONGLE_ID_DEFAULT
31
+ deviceLocation id: DONGLE_ID_DEFAULT
32
+ end
33
+
34
+ def deviceDefault
35
+ return device404Error unless DONGLE_ID_DEFAULT
36
+ device id: DONGLE_ID_DEFAULT
37
+ end
38
+
39
+ def deviceDefaultStats
40
+ return device404Error unless DONGLE_ID_DEFAULT
41
+ deviceStats id: DONGLE_ID_DEFAULT
42
+ end
43
+
44
+ def deviceStats(id:)
45
+ get "/v1/devices/#{id}/stats"
46
+ end
47
+
48
+ def devicesStat(id:)
49
+ devices = get "/v1/devices"
50
+ # TODO: loop through all devices, return all stats and a total
51
+ devices.map { |device|
52
+ get "/v1/devices/#{device.f("dongle_id")}/stats#{args}"
53
+ }
54
+ end
55
+
56
+ def deviceStatsId(id:)
57
+ get "/v1/devices/#{id}/stats#{args}"
58
+ end
59
+
60
+ # routes
61
+
62
+ def route(route_name:)
63
+ get "/v1/route/#{route_name}/"
64
+ end
65
+
66
+ def routeFiles(route_name:)
67
+ get "/v1/route/#{route_name}/files"
68
+ end
69
+
70
+ # segments
71
+
72
+ def segments
73
+ return device404Error unless DONGLE_ID_DEFAULT
74
+ get "/v1/devices/#{DONGLE_ID_DEFAULT}/segments#{args}"
75
+ end
76
+
77
+ def deviceSegments(id:)
78
+ return device404Error unless DONGLE_ID_DEFAULT
79
+ get "/v1/devices/#{id}/segments#{args}"
80
+ end
81
+
82
+ def deviceDefaultSegments
83
+ return device404Error unless DONGLE_ID_DEFAULT
84
+ deviceSegments id: DONGLE_ID_DEFAULT
85
+ end
86
+
87
+ def args
88
+ defaultArgs # alias (alias :args :defaultArgs)
89
+ end
90
+
91
+ def defaultArgs
92
+ one_week = 604800
93
+ "?from=#{(Time.now - one_week - 1).to_i}"
94
+ end
95
+
96
+ def opAuth
97
+ "https://api.commadotai.com/v2/pilotauth/"
98
+ end
99
+
100
+
101
+ # helper
102
+
103
+ def get(method_name)
104
+ # note: trailing slash gets added here
105
+ puts "requesting: #{method_name}"
106
+ url = "#{API_HOST}#{method_name}"
107
+ puts url
108
+ request url: url
109
+ end
110
+
111
+
112
+ # errors
113
+
114
+ def device404Error
115
+ { error: 'Error: DONGLE_ID_DEFAULT is missing - this method cannot be executed, you need to specify a dongle id' }.to_json
116
+ end
117
+
118
+ end
119
+
120
+ end
121
+
122
+ end
data/lib/config.rb ADDED
@@ -0,0 +1,27 @@
1
+ module CommaAPI
2
+
3
+ module Config
4
+
5
+ API_HOST = "https://api.comma.ai"
6
+
7
+ ::JWT_TOKEN = ENV["JWT_TOKEN"] || ENV["COMMA_JWT_TOKEN"]
8
+ raise "JWT_TOKEN not defined, please pass it as ENV variable (rake JWT_TOKEN=YourJwtToken....)" unless JWT_TOKEN
9
+
10
+ DONGLE_ID_DEFAULT = ENV["DONGLE_ID_DEFAULT"]
11
+
12
+
13
+ # default device id - used on the `.deviceDefault()` methods
14
+
15
+ end
16
+
17
+
18
+ module ConfigAthena
19
+
20
+ API_HOST = "https://athena.comma.ai"
21
+
22
+ # ::JWT_TOKEN = Config::JWT_TOKEN
23
+ DONGLE_ID_DEFAULT = Config::DONGLE_ID_DEFAULT
24
+
25
+ end
26
+
27
+ end
data/lib/env.rb ADDED
@@ -0,0 +1,17 @@
1
+ require "net/https"
2
+ require 'json'
3
+ require 'cgi'
4
+ # require 'bundler'
5
+ # Bundler.require :default
6
+ require_relative 'config'
7
+
8
+ module CommaAPI
9
+ PATH = File.expand_path "./"
10
+
11
+ # -----
12
+ # TODO: refactor
13
+
14
+ require_relative 'api_client_lib'
15
+
16
+ include Monkeypatches
17
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module CommaAPI
2
+ VERSION = "TODO - please check gemspec"
3
+ end
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: comma-api-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.2
5
+ platform: ruby
6
+ authors:
7
+ - "@makevoid - Francesco Canessa"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-09-23 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Comma and Athena API ruby library (prototype - this version is currently
14
+ in WIP, public API and functionality is guaranteed to change overtime :D, thanks
15
+ for understanding)
16
+ email: makevoid@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - "./lib/api_client_lib.rb"
22
+ - "./lib/athena_api.rb"
23
+ - "./lib/comma-api-rb.rb"
24
+ - "./lib/comma_api.rb"
25
+ - "./lib/config.rb"
26
+ - "./lib/env.rb"
27
+ - "./lib/version.rb"
28
+ homepage: https://github.com/makevoid/comma_api_rb
29
+ licenses:
30
+ - GPL-3.0
31
+ metadata:
32
+ source_code_uri: https://github.com/makevoid/comma_api_rb
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 2.5.2.3
50
+ signing_key:
51
+ specification_version: 4
52
+ summary: Comma and Athena API ruby library (prototype)
53
+ test_files: []