Skip to content

Commit b3b45cc

Browse files
committed
added vehicle file
1 parent 64f44df commit b3b45cc

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed

datagen/fleet/vehicle.py

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
import random
2+
import math
3+
import datetime
4+
import uuid
5+
import time
6+
import logging
7+
import json
8+
import paho.mqtt.client as mqtt
9+
from kaa_client import KaaClient, CommandsDto, ConfigurationStatusResponseDto
10+
from paho.mqtt.client import MQTTMessage
11+
12+
class Vehicle(object):
13+
def __init__(self, client: KaaClient):
14+
self.kaa_client = client
15+
self.time = time.time()
16+
self.config = {
17+
"maxSpeed": 185,
18+
"maxRange": 555,
19+
"maintenanceInterval": 15000,
20+
"climateSetpoint": 21
21+
}
22+
23+
self.mileage = random.randint(0, 200)
24+
self.routes = json.load(open('./routes.json'))
25+
self.route_point = -1
26+
27+
self.engine = 1
28+
self.trunk = 1
29+
self.windows = 1
30+
self.lock = 1
31+
self.lights = 0
32+
self.beep = 0
33+
self.climate = 1
34+
35+
self.statuses = ['engine', 'trunk', 'windows', 'lock', 'lights', 'beep', 'climate']
36+
37+
self.range = self.config['maxRange']
38+
self.metadata = {
39+
'name': "Vehicle 1",
40+
'lon': -0.0395317,
41+
'lat': 51.5025671,
42+
'engine': "gasoline",
43+
'model': "Boxster",
44+
'brand': "Porsche",
45+
'year': "2019",
46+
'maxSpeed': 265,
47+
'maxRange': 447,
48+
'power': 256,
49+
'Address': "Dock Hill Ave, Rotherhithe, London SE16 6AX, United Kingdom"
50+
}
51+
52+
def get_device_metadata(self):
53+
self.metadata["lastMaintenance"] = str(datetime.datetime.now())
54+
self.metadata["serial"] = str(uuid.uuid4())
55+
return self.metadata
56+
57+
"""
58+
Generates tiers data
59+
"""
60+
def get_tiers_data(self):
61+
if self.engine == 0:
62+
return {}
63+
else:
64+
front_tires = random.uniform(2.35, 2.4)
65+
rear_tires = random.uniform(2.2, 2.3)
66+
67+
return {
68+
'tiers': {
69+
'front_left': front_tires,
70+
'front_right': front_tires,
71+
'back_left': rear_tires,
72+
'back_right': rear_tires
73+
}
74+
}
75+
76+
"""
77+
Generates hill assist data
78+
"""
79+
def get_hill_assist_data(self):
80+
if self.engine == 0:
81+
return {}
82+
else:
83+
return {
84+
'gyro_x': random.randint(0, 20),
85+
'gyro_y': random.randint(0, 15),
86+
'gyro_z': random.randint(0, 5),
87+
}
88+
89+
def get_climate_data(self):
90+
if self.engine == 0:
91+
return {}
92+
else:
93+
now = datetime.datetime.now()
94+
return {
95+
'climate_temperature': (self.config['climateSetpoint'] - 3) + 3 * math.cos(now.minute + now.second/60.0)
96+
}
97+
98+
"""
99+
Generates engine data
100+
"""
101+
def get_engine_data(self):
102+
if self.engine == 0:
103+
return {}
104+
else:
105+
self.mileage += random.randint(10, 40)
106+
self.range -= random.randint(1, 5)
107+
108+
if self.range < 0:
109+
self.range = self.config['maxRange']
110+
self.kaa_client.publish_data_collection({
111+
'log': {
112+
'message': 'Max range exceeded. Vehicle filled up',
113+
'location': 'UK, London'
114+
}
115+
})
116+
117+
maintenance_in = self.config['maintenanceInterval'] - self.mileage
118+
119+
return {
120+
'speed': random.randint(40, 110),
121+
'rpm': random.randint(600, 2000),
122+
'mileage': self.mileage,
123+
'range': self.range,
124+
'maintenance_in': 0 if maintenance_in < 0 else maintenance_in,
125+
'engine_temperature': random.randint(62, 95)
126+
}
127+
128+
"""
129+
Generates location data
130+
"""
131+
def get_location_data(self):
132+
if self.engine == 0:
133+
return {}
134+
else:
135+
next_point = [self.metadata['lat'], self.metadata['lon']]
136+
137+
try:
138+
self.route_point += 1
139+
next_point = self.routes[self.route_point]
140+
except:
141+
self.route_point = 0
142+
next_point = self.routes[self.route_point]
143+
144+
return {
145+
'location': {
146+
'lat': next_point[0],
147+
'lon': next_point[1]
148+
}
149+
}
150+
151+
"""
152+
Generates telemetry data sample.
153+
"""
154+
def get_data_sample(self):
155+
data = {}
156+
157+
for name in self.statuses:
158+
data[f"{name}_status"] = getattr(self, name)
159+
160+
data.update(self.get_tiers_data())
161+
data.update(self.get_engine_data())
162+
data.update(self.get_hill_assist_data())
163+
data.update(self.get_location_data())
164+
data.update(self.get_climate_data())
165+
166+
return data
167+
168+
"""
169+
Logs command as telemetry
170+
"""
171+
def log_command(self, key: str, value: int):
172+
messages = {
173+
'engine': {0: 'Engine off', 1: 'Engine on'},
174+
'trunk': {0: 'Trunk closed', 1: 'Trunk opened'},
175+
'windows': {0: 'Windows closed', 1: 'Windows opened'},
176+
'lock': {0: 'Car locked', 1: 'Car opened'},
177+
'beep': {0: 'Horn sound off', 1: 'Horn on'},
178+
'climate': {0: 'AC off', 1: 'AC on'}
179+
}
180+
if key in messages:
181+
self.kaa_client.publish_data_collection({
182+
'log': {
183+
'message': messages[key][value],
184+
'location': 'UK, London'
185+
}
186+
})
187+
188+
"""
189+
command name: remote_toggle
190+
example of payloads:
191+
Can be one or combination of keys:
192+
{
193+
"engine": 1,
194+
"trunk": 1,
195+
"windows": 1,
196+
"lock": 1,
197+
"lights": 0,
198+
"beep": 0,
199+
"climate": 1
200+
}
201+
"""
202+
def sensor_toggle(self, client: mqtt.Client, userdata, message: MQTTMessage):
203+
command_payload = str(message.payload.decode('utf-8'))
204+
logging.info(f"Received command: [{message.topic}] []")
205+
response_topic = KaaClient.get_command_response_topic(
206+
message, "remote_toggle")
207+
commands = CommandsDto(command_payload).get_command_responses()
208+
for command in commands:
209+
try:
210+
for key in command.payload.keys():
211+
payload_value = int(command.payload[key])
212+
setattr(self, key, payload_value)
213+
command.status_code = 200
214+
command.payload[key] = "status changed"
215+
self.log_command(key, payload_value)
216+
except Exception as error:
217+
logging.error(
218+
f"Invalid command payload [{error}] [{command.to_dict()}]")
219+
client.publish(
220+
response_topic, self.kaa_client.compose_commands_result(commands))
221+
222+
"""
223+
Handle values `maxSpeed`, `maxRange`, `maintenanceInterval`, `climateSetpoint` published from configuration.
224+
"""
225+
def configuration_handler(self, client: mqtt.Client, userdata, message):
226+
configuration_payload = str(message.payload.decode('utf-8'))
227+
logging.info("Received configuration")
228+
config = ConfigurationStatusResponseDto(
229+
configuration_payload).to_dict()["config"]
230+
if configuration_payload:
231+
for key in config.keys():
232+
self.config[key] = config[key]

0 commit comments

Comments
 (0)