Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
afc919a21d
@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
from bson import json_util
|
from bson import json_util
|
||||||
from flask import Flask, request
|
from flask import Flask, request
|
||||||
from flask_pymongo import PyMongo
|
from flask_pymongo import PyMongo
|
||||||
@ -6,6 +7,38 @@ app = Flask(__name__)
|
|||||||
app.config["MONGO_URI"] = "mongodb://mongo:27017/entities"
|
app.config["MONGO_URI"] = "mongodb://mongo:27017/entities"
|
||||||
mongo = PyMongo(app)
|
mongo = PyMongo(app)
|
||||||
|
|
||||||
|
CAR1_SV = int(os.environ.get('DSE2021_CAR1_SV', 130))
|
||||||
|
CAR2_SV = int(os.environ.get('DSE2021_CAR2_SV', 130))
|
||||||
|
CAR3_SV = int(os.environ.get('DSE2021_CAR3_SV', 130))
|
||||||
|
|
||||||
|
CAR1_SD = int(os.environ.get('DSE2021_CAR1_SD', 300))
|
||||||
|
CAR2_SD = int(os.environ.get('DSE2021_CAR2_SD', 500))
|
||||||
|
CAR3_SD = int(os.environ.get('DSE2021_CAR3_SD', 400))
|
||||||
|
|
||||||
|
CAR1_ST = int(os.environ.get('DSE2021_CAR1_ST', 10))
|
||||||
|
CAR2_ST = int(os.environ.get('DSE2021_CAR2_ST', 15))
|
||||||
|
CAR3_ST = int(os.environ.get('DSE2021_CAR3_ST', 25))
|
||||||
|
|
||||||
|
TL1_R = int(os.environ.get('DSE2021_TL1_R', 2000))
|
||||||
|
TL2_R = int(os.environ.get('DSE2021_TL2_R', 800))
|
||||||
|
TL3_R = int(os.environ.get('DSE2021_TL3_R', 1000))
|
||||||
|
|
||||||
|
mongo.db.trafficLights.update_one({"id": "1"}, {"$set": {"range": TL1_R}})
|
||||||
|
mongo.db.trafficLights.update_one({"id": "2"}, {"$set": {"range": TL2_R}})
|
||||||
|
mongo.db.trafficLights.update_one({"id": "3"}, {"$set": {"range": TL3_R}})
|
||||||
|
|
||||||
|
mongo.db.cars.update_one({"vin": "SCBFR7ZA5CC072256"}, {"$set": {"startingVelocity": CAR1_SV}})
|
||||||
|
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812715"}, {"$set": {"startingVelocity": CAR2_SV}})
|
||||||
|
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812716"}, {"$set": {"startingVelocity": CAR3_SV}})
|
||||||
|
|
||||||
|
mongo.db.cars.update_one({"vin": "SCBFR7ZA5CC072256"}, {"$set": {"startingDistance": CAR1_SD}})
|
||||||
|
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812715"}, {"$set": {"startingDistance": CAR2_SD}})
|
||||||
|
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812716"}, {"$set": {"startingDistance": CAR3_SD}})
|
||||||
|
|
||||||
|
mongo.db.cars.update_one({"vin": "SCBFR7ZA5CC072256"}, {"$set": {"startingTime": CAR1_ST}})
|
||||||
|
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812715"}, {"$set": {"startingTime": CAR2_ST}})
|
||||||
|
mongo.db.cars.update_one({"vin": "5GZCZ43D13S812716"}, {"$set": {"startingTime": CAR3_ST}})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/v1/resources/cars', methods=['GET'])
|
@app.route('/api/v1/resources/cars', methods=['GET'])
|
||||||
def get_cars():
|
def get_cars():
|
||||||
|
|||||||
@ -2,25 +2,16 @@
|
|||||||
{
|
{
|
||||||
"oem": "BENTLEY",
|
"oem": "BENTLEY",
|
||||||
"modelType": "Continental",
|
"modelType": "Continental",
|
||||||
"vin": "SCBFR7ZA5CC072256",
|
"vin": "SCBFR7ZA5CC072256"
|
||||||
"startingVelocity": 130,
|
|
||||||
"startingDistance": 300,
|
|
||||||
"startingTime": 10
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"oem": "SATURN",
|
"oem": "SATURN",
|
||||||
"modelType": "Vue",
|
"modelType": "Vue",
|
||||||
"vin": "5GZCZ43D13S812715",
|
"vin": "5GZCZ43D13S812715"
|
||||||
"startingVelocity": 130,
|
|
||||||
"startingDistance": 500,
|
|
||||||
"startingTime": 15
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"oem": "SATURN",
|
"oem": "SATURN",
|
||||||
"modelType": "Vue2",
|
"modelType": "Vue2",
|
||||||
"vin": "5GZCZ43D13S812716",
|
"vin": "5GZCZ43D13S812716"
|
||||||
"startingVelocity": 130,
|
|
||||||
"startingDistance": 100,
|
|
||||||
"startingTime": 25
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -2,22 +2,19 @@
|
|||||||
{
|
{
|
||||||
"id": "1",
|
"id": "1",
|
||||||
"location": [16.20719, 47.89584],
|
"location": [16.20719, 47.89584],
|
||||||
"range": 2000,
|
"switchingTime": 26,
|
||||||
"switchingTime": 5,
|
|
||||||
"color": "RED"
|
"color": "RED"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2",
|
"id": "2",
|
||||||
"location": [16.20814, 47.90937],
|
"location": [16.20814, 47.90937],
|
||||||
"range": 800,
|
"switchingTime": 16,
|
||||||
"switchingTime": 15,
|
|
||||||
"color": "GREEN"
|
"color": "GREEN"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "3",
|
"id": "3",
|
||||||
"location": [16.20917, 47.92703],
|
"location": [16.20917, 47.92703],
|
||||||
"range": 1000,
|
"switchingTime": 20,
|
||||||
"switchingTime": 10,
|
|
||||||
"color": "RED"
|
"color": "RED"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -16,7 +16,7 @@ from event_logger import EventLogger
|
|||||||
class TestEventLogger(unittest.TestCase):
|
class TestEventLogger(unittest.TestCase):
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
self.el = EventLogger(StrictRedis(), False, False)
|
self.el = EventLogger(StrictRedis(), False, False)
|
||||||
self.timestamp = datetime.datetime.now()
|
self.timestamp = datetime.datetime.utcnow()
|
||||||
|
|
||||||
def test_unpack_daf(self):
|
def test_unpack_daf(self):
|
||||||
daf = DAF(vehicle_identification_number='my_vin',
|
daf = DAF(vehicle_identification_number='my_vin',
|
||||||
@ -60,7 +60,7 @@ class TestEventLogger(unittest.TestCase):
|
|||||||
self.assertEqual(message, json.dumps(unknown))
|
self.assertEqual(message, json.dumps(unknown))
|
||||||
|
|
||||||
def test_unpack_unknown_object(self):
|
def test_unpack_unknown_object(self):
|
||||||
obj = datetime.datetime.now()
|
obj = datetime.datetime.utcnow()
|
||||||
|
|
||||||
key, message = self.el._unpack_message_to_log(pickle.dumps(obj))
|
key, message = self.el._unpack_message_to_log(pickle.dumps(obj))
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import pickle
|
import pickle
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from circuitbreaker import circuit
|
from circuitbreaker import circuit
|
||||||
@ -13,7 +14,7 @@ from pika.exceptions import AMQPConnectionError
|
|||||||
|
|
||||||
SWITCHING_TIME = 15
|
SWITCHING_TIME = 15
|
||||||
# Scale speed of switching by factor x
|
# Scale speed of switching by factor x
|
||||||
SCALING = 1
|
SCALING = int(os.environ.get('DSE2021_SCALING', 1))
|
||||||
|
|
||||||
|
|
||||||
class TrafficLight:
|
class TrafficLight:
|
||||||
@ -56,23 +57,10 @@ class TrafficLight:
|
|||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
"""
|
"""
|
||||||
Starts the traffic light by spawning a new thread. It toggles its state every self.switching_time / SCALING
|
Starts the traffic light by spawning a new thread..
|
||||||
seconds. When it switches, it notifies the orchestrator with self.send_status_update().
|
|
||||||
"""
|
"""
|
||||||
self.running = True
|
self.running = True
|
||||||
|
self._t = threading.Thread(target=self._switcher)
|
||||||
def switcher():
|
|
||||||
num_colors = len(TrafficLightColor)
|
|
||||||
# set current color to the one before starting color, because switch immediately happens in loop
|
|
||||||
# therefore it sleeps on the end of the loop and first status is immediately sent to msg broker
|
|
||||||
self.current_color = TrafficLightColor((self._starting_color.value - 1) % num_colors)
|
|
||||||
while self.running:
|
|
||||||
self.current_color = TrafficLightColor((self.current_color.value + 1) % num_colors)
|
|
||||||
self.last_switch = datetime.now()
|
|
||||||
self.send_status_update()
|
|
||||||
time.sleep(self.switching_time / SCALING)
|
|
||||||
|
|
||||||
self._t = threading.Thread(target=switcher)
|
|
||||||
self._t.start()
|
self._t.start()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
@ -91,6 +79,21 @@ class TrafficLight:
|
|||||||
self._tl_mb.send(pickle.dumps(
|
self._tl_mb.send(pickle.dumps(
|
||||||
TrafficLightState(tlid=self.tlid, color=self.current_color, last_switch=self.last_switch)))
|
TrafficLightState(tlid=self.tlid, color=self.current_color, last_switch=self.last_switch)))
|
||||||
|
|
||||||
|
def _switcher(self):
|
||||||
|
"""
|
||||||
|
Toggles the traffic lights state every self.switching_time / SCALING seconds.
|
||||||
|
When it switches, it notifies the orchestrator with self.send_status_update()
|
||||||
|
"""
|
||||||
|
num_colors = len(TrafficLightColor)
|
||||||
|
# set current color to the one before starting color, because switch immediately happens in loop
|
||||||
|
# therefore it sleeps on the end of the loop and first status is immediately sent to msg broker
|
||||||
|
self.current_color = TrafficLightColor((self._starting_color.value - 1) % num_colors)
|
||||||
|
while self.running:
|
||||||
|
self.current_color = TrafficLightColor((self.current_color.value + 1) % num_colors)
|
||||||
|
self.last_switch = datetime.utcnow()
|
||||||
|
self.send_status_update()
|
||||||
|
time.sleep(self.switching_time / SCALING)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
...
|
...
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import pickle
|
import pickle
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
@ -19,11 +20,13 @@ STARTING_POINT = geopy.Point(47.89053, 16.20703)
|
|||||||
# Driving direction in degrees: 0=N, 90=E, 180=S, 270=W
|
# Driving direction in degrees: 0=N, 90=E, 180=S, 270=W
|
||||||
BEARING = 2
|
BEARING = 2
|
||||||
# Scale speed of vehicles by factor x
|
# Scale speed of vehicles by factor x
|
||||||
SCALING = 1
|
SCALING = int(os.environ.get('DSE2021_SCALING', 1))
|
||||||
# in km/h
|
# in km/h
|
||||||
STARTING_VELOCITY = 130 * SCALING
|
STARTING_VELOCITY = 130 * SCALING
|
||||||
# Interval between status updates in seconds (is not scaled)
|
# Interval between status updates in seconds (is not scaled)
|
||||||
UPDATE_INTERVAL = 1
|
UPDATE_INTERVAL = 1
|
||||||
|
# Specify if NCE should happen
|
||||||
|
NCE = int(os.environ.get('DSE2021_NCE', 1))
|
||||||
# At x km the NCE shall happen
|
# At x km the NCE shall happen
|
||||||
NCE_KM = 2.4
|
NCE_KM = 2.4
|
||||||
# Time in seconds to recover from NCE (will be scaled)
|
# Time in seconds to recover from NCE (will be scaled)
|
||||||
@ -104,8 +107,12 @@ class Vehicle:
|
|||||||
|
|
||||||
:return: True if NCE invoked, otherwise False
|
:return: True if NCE invoked, otherwise False
|
||||||
"""
|
"""
|
||||||
if self._nce_possible and not self._nce_happened:
|
d = geopy.distance.distance(kilometers=0.4)
|
||||||
if self._driven_kms >= NCE_KM:
|
tl2_loc = geopy.Point(47.90937, 16.20814)
|
||||||
|
# Calculate point 400m south of traffic light 2
|
||||||
|
nce_point = d.destination(point=tl2_loc, bearing=182)
|
||||||
|
if NCE == 1 and self._nce_possible and not self._nce_happened:
|
||||||
|
if self._gps_location.latitude >= nce_point.latitude:
|
||||||
self._nce_happened = True
|
self._nce_happened = True
|
||||||
self._last_velocity = self.velocity
|
self._last_velocity = self.velocity
|
||||||
self.velocity = 0
|
self.velocity = 0
|
||||||
@ -163,14 +170,14 @@ class Vehicle:
|
|||||||
|
|
||||||
# Get old and updated timestamps
|
# Get old and updated timestamps
|
||||||
old_timestamp = self.last_update
|
old_timestamp = self.last_update
|
||||||
updated_timestamp = datetime.now()
|
updated_timestamp = datetime.utcnow()
|
||||||
self.last_update = updated_timestamp
|
self.last_update = updated_timestamp
|
||||||
|
|
||||||
# get driving time between timestamps (in seconds)
|
# get driving time between timestamps (in seconds)
|
||||||
driving_time = (updated_timestamp - old_timestamp).total_seconds()
|
driving_time = (updated_timestamp - old_timestamp).total_seconds()
|
||||||
|
|
||||||
# reached distance in kilometers: convert km/h to km/s and multiply by driving time
|
# reached distance in kilometers: convert km/h to km/s and multiply by driving time
|
||||||
kilometers = self.velocity / 3600 * driving_time * SCALING
|
kilometers = self.velocity / 3600 * driving_time
|
||||||
|
|
||||||
# Define a general distance object, initialized with a distance of k km.
|
# Define a general distance object, initialized with a distance of k km.
|
||||||
d = geopy.distance.distance(kilometers=kilometers)
|
d = geopy.distance.distance(kilometers=kilometers)
|
||||||
@ -196,7 +203,7 @@ class Vehicle:
|
|||||||
informs the message broker about the current state (DAF) of the vehicle.
|
informs the message broker about the current state (DAF) of the vehicle.
|
||||||
"""
|
"""
|
||||||
print('{} starts driving ... SCALING: x{}\n\n'.format(self.vin, SCALING))
|
print('{} starts driving ... SCALING: x{}\n\n'.format(self.vin, SCALING))
|
||||||
self.last_update = datetime.now()
|
self.last_update = datetime.utcnow()
|
||||||
self._driven_kms = 0
|
self._driven_kms = 0
|
||||||
|
|
||||||
self._t = threading.Thread(target=self.drive)
|
self._t = threading.Thread(target=self.drive)
|
||||||
@ -223,14 +230,16 @@ class Vehicle:
|
|||||||
def check_reset(self):
|
def check_reset(self):
|
||||||
"""
|
"""
|
||||||
Checks if end of route is reached and resets vehicle to starting conditions.
|
Checks if end of route is reached and resets vehicle to starting conditions.
|
||||||
|
It also resets on malicious coordinates.
|
||||||
|
|
||||||
Afterwards, the vehicle is still driving, but again from start.
|
Afterwards, the vehicle is still driving, but again from start.
|
||||||
"""
|
"""
|
||||||
if self._driven_kms >= RESET_KM:
|
if self._driven_kms >= RESET_KM:
|
||||||
print('\n\nEnd of route reached ... resetting and restarting vehicle')
|
self._reset()
|
||||||
self._gps_location = self._starting_point
|
|
||||||
self._driven_kms = 0
|
if self._gps_location.latitude < self._starting_point.latitude or \
|
||||||
self.last_update = datetime.now()
|
self._gps_location.longitude < self._starting_point.longitude:
|
||||||
self.nce = False
|
self._reset()
|
||||||
|
|
||||||
@circuit(failure_threshold=10, expected_exception=AMQPConnectionError)
|
@circuit(failure_threshold=10, expected_exception=AMQPConnectionError)
|
||||||
def send_status_update(self):
|
def send_status_update(self):
|
||||||
@ -255,6 +264,14 @@ class Vehicle:
|
|||||||
else:
|
else:
|
||||||
print('We are still recovering ... ignoring new target velocity.')
|
print('We are still recovering ... ignoring new target velocity.')
|
||||||
|
|
||||||
|
def _reset(self):
|
||||||
|
print('\n\nEnd of route reached ... resetting and restarting vehicle')
|
||||||
|
self._gps_location = self._starting_point
|
||||||
|
self._driven_kms = 0
|
||||||
|
self.last_update = datetime.utcnow()
|
||||||
|
self.nce = False
|
||||||
|
self.velocity = STARTING_VELOCITY
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
...
|
...
|
||||||
|
|||||||
113
components/i_feed/test_ifeed.py
Normal file
113
components/i_feed/test_ifeed.py
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import datetime
|
||||||
|
import pickle
|
||||||
|
import time
|
||||||
|
import unittest
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
import geopy
|
||||||
|
from dse_shared_libs.daf import DAF
|
||||||
|
from dse_shared_libs.mock.datetime import MyDate
|
||||||
|
from dse_shared_libs.target_velocity import TargetVelocity
|
||||||
|
from dse_shared_libs.traffic_light_color import TrafficLightColor
|
||||||
|
|
||||||
|
from devices.traffic_light import TrafficLight
|
||||||
|
from devices.vehicle import Vehicle
|
||||||
|
from dse_shared_libs.mock.rabbit_mq_mocks import MyBlockingConnection
|
||||||
|
|
||||||
|
|
||||||
|
class TestVehicle(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
with patch('pika.BlockingConnection', MyBlockingConnection):
|
||||||
|
self.vin = 'my_vin'
|
||||||
|
self.starting_velocity = 130
|
||||||
|
self.starting_point = geopy.Point(0, 0, 0)
|
||||||
|
self.timestamp = datetime.datetime.utcnow()
|
||||||
|
|
||||||
|
self.v = Vehicle(
|
||||||
|
vin=self.vin,
|
||||||
|
starting_point=self.starting_point,
|
||||||
|
starting_velocity=self.starting_velocity
|
||||||
|
)
|
||||||
|
|
||||||
|
self.v.last_update = self.timestamp
|
||||||
|
self.v._driven_kms = 0
|
||||||
|
|
||||||
|
def tearDown(self) -> None:
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def test_nce_prop(self):
|
||||||
|
with patch('time.sleep', return_value=None):
|
||||||
|
# initially false
|
||||||
|
self.assertEqual(self.v.nce, False)
|
||||||
|
# get past nce km
|
||||||
|
self.v._gps_location.latitude = 48
|
||||||
|
# now nce should fire
|
||||||
|
self.assertEqual(self.v.nce, True)
|
||||||
|
# second call is false again
|
||||||
|
self.assertEqual(self.v.nce, False)
|
||||||
|
|
||||||
|
def test_daf_prop(self):
|
||||||
|
with patch('devices.vehicle.datetime', MyDate):
|
||||||
|
MyDate.set_timestamp(self.timestamp)
|
||||||
|
|
||||||
|
# test if daf object created properly
|
||||||
|
daf = DAF(vehicle_identification_number=self.vin,
|
||||||
|
gps_location=self.starting_point,
|
||||||
|
velocity=self.starting_velocity,
|
||||||
|
timestamp=self.timestamp,
|
||||||
|
near_crash_event=False)
|
||||||
|
self.assertEqual(self.v.daf, daf)
|
||||||
|
|
||||||
|
def test_current_location_prop(self):
|
||||||
|
with patch('devices.vehicle.datetime', MyDate):
|
||||||
|
MyDate.set_timestamp(self.timestamp)
|
||||||
|
|
||||||
|
# initial position should be starting point
|
||||||
|
self.assertEqual(self.v.gps_location, self.starting_point)
|
||||||
|
|
||||||
|
# lets say last time was about an hour ago
|
||||||
|
self.v.last_update = self.timestamp - datetime.timedelta(hours=1)
|
||||||
|
|
||||||
|
# we drive "almost" directly north
|
||||||
|
loc = self.v.gps_location
|
||||||
|
self.assertEqual(round(loc.latitude, 2), 1.17)
|
||||||
|
self.assertEqual(round(loc.longitude, 2), 0.04)
|
||||||
|
|
||||||
|
def test_driven_kms_prop(self):
|
||||||
|
# initial driven kms are 0
|
||||||
|
self.assertEqual(self.v.driven_kms, '0km')
|
||||||
|
|
||||||
|
# alter driven kms
|
||||||
|
self.v._driven_kms = 44.24552
|
||||||
|
# will be rounded to 2 digits
|
||||||
|
self.assertEqual(self.v.driven_kms, '44.25km')
|
||||||
|
|
||||||
|
def test_new_velocity(self):
|
||||||
|
# starting velocity is set to 130
|
||||||
|
self.assertEqual(self.v.velocity, 130)
|
||||||
|
|
||||||
|
# we get a new velocity, lets say 55 ...
|
||||||
|
tv = TargetVelocity(vin='my_vin', target_velocity=55, timestamp=self.timestamp)
|
||||||
|
self.v.new_velocity(pickle.dumps(tv))
|
||||||
|
# then the vehicle should comply with that
|
||||||
|
self.assertEqual(self.v.velocity, 55)
|
||||||
|
|
||||||
|
|
||||||
|
class TestTrafficLight(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
with patch('pika.BlockingConnection', MyBlockingConnection):
|
||||||
|
self.tl = TrafficLight(tlid='my_tl',
|
||||||
|
switching_time=1,
|
||||||
|
starting_color=TrafficLightColor.RED)
|
||||||
|
|
||||||
|
def tearDown(self) -> None:
|
||||||
|
self.tl.stop()
|
||||||
|
|
||||||
|
def test_switching(self):
|
||||||
|
self.assertFalse(hasattr(self.tl, 'current_color'))
|
||||||
|
self.tl.start()
|
||||||
|
self.assertEqual(self.tl.current_color, TrafficLightColor.RED)
|
||||||
|
time.sleep(1.2)
|
||||||
|
self.assertEqual(self.tl.current_color, TrafficLightColor.GREEN)
|
||||||
|
time.sleep(1)
|
||||||
|
self.assertEqual(self.tl.current_color, TrafficLightColor.RED)
|
||||||
@ -1,9 +1,10 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import pickle
|
import pickle
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from math import floor, ceil
|
from math import floor
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from dse_shared_libs import daf, traffic_light_state, traffic_light_color, target_velocity
|
from dse_shared_libs import daf, traffic_light_state, traffic_light_color, target_velocity
|
||||||
@ -22,7 +23,7 @@ sys.modules['target_velocity'] = target_velocity
|
|||||||
|
|
||||||
ENTITY_IDENT_URL = 'http://entityident:5002/api/v1/resources/'
|
ENTITY_IDENT_URL = 'http://entityident:5002/api/v1/resources/'
|
||||||
|
|
||||||
SCALING = 1
|
SCALING = int(os.environ.get('DSE2021_SCALING', 1))
|
||||||
|
|
||||||
|
|
||||||
class Orchestrator:
|
class Orchestrator:
|
||||||
@ -60,7 +61,7 @@ class Orchestrator:
|
|||||||
for traffic_light in traffic_lights['cursor']:
|
for traffic_light in traffic_lights['cursor']:
|
||||||
self.tls[traffic_light['id']] = {'color': traffic_light['color'],
|
self.tls[traffic_light['id']] = {'color': traffic_light['color'],
|
||||||
'switching_time': traffic_light['switchingTime'],
|
'switching_time': traffic_light['switchingTime'],
|
||||||
'last_switch': datetime.now()}
|
'last_switch': datetime.utcnow()}
|
||||||
|
|
||||||
def setup_msg_queues(self):
|
def setup_msg_queues(self):
|
||||||
"""
|
"""
|
||||||
@ -88,7 +89,7 @@ class Orchestrator:
|
|||||||
"""
|
"""
|
||||||
Gets the daf object's pickle binary dump.
|
Gets the daf object's pickle binary dump.
|
||||||
Unpickle, calculate new target velocity based on daf and current tl data and
|
Unpickle, calculate new target velocity based on daf and current tl data and
|
||||||
respond new target velicity for this vehicle.
|
respond new target velocity for this vehicle.
|
||||||
|
|
||||||
:param pickle_binary: daf object pickle binary dump
|
:param pickle_binary: daf object pickle binary dump
|
||||||
"""
|
"""
|
||||||
@ -100,55 +101,14 @@ class Orchestrator:
|
|||||||
params={'lat': loc.latitude, 'lon': loc.longitude})
|
params={'lat': loc.latitude, 'lon': loc.longitude})
|
||||||
traffic_lights_geo = response.json()
|
traffic_lights_geo = response.json()
|
||||||
current_vel = received_daf_object.velocity
|
current_vel = received_daf_object.velocity
|
||||||
target_vel = 130 * SCALING
|
|
||||||
print('Nearest traffic lights: {}'.format(traffic_lights_geo['cursor']))
|
target_vel = self._compute_velocity(traffic_lights_geo, current_vel)
|
||||||
for traffic_light in traffic_lights_geo['cursor']:
|
|
||||||
# Should only ever contain one traffic light (the next in line)
|
|
||||||
tl_id = traffic_light['id']
|
|
||||||
distance = traffic_light['calculatedRange']
|
|
||||||
switching_time = self.tls[tl_id]['switching_time'] / float(SCALING)
|
|
||||||
# Time until next switch must be scaled accordingly
|
|
||||||
next_switch_time = self.tls[tl_id]['last_switch'] + timedelta(seconds=switching_time)
|
|
||||||
time_until_switch = (next_switch_time - datetime.now()).total_seconds()
|
|
||||||
print('Distance to TL: {}'.format(distance))
|
|
||||||
print('Time until switch in seconds: {}'.format(time_until_switch))
|
|
||||||
if self.tls[tl_id]['color'] is TrafficLightColor.RED:
|
|
||||||
speed_needed_max = (distance / float(time_until_switch)) * 3.6
|
|
||||||
if speed_needed_max < 130 * SCALING:
|
|
||||||
if current_vel < speed_needed_max:
|
|
||||||
target_vel = current_vel
|
|
||||||
else:
|
|
||||||
target_vel = floor(speed_needed_max)
|
|
||||||
else:
|
|
||||||
# Cannot make it on next green
|
|
||||||
i = 2
|
|
||||||
while speed_needed_max > 130 * SCALING:
|
|
||||||
next_green_phase_start = time_until_switch + switching_time * i
|
|
||||||
speed_needed_max = (distance / float(next_green_phase_start)) * 3.6
|
|
||||||
i = i + 2
|
|
||||||
target_vel = floor(speed_needed_max)
|
|
||||||
else:
|
|
||||||
# Check if we can reach TL in time
|
|
||||||
speed_needed_min = (distance / float(time_until_switch)) * 3.6
|
|
||||||
if speed_needed_min < 130 * SCALING:
|
|
||||||
if current_vel < speed_needed_min:
|
|
||||||
target_vel = 130 * SCALING
|
|
||||||
else:
|
|
||||||
target_vel = current_vel
|
|
||||||
else:
|
|
||||||
i = 1
|
|
||||||
speed_needed_max = 132 * SCALING
|
|
||||||
while speed_needed_max > 130 * SCALING:
|
|
||||||
next_green_phase_start = time_until_switch + switching_time * i
|
|
||||||
speed_needed_max = (distance / float(next_green_phase_start)) * 3.6
|
|
||||||
i = i + 2
|
|
||||||
target_vel = floor(speed_needed_max)
|
|
||||||
|
|
||||||
response_channel = self._velocity_mbs[received_daf_object.vehicle_identification_number]
|
response_channel = self._velocity_mbs[received_daf_object.vehicle_identification_number]
|
||||||
print('Target velocity: {}'.format(target_vel))
|
print('Target velocity: {}'.format(target_vel))
|
||||||
response_channel.send(pickle.dumps(
|
response_channel.send(pickle.dumps(
|
||||||
TargetVelocity(vin=received_daf_object.vehicle_identification_number, target_velocity=target_vel,
|
TargetVelocity(vin=received_daf_object.vehicle_identification_number, target_velocity=target_vel,
|
||||||
timestamp=datetime.now())))
|
timestamp=datetime.utcnow())))
|
||||||
|
|
||||||
def handle_tl_state_receive(self, msg):
|
def handle_tl_state_receive(self, msg):
|
||||||
"""
|
"""
|
||||||
@ -164,3 +124,55 @@ class Orchestrator:
|
|||||||
self.tls[tl_state.tlid]['color'] = tl_state.color
|
self.tls[tl_state.tlid]['color'] = tl_state.color
|
||||||
self.tls[tl_state.tlid]['last_switch'] = tl_state.last_switch
|
self.tls[tl_state.tlid]['last_switch'] = tl_state.last_switch
|
||||||
print(tl_state)
|
print(tl_state)
|
||||||
|
|
||||||
|
def _compute_velocity(self, traffic_lights_geo, current_vel):
|
||||||
|
target_vel = 130 * SCALING
|
||||||
|
|
||||||
|
print('Nearest traffic lights: {}'.format(traffic_lights_geo['cursor']))
|
||||||
|
for traffic_light in traffic_lights_geo['cursor']:
|
||||||
|
# Should only ever contain one traffic light (the next in line)
|
||||||
|
tl_id = traffic_light['id']
|
||||||
|
distance = traffic_light['calculatedRange']
|
||||||
|
switching_time = self.tls[tl_id]['switching_time'] / float(SCALING)
|
||||||
|
# Time until next switch must be scaled accordingly
|
||||||
|
next_switch_time = self.tls[tl_id]['last_switch'] + timedelta(seconds=switching_time)
|
||||||
|
time_until_switch = (next_switch_time - datetime.utcnow()).total_seconds()
|
||||||
|
print('Distance to TL: {}'.format(distance))
|
||||||
|
print('Time until switch in seconds: {}'.format(time_until_switch))
|
||||||
|
|
||||||
|
if self.tls[tl_id]['color'] is TrafficLightColor.RED:
|
||||||
|
speed_needed_max = (distance / float(time_until_switch)) * 3.6
|
||||||
|
if speed_needed_max < 130 * SCALING:
|
||||||
|
if current_vel < speed_needed_max:
|
||||||
|
target_vel = current_vel
|
||||||
|
else:
|
||||||
|
target_vel = floor(speed_needed_max)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Cannot make it on next green
|
||||||
|
i = 2
|
||||||
|
while speed_needed_max > 130 * SCALING:
|
||||||
|
next_green_phase_start = time_until_switch + switching_time * i
|
||||||
|
speed_needed_max = (distance / float(next_green_phase_start)) * 3.6
|
||||||
|
i = i + 2
|
||||||
|
target_vel = floor(speed_needed_max)
|
||||||
|
|
||||||
|
elif self.tls[tl_id]['color'] is TrafficLightColor.GREEN:
|
||||||
|
# Check if we can reach TL in time
|
||||||
|
speed_needed_min = (distance / float(time_until_switch)) * 3.6
|
||||||
|
if speed_needed_min < 130 * SCALING:
|
||||||
|
if current_vel < speed_needed_min:
|
||||||
|
target_vel = 130 * SCALING
|
||||||
|
else:
|
||||||
|
target_vel = current_vel
|
||||||
|
else:
|
||||||
|
i = 1
|
||||||
|
speed_needed_max = 132 * SCALING
|
||||||
|
while speed_needed_max > 130 * SCALING:
|
||||||
|
next_green_phase_start = time_until_switch + switching_time * i
|
||||||
|
speed_needed_max = (distance / float(next_green_phase_start)) * 3.6
|
||||||
|
i = i + 2
|
||||||
|
target_vel = floor(speed_needed_max)
|
||||||
|
else:
|
||||||
|
print('Unknown Traffic Light Color!')
|
||||||
|
return target_vel
|
||||||
|
|||||||
54
components/orchestration/test_orchestrator.py
Normal file
54
components/orchestration/test_orchestrator.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import datetime
|
||||||
|
import unittest
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from dse_shared_libs.mock.response import MyResponse
|
||||||
|
from dse_shared_libs.traffic_light_color import TrafficLightColor
|
||||||
|
|
||||||
|
from orchestrator import Orchestrator
|
||||||
|
|
||||||
|
|
||||||
|
class TestOrchestrator(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
self.timestamp = datetime.datetime.utcnow()
|
||||||
|
with patch('requests.sessions.Session.get', MyResponse):
|
||||||
|
self.orc = Orchestrator()
|
||||||
|
|
||||||
|
def test_full_speed_if_nothing_in_range(self):
|
||||||
|
tl_geo = {'cursor': []}
|
||||||
|
current_vel = 55.0
|
||||||
|
|
||||||
|
target_vel = self.orc._compute_velocity(tl_geo, current_vel)
|
||||||
|
self.assertEqual(130, target_vel)
|
||||||
|
|
||||||
|
def test_keep_speed_if_far_away_and_green(self):
|
||||||
|
self.orc.tls = {'1': {'color': TrafficLightColor.GREEN, 'switching_time': 1000, 'last_switch': self.timestamp}}
|
||||||
|
tl_geo = {'cursor': [
|
||||||
|
{'id': '1', 'calculatedRange': 1000}
|
||||||
|
]}
|
||||||
|
current_vel = 55.0
|
||||||
|
|
||||||
|
target_vel = self.orc._compute_velocity(tl_geo, current_vel)
|
||||||
|
self.assertEqual(current_vel, target_vel)
|
||||||
|
|
||||||
|
def test_slow_down_if_passing_RED_not_possible(self):
|
||||||
|
self.orc.tls = {'1': {'color': TrafficLightColor.RED, 'switching_time': 100000, 'last_switch': self.timestamp}}
|
||||||
|
tl_geo = {'cursor': [
|
||||||
|
{'id': '1', 'calculatedRange': 1}
|
||||||
|
]}
|
||||||
|
current_vel = 130.0
|
||||||
|
|
||||||
|
target_vel = self.orc._compute_velocity(tl_geo, current_vel)
|
||||||
|
self.assertNotEqual(current_vel, target_vel)
|
||||||
|
self.assertEqual(0, target_vel)
|
||||||
|
|
||||||
|
def test_adjust_speed_to_get_over_on_green_if_currently_red(self):
|
||||||
|
self.orc.tls = {'1': {'color': TrafficLightColor.RED, 'switching_time': 100, 'last_switch': self.timestamp}}
|
||||||
|
tl_geo = {'cursor': [
|
||||||
|
{'id': '1', 'calculatedRange': 1000}
|
||||||
|
]}
|
||||||
|
current_vel = 130.0
|
||||||
|
|
||||||
|
target_vel = self.orc._compute_velocity(tl_geo, current_vel)
|
||||||
|
self.assertNotEqual(current_vel, target_vel)
|
||||||
|
self.assertEqual(36.0, target_vel)
|
||||||
0
components/shared/dse_shared_libs/mock/__init__.py
Normal file
0
components/shared/dse_shared_libs/mock/__init__.py
Normal file
10
components/shared/dse_shared_libs/mock/datetime.py
Normal file
10
components/shared/dse_shared_libs/mock/datetime.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
class MyDate:
|
||||||
|
timestamp = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_timestamp(cls, timestamp):
|
||||||
|
cls.timestamp = timestamp
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def utcnow(cls):
|
||||||
|
return cls.timestamp
|
||||||
43
components/shared/dse_shared_libs/mock/rabbit_mq_mocks.py
Normal file
43
components/shared/dse_shared_libs/mock/rabbit_mq_mocks.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
class MyQueue:
|
||||||
|
@property
|
||||||
|
def queue(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class MyMethod:
|
||||||
|
method = MyQueue()
|
||||||
|
|
||||||
|
|
||||||
|
class MyChannel:
|
||||||
|
@staticmethod
|
||||||
|
def exchange_declare(*args, **kwargs):
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def queue_declare(*args, **kwargs):
|
||||||
|
return MyMethod
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def queue_bind(*args, **kwargs):
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def basic_consume(*args, **kwargs):
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def basic_publish(*args, **kwargs):
|
||||||
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def start_consuming(*args, **kwargs):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class MyBlockingConnection:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
...
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def channel():
|
||||||
|
return MyChannel()
|
||||||
7
components/shared/dse_shared_libs/mock/response.py
Normal file
7
components/shared/dse_shared_libs/mock/response.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
class MyResponse:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
...
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def json(*args, **kwargs):
|
||||||
|
return {'cursor': []}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
flask
|
flask==1.1.4
|
||||||
Flask-Cors
|
Flask-Cors
|
||||||
requests
|
requests
|
||||||
Flask-PyMongo
|
Flask-PyMongo
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from bson import json_util
|
|||||||
from flask import Flask, jsonify
|
from flask import Flask, jsonify
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
from flask import request
|
from flask import request
|
||||||
import json;
|
import json
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
CORS(app)
|
CORS(app)
|
||||||
|
|||||||
@ -1,6 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: scaling-configmap
|
|
||||||
data:
|
|
||||||
scaling: "1"
|
|
||||||
19
kubernetes/configmaps/simulation-parameters-configmap.yaml
Normal file
19
kubernetes/configmaps/simulation-parameters-configmap.yaml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
data:
|
||||||
|
DSE2021_SCALING: "2"
|
||||||
|
DSE2021_NCE: "1"
|
||||||
|
DSE2021_CAR1_SV: "130"
|
||||||
|
DSE2021_CAR2_SV: "130"
|
||||||
|
DSE2021_CAR3_SV: "130"
|
||||||
|
DSE2021_CAR1_SD: "300"
|
||||||
|
DSE2021_CAR2_SD: "500"
|
||||||
|
DSE2021_CAR3_SD: "400"
|
||||||
|
DSE2021_CAR1_ST: "10"
|
||||||
|
DSE2021_CAR2_ST: "15"
|
||||||
|
DSE2021_CAR3_ST: "25"
|
||||||
|
DSE2021_TL1_R: "2000"
|
||||||
|
DSE2021_TL2_R: "800"
|
||||||
|
DSE2021_TL3_R: "1000"
|
||||||
@ -23,11 +23,11 @@ spec:
|
|||||||
- containerPort: 80
|
- containerPort: 80
|
||||||
resources: {}
|
resources: {}
|
||||||
env:
|
env:
|
||||||
- name: SCALING
|
- name: DSE2021_SCALING
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
name: scaling-configmap
|
name: simulation-parameters-configmap
|
||||||
key: scaling
|
key: DSE2021_SCALING
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
serviceAccountName: ""
|
serviceAccountName: ""
|
||||||
volumes: null
|
volumes: null
|
||||||
|
|||||||
@ -23,11 +23,71 @@ spec:
|
|||||||
- containerPort: 5002
|
- containerPort: 5002
|
||||||
resources: {}
|
resources: {}
|
||||||
env:
|
env:
|
||||||
- name: SCALING
|
- name: DSE2021_SCALING
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
name: scaling-configmap
|
name: simulation-parameters-configmap
|
||||||
key: scaling
|
key: DSE2021_SCALING
|
||||||
|
- name: DSE2021_CAR1_SV
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR1_SV
|
||||||
|
- name: DSE2021_CAR2_SV
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR2_SV
|
||||||
|
- name: DSE2021_CAR3_SV
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR3_SV
|
||||||
|
- name: DSE2021_CAR1_SD
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR1_SD
|
||||||
|
- name: DSE2021_CAR2_SD
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR2_SD
|
||||||
|
- name: DSE2021_CAR3_SD
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR3_SD
|
||||||
|
- name: DSE2021_CAR1_ST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR1_ST
|
||||||
|
- name: DSE2021_CAR2_ST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR2_ST
|
||||||
|
- name: DSE2021_CAR3_ST
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_CAR3_ST
|
||||||
|
- name: DSE2021_TL1_R
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_TL1_R
|
||||||
|
- name: DSE2021_TL2_R
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_TL2_R
|
||||||
|
- name: DSE2021_TL3_R
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_TL3_R
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
serviceAccountName: ""
|
serviceAccountName: ""
|
||||||
volumes: null
|
volumes: null
|
||||||
|
|||||||
@ -23,11 +23,11 @@ spec:
|
|||||||
- containerPort: 5001
|
- containerPort: 5001
|
||||||
resources: {}
|
resources: {}
|
||||||
env:
|
env:
|
||||||
- name: SCALING
|
- name: DSE2021_SCALING
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
name: scaling-configmap
|
name: simulation-parameters-configmap
|
||||||
key: scaling
|
key: DSE2021_SCALING
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
serviceAccountName: ""
|
serviceAccountName: ""
|
||||||
volumes: null
|
volumes: null
|
||||||
|
|||||||
@ -21,11 +21,16 @@ spec:
|
|||||||
name: ifeed
|
name: ifeed
|
||||||
resources: {}
|
resources: {}
|
||||||
env:
|
env:
|
||||||
- name: SCALING
|
- name: DSE2021_SCALING
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
name: scaling-configmap
|
name: simulation-parameters-configmap
|
||||||
key: scaling
|
key: DSE2021_SCALING
|
||||||
|
- name: DSE2021_NCE
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: simulation-parameters-configmap
|
||||||
|
key: DSE2021_NCE
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
serviceAccountName: ""
|
serviceAccountName: ""
|
||||||
volumes: null
|
volumes: null
|
||||||
|
|||||||
@ -21,11 +21,11 @@ spec:
|
|||||||
name: orchestration
|
name: orchestration
|
||||||
resources: {}
|
resources: {}
|
||||||
env:
|
env:
|
||||||
- name: SCALING
|
- name: DSE2021_SCALING
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
name: scaling-configmap
|
name: simulation-parameters-configmap
|
||||||
key: scaling
|
key: DSE2021_SCALING
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
serviceAccountName: ""
|
serviceAccountName: ""
|
||||||
volumes: null
|
volumes: null
|
||||||
|
|||||||
@ -23,11 +23,11 @@ spec:
|
|||||||
- containerPort: 5004
|
- containerPort: 5004
|
||||||
resources: {}
|
resources: {}
|
||||||
env:
|
env:
|
||||||
- name: SCALING
|
- name: DSE2021_SCALING
|
||||||
valueFrom:
|
valueFrom:
|
||||||
configMapKeyRef:
|
configMapKeyRef:
|
||||||
name: scaling-configmap
|
name: simulation-parameters-configmap
|
||||||
key: scaling
|
key: DSE2021_SCALING
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
serviceAccountName: ""
|
serviceAccountName: ""
|
||||||
volumes: null
|
volumes: null
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 125 KiB |
Loading…
x
Reference in New Issue
Block a user