comma-api-rb 0.3.2

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 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: []