autoverse-cli 0.1.0__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.
avrs/requests/can.py ADDED
@@ -0,0 +1,131 @@
1
+ from avrs.requests.request import AvrsApiRequest
2
+ import can
3
+ import cantools
4
+ import time
5
+ import os
6
+ import pandas as pd
7
+ import datetime
8
+
9
+ # class Can():
10
+ # def __init__(self, parser, cfg):
11
+ # psr = parser.add_parser('can', help='Peforms a variety of CAN commands')
12
+ # sps = psr.add_subparsers(required= True, help='sub-command of NPC')
13
+ # SendCan(sps, dbc)
14
+ # #TestCanRates(sps, cfg)
15
+ # LogCan(sps, dbc)
16
+
17
+
18
+ # class SendCan(AvrsApiRequest):
19
+ # def __init__(self, parser, dbc):
20
+ # psr = parser.add_parser('send', help='sends CAN data for given duration (seconds) with given throttle and steer percent values')
21
+ # psr.add_argument('duration', type=float, help='Length of time to send Can data')
22
+ # psr.add_argument('hertz', type=float, help = 'Frequency of Can Messages')
23
+ # psr.add_argument('throttle', type=float, help='throttle (in percent)')
24
+ # psr.add_argument('steer', type=float, help='steer (in percent)')
25
+ # self.dbc = dbc
26
+ # psr.set_defaults(func=self.send_can_values)
27
+
28
+
29
+ # def send_can_values(self, args):
30
+ # with can.interface.Bus('vcan0', bustype='socketcan') as bus:
31
+ # message_1 = self.dbc.get_message_by_name("HL_Msg_01")
32
+ # message_2 = self.dbc.get_message_by_name("HL_Msg_02")
33
+ # signals_1 = {
34
+ # "HL_TargetThrottle": args.throttle,
35
+ # "HL_TargetGear": 1,
36
+ # "HL_TargetPressure_RR": 0,
37
+ # "HL_TargetPressure_RL": 0,
38
+ # "HL_TargetPressure_FR": 0,
39
+ # "HL_TargetPressure_FL": 0,
40
+ # "HL_Alive_01": 0,
41
+ # }
42
+
43
+ # signals_2 = {
44
+ # "HL_Alive_02": 0,
45
+ # "HL_PSA_Profile_Vel_rad_s": 0,
46
+ # "HL_PSA_Profile_Dec_rad_s2": 0,
47
+ # "HL_PSA_Profile_Acc_rad_s2": 0,
48
+ # "HL_TargetPSAControl": args.steer,
49
+ # "HL_PSA_ModeOfOperation": 0,
50
+ # }
51
+
52
+ # start_time = time.time()
53
+
54
+ # print('sending can data...')
55
+ # while time.time() - start_time < args.duration:
56
+ # data = message_1.encode(signals_1)
57
+ # msg = can.Message(arbitration_id=message_1.frame_id, data=data, is_extended_id=False)
58
+ # bus.send(msg)
59
+
60
+ # data = message_2.encode(signals_2)
61
+ # msg = can.Message(arbitration_id=message_2.frame_id, data=data, is_extended_id=False)
62
+ # bus.send(msg)
63
+ # time.sleep(args.hertz)
64
+ # print('done')
65
+
66
+
67
+ # # class TestCanRates(AvrsApiRequest):
68
+ # # def __init__(self, parser, cfg):
69
+ # # AvrsApiRequest.__init__(self, parser, cfg, 'TestCanRates')
70
+ # # psr = parser.add_parser('test-rates', help='get average can message rates over given duration for all can messages on vcan0')
71
+ # # psr.add_argument('duration', type=float, help='Length of time to test Can rates')
72
+ # # psr.set_defaults(func=self.send_request)
73
+
74
+
75
+ # # def get_request_body(self, args):
76
+ # # return {
77
+ # # 'Duration': args.duration,
78
+ # # }
79
+
80
+ # class LogCan(AvrsApiRequest):
81
+ # def __init__(self, parser, dbc):
82
+ # psr = parser.add_parser('log', help='logs csv CAN data for given duration (seconds) to the given absolute file path. Will append numbers to colliding file names')
83
+ # psr.add_argument('duration', type=float, help='length of time to log Can data')
84
+ # psr.add_argument('path', help='absoulte file path')
85
+ # psr.set_defaults(func=self.log_can)
86
+ # self.dbc = dbc
87
+
88
+ # def log_can(self, args):
89
+ # start_time = time.time()
90
+
91
+ # # Check and remove the existing 'messages.csv' file
92
+ # file_no = 1
93
+ # tmp_file_path = args.path
94
+ # print(tmp_file_path)
95
+ # while os.path.exists(tmp_file_path):
96
+ # tmp_file_path = args.path.replace('.csv', '{}.csv'.format(file_no))
97
+ # file_no += 1
98
+ # args.path = tmp_file_path
99
+
100
+ # messages_list = []
101
+ # databases = [self.dbc]
102
+ # print('logging can data...')
103
+
104
+ # with can.interface.Bus('vcan0', bustype='socketcan') as bus:
105
+ # while time.time() - start_time < args.duration:
106
+ # message = bus.recv()
107
+ # # If a message was received
108
+ # if message is not None:
109
+ # for db in databases:
110
+ # decoded = self.decode_message(message)
111
+ # if decoded:
112
+ # messages_list.append(decoded)
113
+ # break
114
+ # df = pd.DataFrame(messages_list)
115
+ # df.to_csv(args.path, index=False)
116
+ # print('done')
117
+
118
+
119
+ # def decode_message(self, message):
120
+ # try:
121
+ # decoded_message = self.dbc.decode_message(message.arbitration_id, message.data)
122
+ # message_name = self.dbc.get_message_by_frame_id(message.arbitration_id).name
123
+ # timestamp = datetime.datetime.now().isoformat()
124
+ # return {'timestamp': timestamp, 'name': message_name, 'data': decoded_message}
125
+ # except KeyError:
126
+ # # Return None if decoding fails
127
+ # return None
128
+
129
+
130
+
131
+
avrs/requests/demo.py ADDED
@@ -0,0 +1,23 @@
1
+ from avrs.requests.request import AvrsApiRequest
2
+
3
+ class AvrsDemoRequest(AvrsApiRequest):
4
+ def __init__(self, parser, cfg):
5
+ AvrsApiRequest.__init__(self, parser, cfg, 'DemoSendConfig', '')
6
+ psr = parser.add_parser('demo', help='Sends a request used for a demonstration')
7
+ psr.add_argument('--ego-type-index', type=int, default=0, help='')
8
+ psr.add_argument('--num-npcs', type=int, default=0, help='')
9
+ psr.add_argument('--npc-trajs', type=int, default=[0, 0, 0, 0], nargs='+', help='')
10
+ psr.add_argument('--npc-type-index', default=0, type=int)
11
+ psr.add_argument('--env-type-index', default=0, type=int)
12
+ psr.add_argument('--weather-type-index', default=0, type=int)
13
+ psr.set_defaults(func=self.send_request)
14
+
15
+ def get_request_body(self, args):
16
+ return {
17
+ 'IndexEgoType': args.ego_type_index,
18
+ 'NumberNPCS': args.num_npcs,
19
+ 'NPCTrajectories': args.npc_trajs,
20
+ 'IndexNPCType': args.npc_type_index,
21
+ 'IndexEnvironmentType': args.env_type_index,
22
+ 'TypeIndexIndex': args.weather_type_index
23
+ }
avrs/requests/input.py ADDED
@@ -0,0 +1,46 @@
1
+ from avrs.requests.request import AvrsApiRequest
2
+
3
+ class InputRequest(AvrsApiRequest):
4
+ def __init__(self, parser, cfg):
5
+ psr = parser.add_parser('user-input', help='Commands related to controlling the vehicles with controllers')
6
+ sps = psr.add_subparsers(required= True, help='sub-command of Input')
7
+ EnableInput(sps, cfg)
8
+ DisableInput(sps, cfg)
9
+ ChangeInput(sps, cfg)
10
+
11
+ class EnableInput(AvrsApiRequest):
12
+ def __init__(self, parser, cfg):
13
+ AvrsApiRequest.__init__(self, parser, cfg, 'EnableInput', 'Ego')
14
+ psr = parser.add_parser('enable', help='Enable user input on car')
15
+ psr.add_argument('controller', help='type of way to control the actor', nargs = 1,
16
+ choices=('keyboard', 'xbox', 'wheel', 'can'))
17
+ psr.set_defaults(func=self.send_request)
18
+
19
+ def get_request_body(self, args):
20
+ return {
21
+ 'Controller': args.controller
22
+ }
23
+
24
+ class DisableInput(AvrsApiRequest):
25
+ def __init__(self, parser, cfg):
26
+ AvrsApiRequest.__init__(self, parser, cfg, 'DisableInput', 'Ego')
27
+ psr = parser.add_parser('disable', help='disable user input on car')
28
+ psr.set_defaults(func=self.send_request)
29
+
30
+ def get_request_body(self, args):
31
+ return {
32
+ }
33
+
34
+ class ChangeInput(AvrsApiRequest):
35
+ def __init__(self, parser, cfg):
36
+ AvrsApiRequest.__init__(self, parser, cfg, 'ChangeInput', 'Ego')
37
+ psr = parser.add_parser('change', help='change the input type if input is already enabled')
38
+ psr.add_argument('controller', help='type of way to control the actor', nargs = 1,
39
+ choices=('keyboard', 'xbox', 'wheel'))
40
+ psr.set_defaults(func=self.send_request)
41
+
42
+ def get_request_body(self, args):
43
+ return {
44
+ 'Controller': args.controller
45
+ }
46
+
@@ -0,0 +1,28 @@
1
+ from avrs.requests.request import AvrsApiRequest
2
+
3
+ class LogPath(AvrsApiRequest):
4
+ def __init__(self, parser, cfg):
5
+ AvrsApiRequest.__init__(self, parser, cfg, 'LogPath', 'Ego')
6
+ psr = parser.add_parser('log-path', help='logs the path of the current vehicle so it can be used as' +
7
+ ' an NPC profile')
8
+
9
+ psr.add_argument('filename', help = 'the name of the file you want')
10
+ psr.add_argument('time', type = float, help = 'the time in seconds you want to log the vehicle path. If you want to keep continously logging until'
11
+ + ' end of simulation, enter -1')
12
+ psr.add_argument('filepath', nargs='?', help = '(Optional) By default the csv saves in your saved folder located in the simulator.' +
13
+ ' However if you would like to save to a new location, please provide an ABSOLUTE file path', default = None)
14
+ psr.set_defaults(func=self.send_request)
15
+
16
+ def get_request_body(self, args):
17
+ if args.filepath == None:
18
+ return {
19
+ 'Filename' : args.filename,
20
+ 'Time' : args.time,
21
+ 'AbsolutePath' : ""
22
+ }
23
+ else:
24
+ return {
25
+ 'Filename' : args.filename,
26
+ 'Time' : args.time,
27
+ 'Path' : args.filepath
28
+ }
@@ -0,0 +1,16 @@
1
+
2
+ from avrs.requests.request import AvrsApiRequest
3
+
4
+ class MoveToLandmarkRequest(AvrsApiRequest):
5
+ def __init__(self, parser, cfg):
6
+ AvrsApiRequest.__init__(self, parser, cfg, 'MoveToLandmark', 'Ego')
7
+ psr = parser.add_parser('move-to-landmark', help='command an object to move to a landmark')
8
+ psr.add_argument('--object-name', default='Ego', help='the name of the object to move')
9
+ psr.add_argument('landmark', help='the name of the landmark to move the object to')
10
+ psr.set_defaults(func=self.send_request)
11
+
12
+ def get_request_body(self, args):
13
+ self.target_object_id = args.object_name
14
+ return {
15
+ 'LandmarkName': args.landmark
16
+ }
avrs/requests/npc.py ADDED
@@ -0,0 +1,289 @@
1
+ from avrs.requests.request import AvrsApiRequest
2
+ from argparse import RawDescriptionHelpFormatter
3
+ from argparse import RawTextHelpFormatter
4
+
5
+ class Npc():
6
+ def __init__(self, parser, cfg):
7
+ psr = parser.add_parser('npc', help='Peforms a variety of NPC control commands')
8
+ sps = psr.add_subparsers(required= True, help='sub-command of NPC')
9
+ NpcSpawn(sps, cfg)
10
+ NpcDespawn(sps, cfg)
11
+ NpcChangeDifficulty(sps, cfg)
12
+ NpcStart(sps, cfg)
13
+ NpcStop(sps, cfg)
14
+ NpcSetSpeed(sps, cfg)
15
+ NpcChangeProfile(sps, cfg)
16
+ NpcTeleport(sps, cfg)
17
+
18
+ NPC_SPAWN_POSITION_HELP = '''
19
+ spawn the NPC in a relative position or absoulte position
20
+ '''
21
+
22
+ NPC_SPAWN_PROFILE_HELP = '''
23
+ Sets the profile of which the npc follows. Note: the profiles provided are ones Provided by Autonoma.
24
+ If you wish to use your own you have two options. If your custom profile
25
+ is located in the saved folder of the simulator you can just enter the filename.
26
+ However if this is not the case you must enter the absolute path of the file
27
+ Provided Profiles:
28
+ middleRouteYas
29
+ leftRouteYas
30
+ rightRouteYas
31
+ backMiddleRouteYas
32
+ backLeftRouteYas
33
+ '''
34
+
35
+ NPC_ROUTE_CHOICES = [
36
+ 'middleRouteYas',
37
+ 'leftRouteYas',
38
+ 'rightRouteYas',
39
+ 'backMiddleRouteYas',
40
+ 'backLeftRouteYas',
41
+ 'atlNpc1',
42
+ 'atlNpc2',
43
+ 'atlNpc3',
44
+ 'atlNpc4',
45
+ 'atlNpc5'
46
+ ]
47
+
48
+ class NpcSpawn(AvrsApiRequest):
49
+ def __init__(self, parser, cfg):
50
+ AvrsApiRequest.__init__(self, parser, cfg, 'SpawnObject', '')
51
+ psr = parser.add_parser(
52
+ 'spawn', help='spawn an NPC', formatter_class=RawTextHelpFormatter)
53
+
54
+ psr.add_argument(
55
+ '--name',
56
+ default='npc0',
57
+ help='name of the npc to spawn')
58
+
59
+ psr.add_argument(
60
+ '--vehicle-type',
61
+ default='HondaOdyssey',
62
+ help='what type of vehicle to spawn as an NPC')
63
+
64
+ psr.add_argument(
65
+ '--position',
66
+ choices=('relative', 'absolute'),
67
+ default='absolute',
68
+ help=NPC_SPAWN_POSITION_HELP)
69
+
70
+ psr.add_argument(
71
+ '--profile',
72
+ default='leftRouteYas',
73
+ help=NPC_SPAWN_PROFILE_HELP)
74
+
75
+ psr.add_argument(
76
+ '--velocity-type',
77
+ default='constant',
78
+ help='the path the NPC follows is a constant velocity or speed')
79
+
80
+ psr.add_argument(
81
+ '--speed',
82
+ type=float,
83
+ default=20,
84
+ help='the speed of the npc is m/s')
85
+
86
+ psr.add_argument(
87
+ '--difficulty',
88
+ type=float,
89
+ default=1.0,
90
+ help='the playback speed of the velocity profile, 1.0 is normal')
91
+
92
+ psr.add_argument(
93
+ '--enable-sensors',
94
+ type=bool,
95
+ default=False,
96
+ help='whether to enable sensors on the NPC')
97
+
98
+ psr.add_argument(
99
+ '--with-view-cameras',
100
+ type=bool,
101
+ default=False,
102
+ help='whether to attach viewing cameras to the NPC')
103
+
104
+ psr.set_defaults(func=self.send_request)
105
+
106
+
107
+ def get_request_body(self, args):
108
+ if args.profile not in NPC_ROUTE_CHOICES:
109
+ print(f"Warning: '{args.profile}' is not a default option, procceeding with custom file")
110
+
111
+ npc_init_pld = {
112
+ 'Name': args.name,
113
+ 'Position': args.position,
114
+ 'Profile': args.profile,
115
+ 'Velocity' : args.velocity_type,
116
+ 'Speed' : args.speed,
117
+ 'Difficulty' : args.difficulty,
118
+ 'bEnableSensors': args.enable_sensors
119
+ }
120
+
121
+ eav_init_pld = {
122
+ 'VehicleCanName': 'can0'
123
+ }
124
+
125
+ plds = [
126
+ {
127
+ 'TypeName': 'NpcInitializer',
128
+ 'Body': npc_init_pld
129
+ }
130
+ ]
131
+
132
+ if args.with_view_cameras:
133
+ plds.append(
134
+ {
135
+ 'TypeName': 'InitializerTemplates',
136
+ 'Body': {
137
+ 'Templates': [
138
+ {
139
+ 'PayloadType': 'SimViewTargetIpd',
140
+ 'PayloadSpec': 'DefaultCarCams'
141
+ }
142
+ ]
143
+ }
144
+ })
145
+
146
+ return {
147
+ 'Name': args.name,
148
+ 'Type': args.vehicle_type,
149
+ 'Location': {},
150
+ 'Rotation': {},
151
+ 'Payloads': plds
152
+ }
153
+
154
+ class NpcDespawn(AvrsApiRequest):
155
+ def __init__(self, parser, cfg):
156
+ AvrsApiRequest.__init__(self, parser, cfg, 'NpcDespawn', 'Npc')
157
+ psr = parser.add_parser('despawn', help='despawn an NPC')
158
+ psr.add_argument('name', help = 'name of the npc to despawn')
159
+ psr.set_defaults(func=self.send_request)
160
+
161
+ def get_request_body(self, args):
162
+ return {
163
+ 'Name': args.name
164
+ }
165
+
166
+
167
+ class NpcTeleport(AvrsApiRequest):
168
+ def __init__(self, parser, cfg):
169
+ AvrsApiRequest.__init__(self, parser, cfg, 'NpcTeleport', 'Npc')
170
+ psr = parser.add_parser('teleport', help = 'telport an active NPC to new x,y,z location,'
171
+ + 'a location on the path will be selected closeset to this value')
172
+ psr.add_argument('name', help='name of npc to teleport')
173
+ subparsers = psr.add_subparsers(dest = "action", help='sub-command of NPC teleport')
174
+
175
+ # Define the parser for the 'vehicle' option
176
+ vehicle_parser = subparsers.add_parser('vehicle', help='Teleport to the vehicle to an existing car')
177
+
178
+ # Defines the parser for the 'custom' option
179
+ custom_parser = subparsers.add_parser('custom', help='Teleport to custom coordinates')
180
+ custom_parser.add_argument('x', type=float, help='X coordinate.')
181
+ custom_parser.add_argument('y', type=float, help='Y coordinate.')
182
+ custom_parser.add_argument('z', type=float, help='Y coordinate.')
183
+
184
+ psr.set_defaults(func = self.send_request)
185
+
186
+ def get_request_body(self, args):
187
+ if args.action == 'vehicle':
188
+ print("Correct")
189
+ return {
190
+ 'Name': args.name,
191
+ 'Type': args.action,
192
+ 'X': 0,
193
+ 'Y': 0,
194
+ 'Z': 0
195
+ }
196
+ else:
197
+ return {
198
+ 'Name': args.name,
199
+ 'Type': args.action,
200
+ 'X': args.x,
201
+ 'Y': args.y,
202
+ 'Z ': args.z
203
+ }
204
+
205
+ class NpcChangeProfile(AvrsApiRequest):
206
+ def __init__(self, parser, cfg):
207
+ AvrsApiRequest.__init__(self, parser, cfg, 'NpcChangeProfile', 'Npc')
208
+ psr = parser.add_parser('change-path', help = 'changes the raceline of an active NPC')
209
+ psr.add_argument('name', help='name of npc to change the path for')
210
+ psr.add_argument('profile', type=str, help = 'change the profile of the NPC, the same profile constraints apply as the spawn command')
211
+ psr.set_defaults(func=self.send_request)
212
+
213
+ def get_request_body(self, args):
214
+ choices = ['middleRouteYas', 'leftRouteYas', 'rightRouteYas', 'backMiddleRouteYas', 'backLeftRouteYas', 'atlNpc1', 'atlNpc2', 'atlNpc3', 'atlNpc4', 'atlNpc5']
215
+ if args.profile not in choices:
216
+ print(f"Warning: '{args.profile}' is not a default option, procceeding with custom file")
217
+ return {
218
+ 'Name': args.name,
219
+ 'NewProfile': args.profile
220
+ }
221
+
222
+ class NpcChangeDifficulty(AvrsApiRequest):
223
+ def __init__(self, parser, cfg):
224
+ AvrsApiRequest.__init__(self, parser, cfg, 'NpcChangeDifficulty', 'Npc')
225
+ psr = parser.add_parser('change-difficulty', help = 'changes the difficulty or the the playback speed '
226
+ + 'of an npc with a non-constant velocity')
227
+ psr.add_argument('name', help='name of npc to change the path for')
228
+ psr.add_argument('difficulty', type = float, help='name of npc to change the path for')
229
+ psr.set_defaults(func=self.send_request)
230
+
231
+ def get_request_body(self, args):
232
+ return {
233
+ 'Name': args.name,
234
+ 'NewDifficulty': args.difficulty
235
+ }
236
+
237
+
238
+ class NpcStart(AvrsApiRequest):
239
+ def __init__(self, parser, cfg):
240
+ AvrsApiRequest.__init__(self, parser, cfg, 'NpcStart', 'Npc')
241
+ psr = parser.add_parser('start', help = 'start an NPC')
242
+ psr.add_argument('name', help='name of npc to start')
243
+ psr.set_defaults(func=self.send_request)
244
+
245
+ def get_request_body(self, args):
246
+ return {
247
+ 'Name' : args.name
248
+ }
249
+
250
+ class NpcStop(AvrsApiRequest):
251
+ def __init__(self, parser, cfg):
252
+ AvrsApiRequest.__init__(self, parser, cfg, 'NpcStop', 'Npc')
253
+ psr = parser.add_parser('stop', help = 'stop an NPC')
254
+ psr.add_argument('name', help='name of npc to stop')
255
+ psr.set_defaults(func=self.send_request)
256
+
257
+ def get_request_body(self, args):
258
+ return {
259
+ 'Name' : args.name
260
+ }
261
+
262
+
263
+ class NpcSetSpeed(AvrsApiRequest):
264
+ def __init__(self, parser, cfg):
265
+ AvrsApiRequest.__init__(self, parser, cfg, 'NpcSetSpeed', 'Npc')
266
+ psr = parser.add_parser('set-speed', help = 'sets the speed of an Anctive NPC')
267
+ psr.add_argument('name', help='name of npc to change the speed for')
268
+ psr.add_argument('speed', type = float, help='speed of the NPC')
269
+ psr.set_defaults(func=self.send_request)
270
+
271
+ def get_request_body(self, args):
272
+ return {
273
+ 'Name': args.name,
274
+ 'Speed': args.speed
275
+ }
276
+
277
+
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
@@ -0,0 +1,45 @@
1
+ import socket
2
+ import json
3
+ import os
4
+ import os.path
5
+ import multiprocessing
6
+ import time
7
+ import sys
8
+ import http.client
9
+
10
+ class AvrsApiRequest:
11
+ def __init__(self, parser, cfg, request_type, target_id):
12
+ self.target_object_id = target_id
13
+ self.request_type = request_type
14
+
15
+ def get_request(self, args):
16
+ return {
17
+ 'TargetObjectId': self.target_object_id,
18
+ 'RequestType': self.request_type,
19
+ 'RequestBody': json.dumps(self.get_request_body(args))
20
+ }
21
+
22
+ def get_request_body(self, args):
23
+ return '{}'
24
+
25
+ def send_request(self, args):
26
+ #self.send_tcp_request(args)
27
+ self.send_http_request(args)
28
+
29
+ def send_tcp_request(self, args):
30
+ pass
31
+ # s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
32
+ # s.connect((self.ip, self.port))
33
+ # s.send(json.dumps(self.get_request(args)).encode('utf-8'))
34
+ # response = s.recv(self.buffer_size).decode('utf-8')
35
+ # print('{}'.format(response))
36
+
37
+ def send_http_request(self, args):
38
+ connection = http.client.HTTPConnection("localhost", 30313, timeout=2)
39
+ headers = {'Content-type': 'application/json'}
40
+ body = json.dumps(self.get_request(args)).encode('utf-8')
41
+ connection.request('POST', '/post', body, headers)
42
+ response = connection.getresponse()
43
+ if response.status != 200:
44
+ print('response had status code {}'.format(response))
45
+ print('{}'.format(response.read().decode('utf-8')))