dimo-python-sdk 0.0.1__py3-none-any.whl
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.
- dimo/__init__.py +3 -0
- dimo/auth.py +85 -0
- dimo/constants.py +10 -0
- dimo/device_data.py +118 -0
- dimo/device_definitions.py +39 -0
- dimo/devices.py +252 -0
- dimo/dimo.py +79 -0
- dimo/environments.py +30 -0
- dimo/events.py +13 -0
- dimo/identity.py +222 -0
- dimo/request.py +33 -0
- dimo/telemetry.py +131 -0
- dimo/test.py +92 -0
- dimo/token_exchange.py +22 -0
- dimo/trips.py +18 -0
- dimo/user.py +53 -0
- dimo/valuations.py +32 -0
- dimo/vehicle_signal_decoding.py +99 -0
- dimo_python_sdk-0.0.1.dist-info/LICENSE +201 -0
- dimo_python_sdk-0.0.1.dist-info/METADATA +385 -0
- dimo_python_sdk-0.0.1.dist-info/RECORD +23 -0
- dimo_python_sdk-0.0.1.dist-info/WHEEL +5 -0
- dimo_python_sdk-0.0.1.dist-info/top_level.txt +1 -0
dimo/__init__.py
ADDED
dimo/auth.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
from web3 import Web3
|
|
2
|
+
from eth_account.messages import encode_defunct
|
|
3
|
+
from dimo.constants import dimo_constants
|
|
4
|
+
from urllib.parse import urlencode
|
|
5
|
+
|
|
6
|
+
class Auth:
|
|
7
|
+
|
|
8
|
+
def __init__(self, request_method, get_auth_headers):
|
|
9
|
+
self._request = request_method
|
|
10
|
+
self._get_auth_headers = get_auth_headers
|
|
11
|
+
|
|
12
|
+
async def generate_challenge(self,
|
|
13
|
+
client_id,
|
|
14
|
+
domain,
|
|
15
|
+
address,
|
|
16
|
+
headers,
|
|
17
|
+
scope='openid email',
|
|
18
|
+
response_type='code'):
|
|
19
|
+
body = {
|
|
20
|
+
'client_id': client_id,
|
|
21
|
+
'domain': domain,
|
|
22
|
+
'scope': scope,
|
|
23
|
+
'response_type': response_type,
|
|
24
|
+
'address': address
|
|
25
|
+
}
|
|
26
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
|
27
|
+
return self._request(
|
|
28
|
+
'POST',
|
|
29
|
+
'Auth',
|
|
30
|
+
'/auth/web3/generate_challenge',
|
|
31
|
+
data=urlencode(body),
|
|
32
|
+
headers=headers
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
async def sign_challenge(self, message, private_key, env="Production"):
|
|
36
|
+
web3 = Web3(Web3.HTTPProvider(dimo_constants[env]['RPC_provider']))
|
|
37
|
+
signed_message = web3.eth.account.sign_message(encode_defunct(text=message), private_key=private_key)
|
|
38
|
+
return signed_message.signature.hex()
|
|
39
|
+
|
|
40
|
+
async def submit_challenge(self, form_data, headers):
|
|
41
|
+
return self._request('POST', 'Auth', '/auth/web3/submit_challenge', data=form_data, headers=headers)
|
|
42
|
+
|
|
43
|
+
# Requires client_id, domain, and private_key. Address defaults to client_id.
|
|
44
|
+
async def get_token(self,
|
|
45
|
+
client_id,
|
|
46
|
+
domain,
|
|
47
|
+
private_key,
|
|
48
|
+
address=None,
|
|
49
|
+
scope='openid email',
|
|
50
|
+
response_type='code',
|
|
51
|
+
grant_type="authorization_code",
|
|
52
|
+
env="Production"):
|
|
53
|
+
|
|
54
|
+
if address is None:
|
|
55
|
+
address = client_id
|
|
56
|
+
|
|
57
|
+
headers = {
|
|
58
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
challenge = await self.generate_challenge(
|
|
62
|
+
headers=headers,
|
|
63
|
+
client_id=client_id,
|
|
64
|
+
domain=domain,
|
|
65
|
+
scope=scope,
|
|
66
|
+
response_type=response_type,
|
|
67
|
+
address=address
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
sign = await self.sign_challenge(
|
|
71
|
+
message=challenge['challenge'],
|
|
72
|
+
private_key=private_key,
|
|
73
|
+
env=env
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
body = {
|
|
77
|
+
'client_id': client_id,
|
|
78
|
+
'domain': domain,
|
|
79
|
+
'state': challenge['state'],
|
|
80
|
+
'signature': sign,
|
|
81
|
+
'grant_type': grant_type
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
submit = await self.submit_challenge(body, headers)
|
|
85
|
+
return submit
|
dimo/constants.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
dimo_constants = {
|
|
2
|
+
"Production": {
|
|
3
|
+
"NFT_address": "0xbA5738a18d83D41847dfFbDC6101d37C69c9B0cF",
|
|
4
|
+
"RPC_provider": "https://eth.llamarpc.com"
|
|
5
|
+
},
|
|
6
|
+
"Dev": {
|
|
7
|
+
"NFT_address": "0x45fbCD3ef7361d156e8b16F5538AE36DEdf61Da8",
|
|
8
|
+
"RPC_provider": "https://eth.llamarpc.com"
|
|
9
|
+
}
|
|
10
|
+
}
|
dimo/device_data.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
class DeviceData:
|
|
2
|
+
|
|
3
|
+
def __init__(self, request_method, get_auth_headers):
|
|
4
|
+
self._request = request_method
|
|
5
|
+
self._get_auth_headers = get_auth_headers
|
|
6
|
+
|
|
7
|
+
async def get_vehicle_history(self, privileged_token, token_id, start_time=None, end_time=None, buckets=None):
|
|
8
|
+
params = {}
|
|
9
|
+
if start_time is not None:
|
|
10
|
+
params['startTime'] = start_time
|
|
11
|
+
if end_time is not None:
|
|
12
|
+
params['endTime'] = end_time
|
|
13
|
+
if buckets is not None:
|
|
14
|
+
params['buckets'] = buckets
|
|
15
|
+
url = f'/v2/vehicle/{token_id}/history'
|
|
16
|
+
return self._request(
|
|
17
|
+
'GET',
|
|
18
|
+
'DeviceData',
|
|
19
|
+
url,
|
|
20
|
+
params=params,
|
|
21
|
+
headers=self._get_auth_headers(privileged_token)
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
async def get_vehicle_status(self, privileged_token, token_id):
|
|
25
|
+
url = f'/v2/vehicle/{token_id}/status'
|
|
26
|
+
return self._request(
|
|
27
|
+
'GET',
|
|
28
|
+
'DeviceData',
|
|
29
|
+
url,
|
|
30
|
+
headers=self._get_auth_headers(privileged_token)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
async def get_v1_vehicle_history(self, privileged_token, token_id, start_date=None, end_date=None):
|
|
34
|
+
params = {}
|
|
35
|
+
if start_date is not None:
|
|
36
|
+
params['startDate'] = start_date
|
|
37
|
+
if end_date is not None:
|
|
38
|
+
params['endDate'] = end_date
|
|
39
|
+
url = f'/v1/vehicle/{token_id}/history'
|
|
40
|
+
return self._request(
|
|
41
|
+
'GET',
|
|
42
|
+
'DeviceData',
|
|
43
|
+
url,
|
|
44
|
+
params=params,
|
|
45
|
+
headers=self._get_auth_headers(privileged_token)
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
async def get_v1_vehicle_status(self, privileged_token, token_id):
|
|
49
|
+
url = f'/v1/vehicle/{token_id}/status'
|
|
50
|
+
return self._request(
|
|
51
|
+
'GET',
|
|
52
|
+
'DeviceData',
|
|
53
|
+
url,
|
|
54
|
+
headers=self._get_auth_headers(privileged_token)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
async def get_v1_vehicle_status_raw(self, privileged_token, token_id):
|
|
58
|
+
url = f'/v1/vehicle/{token_id}/status-raw'
|
|
59
|
+
return self._request(
|
|
60
|
+
'GET',
|
|
61
|
+
'DeviceData',
|
|
62
|
+
url,
|
|
63
|
+
headers=self._get_auth_headers(privileged_token)
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
async def get_user_device_status(self, access_token, user_device_id):
|
|
67
|
+
url = f'/v1/user/device-data/{user_device_id}/status'
|
|
68
|
+
return self._request(
|
|
69
|
+
'GET',
|
|
70
|
+
'DeviceData',
|
|
71
|
+
url,
|
|
72
|
+
headers=self._get_auth_headers(access_token)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
async def get_user_device_history(self, access_token, user_device_id, start_date=None, end_date=None):
|
|
76
|
+
params = {}
|
|
77
|
+
if start_date is not None:
|
|
78
|
+
params['startDate'] = start_date
|
|
79
|
+
if end_date is not None:
|
|
80
|
+
params['endDate'] = end_date
|
|
81
|
+
url = f'/v1/user/device-data/{user_device_id}/historical'
|
|
82
|
+
return self._request(
|
|
83
|
+
'GET',
|
|
84
|
+
'DeviceData',
|
|
85
|
+
url,
|
|
86
|
+
params=params,
|
|
87
|
+
headers=self._get_auth_headers(access_token),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
async def get_daily_distance(self, access_token, user_device_id, time_zone):
|
|
91
|
+
params = {
|
|
92
|
+
'timeZone': time_zone
|
|
93
|
+
}
|
|
94
|
+
url = f'/v1/user/device-data/{user_device_id}/daily-distance'
|
|
95
|
+
return self._request(
|
|
96
|
+
'GET',
|
|
97
|
+
'DeviceData',
|
|
98
|
+
url,
|
|
99
|
+
headers=self._get_auth_headers(access_token),
|
|
100
|
+
params=params)
|
|
101
|
+
|
|
102
|
+
async def get_total_distance(self, access_token, user_device_id):
|
|
103
|
+
url = f'/v1/user/device-data/{user_device_id}/distance-driven'
|
|
104
|
+
return self._request(
|
|
105
|
+
'GET',
|
|
106
|
+
'DeviceData',
|
|
107
|
+
url,
|
|
108
|
+
headers=self._get_auth_headers(access_token)
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
async def send_json_export_email(self, access_token, user_device_id):
|
|
112
|
+
url = f'/v1/user/device-data/{user_device_id}/export/json/email'
|
|
113
|
+
return self._request(
|
|
114
|
+
'POST',
|
|
115
|
+
'DeviceData',
|
|
116
|
+
url,
|
|
117
|
+
headers=self._get_auth_headers(access_token)
|
|
118
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
class DeviceDefinitions:
|
|
2
|
+
|
|
3
|
+
def __init__(self, request_method, get_auth_headers):
|
|
4
|
+
self._request = request_method
|
|
5
|
+
self._get_auth_headers = get_auth_headers
|
|
6
|
+
|
|
7
|
+
async def get_by_mmy(self, make, model, year):
|
|
8
|
+
params = {
|
|
9
|
+
'make': make,
|
|
10
|
+
'model': model,
|
|
11
|
+
'year': year
|
|
12
|
+
}
|
|
13
|
+
return self._request(
|
|
14
|
+
'GET',
|
|
15
|
+
'DeviceDefinitions',
|
|
16
|
+
'/device-definitions',
|
|
17
|
+
params=params
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
async def get_by_id(self, id):
|
|
21
|
+
url = f'/device-definitions/{id}'
|
|
22
|
+
return self._request(
|
|
23
|
+
'GET',
|
|
24
|
+
'DeviceDefinitions',
|
|
25
|
+
url)
|
|
26
|
+
|
|
27
|
+
async def list_device_makes(self):
|
|
28
|
+
return self._request(
|
|
29
|
+
'GET',
|
|
30
|
+
'DeviceDefinitions',
|
|
31
|
+
'/device-makes'
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
async def get_device_type_by_id(self, id):
|
|
35
|
+
url = f'/device-types/{id}'
|
|
36
|
+
return self._request(
|
|
37
|
+
'GET',
|
|
38
|
+
'DeviceDefinitions',
|
|
39
|
+
url)
|
dimo/devices.py
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
class Devices:
|
|
2
|
+
|
|
3
|
+
def __init__(self, request_method, get_auth_headers):
|
|
4
|
+
self._request = request_method
|
|
5
|
+
self._get_auth_headers = get_auth_headers
|
|
6
|
+
|
|
7
|
+
async def create_vehicle(self, access_token, country_code, device_definition_id):
|
|
8
|
+
body = {
|
|
9
|
+
'countryCode': country_code,
|
|
10
|
+
'deviceDefinitionId': device_definition_id
|
|
11
|
+
}
|
|
12
|
+
return self._request(
|
|
13
|
+
'POST',
|
|
14
|
+
'Devices',
|
|
15
|
+
'/v1/user/devices',
|
|
16
|
+
headers=self._get_auth_headers(access_token),
|
|
17
|
+
data=body
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
async def create_vehicle_from_smartcar(self, access_token, code, country_code, redirect_uri):
|
|
21
|
+
body = {
|
|
22
|
+
'code': code,
|
|
23
|
+
'countryCode': country_code,
|
|
24
|
+
'redirectURI': redirect_uri
|
|
25
|
+
}
|
|
26
|
+
return self._request(
|
|
27
|
+
'POST',
|
|
28
|
+
'Devices',
|
|
29
|
+
'/v1/user/devices/fromsmartcar',
|
|
30
|
+
headers=self._get_auth_headers(access_token),
|
|
31
|
+
data=body
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
async def create_vehicle_from_vin(self, access_token, can_protocol, country_code, vin):
|
|
35
|
+
body = {
|
|
36
|
+
'canProtocol': can_protocol,
|
|
37
|
+
'countryCode': country_code,
|
|
38
|
+
'vin': vin
|
|
39
|
+
}
|
|
40
|
+
return self._request(
|
|
41
|
+
'POST',
|
|
42
|
+
'Devices',
|
|
43
|
+
'/v1/user/devices/fromvin',
|
|
44
|
+
headers=self._get_auth_headers(access_token),
|
|
45
|
+
data=body
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
async def update_vehicle_vin(self, access_token, user_device_id):
|
|
49
|
+
url = f'/v1/user/devices/{user_device_id}/vin'
|
|
50
|
+
return self._request(
|
|
51
|
+
'PATCH',
|
|
52
|
+
'Devices',
|
|
53
|
+
url,
|
|
54
|
+
headers=self._get_auth_headers(access_token)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
async def get_claiming_payload(self, access_token, serial):
|
|
58
|
+
url = f'/v1/aftermarket/device/by-serial/{serial}/commands/claim'
|
|
59
|
+
return self._request(
|
|
60
|
+
'POST',
|
|
61
|
+
'Devices',
|
|
62
|
+
url,
|
|
63
|
+
headers=self._get_auth_headers(access_token)
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
async def sign_claiming_payload(self, access_token, serial, claim_request):
|
|
67
|
+
body = {
|
|
68
|
+
'claimRequest': claim_request
|
|
69
|
+
}
|
|
70
|
+
url = f'/v1/aftermarket/device/by-serial/{serial}/commands/claim'
|
|
71
|
+
return self._request(
|
|
72
|
+
'POST',
|
|
73
|
+
'Devices',
|
|
74
|
+
url,
|
|
75
|
+
headers=self._get_auth_headers(access_token),
|
|
76
|
+
data=body
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
async def get_minting_payload(self, access_token, user_device_id):
|
|
80
|
+
url = f'/v1/user/devices/{user_device_id}/commands/mint'
|
|
81
|
+
return self._request(
|
|
82
|
+
'POST',
|
|
83
|
+
'Devices',
|
|
84
|
+
url,
|
|
85
|
+
headers=self._get_auth_headers(access_token)
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
async def sign_minting_payload(self, access_token, user_device_id, mint_request):
|
|
89
|
+
body = {
|
|
90
|
+
'mintRequest': mint_request
|
|
91
|
+
}
|
|
92
|
+
url = f'/v1/user/devices/{user_device_id}/commands/mint'
|
|
93
|
+
return self._request(
|
|
94
|
+
'POST',
|
|
95
|
+
'Devices',
|
|
96
|
+
url,
|
|
97
|
+
headers=self._get_auth_headers(access_token),
|
|
98
|
+
data=body
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
async def opt_in_share_data(self, access_token, user_device_id):
|
|
102
|
+
url = f'/v1/user/devices/{user_device_id}/commands/opt-in'
|
|
103
|
+
return self._request(
|
|
104
|
+
'POST',
|
|
105
|
+
'Devices',
|
|
106
|
+
url,
|
|
107
|
+
headers=self._get_auth_headers(access_token)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
async def refresh_smartcar_data(self, access_token, user_device_id):
|
|
111
|
+
url = f'/v1/user/devices/{user_device_id}/commands/refresh'
|
|
112
|
+
return self._request(
|
|
113
|
+
'POST',
|
|
114
|
+
'Devices',
|
|
115
|
+
url,
|
|
116
|
+
headers=self._get_auth_headers(access_token)
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
async def get_pairing_payload(self, access_token, user_device_id):
|
|
120
|
+
url = f'/v1/user/devices/{user_device_id}/aftermarket/commands/pair'
|
|
121
|
+
return self._request(
|
|
122
|
+
'GET',
|
|
123
|
+
'Devices',
|
|
124
|
+
url,
|
|
125
|
+
headers=self._get_auth_headers(access_token)
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
async def sign_pairing_payload(self, access_token, user_device_id, user_signature):
|
|
129
|
+
body = {
|
|
130
|
+
'userSignature': user_signature
|
|
131
|
+
}
|
|
132
|
+
url = f'/v1/user/devices/{user_device_id}/aftermarket/commands/pair'
|
|
133
|
+
return self._request(
|
|
134
|
+
'POST',
|
|
135
|
+
'Devices',
|
|
136
|
+
url,
|
|
137
|
+
headers=self._get_auth_headers(access_token),
|
|
138
|
+
data=body
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
async def get_unpairing_payload(self, access_token, user_device_id):
|
|
142
|
+
url = f'/v1/user/devices/{user_device_id}/aftermarket/commands/unpair'
|
|
143
|
+
return self._request(
|
|
144
|
+
'GET',
|
|
145
|
+
'Devices',
|
|
146
|
+
url,
|
|
147
|
+
headers=self._get_auth_headers(access_token)
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
async def sign_unpairing_payload(self, access_token, user_device_id, user_signature):
|
|
151
|
+
body = {
|
|
152
|
+
'userSignature': user_signature
|
|
153
|
+
}
|
|
154
|
+
url = f'/v1/user/devices/{user_device_id}/aftermarket/commands/unpair'
|
|
155
|
+
return self._request(
|
|
156
|
+
'POST',
|
|
157
|
+
'Devices',
|
|
158
|
+
url,
|
|
159
|
+
headers=self._get_auth_headers(access_token),
|
|
160
|
+
data=body
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
async def lock_doors(self, privilege_token, token_id):
|
|
164
|
+
url = f'/v1/vehicle/{token_id}/commands/doors/lock'
|
|
165
|
+
return self._request(
|
|
166
|
+
'POST',
|
|
167
|
+
'Devices',
|
|
168
|
+
url,
|
|
169
|
+
headers=self._get_auth_headers(privilege_token)
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
async def unlock_doors(self, privilege_token, token_id):
|
|
173
|
+
url = f'/v1/vehicle/{token_id}/commands/doors/unlock'
|
|
174
|
+
return self._request(
|
|
175
|
+
'POST',
|
|
176
|
+
'Devices',
|
|
177
|
+
url,
|
|
178
|
+
headers=self._get_auth_headers(privilege_token)
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
async def open_frunk(self, privilege_token, token_id):
|
|
182
|
+
url = f'/v1/vehicle/{token_id}/commands/frunk/open'
|
|
183
|
+
return self._request(
|
|
184
|
+
'POST',
|
|
185
|
+
'Devices',
|
|
186
|
+
url,
|
|
187
|
+
headers=self._get_auth_headers(privilege_token)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
async def open_trunk(self, privilege_token, token_id):
|
|
191
|
+
url = f'/v1/vehicle/{token_id}/commands/trunk/open'
|
|
192
|
+
return self._request(
|
|
193
|
+
'POST',
|
|
194
|
+
'Devices',
|
|
195
|
+
url,
|
|
196
|
+
headers=self._get_auth_headers(privilege_token)
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
async def list_error_codes(self, access_token, user_device_id):
|
|
200
|
+
url = f'/v1/user/devices/{user_device_id}/error-codes'
|
|
201
|
+
return self._request(
|
|
202
|
+
'GET',
|
|
203
|
+
'Devices',
|
|
204
|
+
url,
|
|
205
|
+
headers=self._get_auth_headers(access_token)
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
async def submit_error_codes(self, access_token, user_device_id, query_device_error_codes):
|
|
209
|
+
body = {
|
|
210
|
+
'queryDeviceErrorCodes': query_device_error_codes
|
|
211
|
+
}
|
|
212
|
+
url = f'/v1/user/devices/{user_device_id}/error-codes'
|
|
213
|
+
return self._request(
|
|
214
|
+
'POST',
|
|
215
|
+
'Devices',
|
|
216
|
+
url,
|
|
217
|
+
headers=self._get_auth_headers(access_token),
|
|
218
|
+
data=body
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
async def clear_error_codes(self, access_token, user_device_id):
|
|
222
|
+
url = f'/v1/user/devices/{user_device_id}/error-codes/clear'
|
|
223
|
+
return self._request(
|
|
224
|
+
'POST',
|
|
225
|
+
'Devices',
|
|
226
|
+
url,
|
|
227
|
+
headers=self._get_auth_headers(access_token)
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
async def get_aftermarket_device(self, token_id):
|
|
231
|
+
url = f'/v1/aftermarket/device/{token_id}'
|
|
232
|
+
self._request(
|
|
233
|
+
'GET',
|
|
234
|
+
'Devices',
|
|
235
|
+
url
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
async def get_aftermarket_device_image(self, token_id):
|
|
239
|
+
url = f'/v1/aftermarket/device/{token_id}/image'
|
|
240
|
+
self._request(
|
|
241
|
+
'GET',
|
|
242
|
+
'Devices',
|
|
243
|
+
url
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
async def get_aftermarket_device_metadata_by_address(self, address):
|
|
247
|
+
url = f'/v1/aftermarket/device/by-address/{address}'
|
|
248
|
+
self._request(
|
|
249
|
+
'GET',
|
|
250
|
+
'Devices',
|
|
251
|
+
url
|
|
252
|
+
)
|
dimo/dimo.py
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from dimo.auth import Auth
|
|
2
|
+
from dimo.device_data import DeviceData
|
|
3
|
+
from dimo.device_definitions import DeviceDefinitions
|
|
4
|
+
from dimo.devices import Devices
|
|
5
|
+
from dimo.events import Events
|
|
6
|
+
from dimo.token_exchange import TokenExchange
|
|
7
|
+
from dimo.trips import Trips
|
|
8
|
+
from dimo.user import User
|
|
9
|
+
from dimo.valuations import Valuations
|
|
10
|
+
from dimo.vehicle_signal_decoding import VehicleSignalDecoding
|
|
11
|
+
|
|
12
|
+
from dimo.identity import Identity
|
|
13
|
+
from dimo.telemetry import Telemetry
|
|
14
|
+
|
|
15
|
+
from dimo.request import Request
|
|
16
|
+
from dimo.environments import dimo_environment
|
|
17
|
+
import re
|
|
18
|
+
|
|
19
|
+
class DIMO:
|
|
20
|
+
|
|
21
|
+
def __init__(self, env="Production"):
|
|
22
|
+
self.env = env
|
|
23
|
+
self.urls = dimo_environment[env]
|
|
24
|
+
self.auth = Auth(self.request, self._get_auth_headers)
|
|
25
|
+
self.device_data = DeviceData(self.request, self._get_auth_headers)
|
|
26
|
+
self.device_definitions = DeviceDefinitions(self.request, self._get_auth_headers)
|
|
27
|
+
self.devices = Devices(self.request, self._get_auth_headers)
|
|
28
|
+
self.events = Events(self.request, self._get_auth_headers)
|
|
29
|
+
self.token_exchange = TokenExchange(self.request, self._get_auth_headers)
|
|
30
|
+
self.trips = Trips(self.request, self._get_auth_headers)
|
|
31
|
+
self.user = User(self.request, self._get_auth_headers)
|
|
32
|
+
self.valuations = Valuations(self.request, self._get_auth_headers)
|
|
33
|
+
self.vehicle_signal_decoding = VehicleSignalDecoding(self.request, self._get_auth_headers)
|
|
34
|
+
self.identity = Identity(self)
|
|
35
|
+
self.telemetry = Telemetry(self)
|
|
36
|
+
self._session = Request.session
|
|
37
|
+
|
|
38
|
+
# Creates a full path for endpoints combining DIMO service, specific endpoint, and optional params
|
|
39
|
+
def _get_full_path(self, service, path, params=None):
|
|
40
|
+
base_path = self.urls[service]
|
|
41
|
+
full_path = f"{base_path}{path}"
|
|
42
|
+
|
|
43
|
+
if params:
|
|
44
|
+
for key, value in params.items():
|
|
45
|
+
pattern = f":{key}"
|
|
46
|
+
full_path = re.sub(pattern, str(value), full_path)
|
|
47
|
+
return full_path
|
|
48
|
+
|
|
49
|
+
# Sets headers based on access_token or privileged_token
|
|
50
|
+
def _get_auth_headers(self, token):
|
|
51
|
+
return {
|
|
52
|
+
'Authorization': f'Bearer {token}',
|
|
53
|
+
'Content-Type': 'application/json'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# request method for HTTP requests for the REST API
|
|
57
|
+
def request(self, http_method, service, path, **kwargs):
|
|
58
|
+
full_path = self._get_full_path(service, path)
|
|
59
|
+
return Request(http_method, full_path)(**kwargs)
|
|
60
|
+
|
|
61
|
+
# query method for graphQL queries, identity and telemetry
|
|
62
|
+
async def query(self, service, query, variables=None, token=None):
|
|
63
|
+
headers = self._get_auth_headers(token) if token else {}
|
|
64
|
+
headers['Content-Type'] = 'application/json'
|
|
65
|
+
headers['User-Agent'] = 'dimo-python-sdk'
|
|
66
|
+
|
|
67
|
+
data = {
|
|
68
|
+
'query': query,
|
|
69
|
+
'variables': variables or {}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
response = self.request(
|
|
73
|
+
'POST',
|
|
74
|
+
service,
|
|
75
|
+
'',
|
|
76
|
+
headers=headers,
|
|
77
|
+
data=data
|
|
78
|
+
)
|
|
79
|
+
return response
|
dimo/environments.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
dimo_environment = {
|
|
2
|
+
"Production": {
|
|
3
|
+
'Auth': 'https://auth.dimo.zone',
|
|
4
|
+
'Identity': 'https://identity-api.dimo.zone/query',
|
|
5
|
+
'Devices': 'https://devices-api.dimo.zone',
|
|
6
|
+
'DeviceData': 'https://device-data-api.dimo.zone',
|
|
7
|
+
'DeviceDefinitions': 'https://device-definitions-api.dimo.zone',
|
|
8
|
+
'Events': 'https://events-api.dimo.zone',
|
|
9
|
+
'Telemetry': 'https://telemetry-api.dimo.zone/query',
|
|
10
|
+
'TokenExchange': 'https://token-exchange-api.dimo.zone',
|
|
11
|
+
'Trips': 'https://trips-api.dimo.zone',
|
|
12
|
+
'User': 'https://users-api.dimo.zone',
|
|
13
|
+
'Valuations': 'https://valuations-api.dimo.zone',
|
|
14
|
+
'VehicleSignalDecoding': 'https://vehicle-signal-decoding.dimo.zone'
|
|
15
|
+
},
|
|
16
|
+
"Dev": {
|
|
17
|
+
'Auth': 'https://auth.dev.dimo.zone',
|
|
18
|
+
'Identity': 'https://identity-api.dev.dimo.zone/query',
|
|
19
|
+
'Devices': 'https://devices-api.dev.dimo.zone',
|
|
20
|
+
'DeviceData': 'https://device-data-api.dev.dimo.zone',
|
|
21
|
+
'DeviceDefinitions': 'https://device-definitions-api.dev.dimo.zone',
|
|
22
|
+
'Events': 'https://events-api.dev.dimo.zone',
|
|
23
|
+
'Telemetry': 'https://telemetry-api.dev.dimo.zone/query',
|
|
24
|
+
'TokenExchange': 'https://token-exchange-api.dev.dimo.zone',
|
|
25
|
+
'Trips': 'https://trips-api.dev.dimo.zone',
|
|
26
|
+
'User': 'https://users-api.dev.dimo.zone',
|
|
27
|
+
'Valuations': 'https://valuations-api.dev.dimo.zone',
|
|
28
|
+
'VehicleSignalDecoding': 'https://vehicle-signal-decoding.dev.dimo.zone'
|
|
29
|
+
}
|
|
30
|
+
}
|
dimo/events.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class Events:
|
|
2
|
+
|
|
3
|
+
def __init__(self, request_method, get_auth_headers):
|
|
4
|
+
self._request = request_method
|
|
5
|
+
self._get_auth_headers = get_auth_headers
|
|
6
|
+
|
|
7
|
+
async def get_events(self, access_token):
|
|
8
|
+
return self._request(
|
|
9
|
+
'GET',
|
|
10
|
+
'Events',
|
|
11
|
+
'/v1/events',
|
|
12
|
+
headers=self._get_auth_headers(access_token)
|
|
13
|
+
)
|