vehicle sends daf to orchestrator via rabbitMQ broker
vehicle receives new target velocity from orchestrator as response; at this point, this velocity is just a random float between 0 and 130;
This commit is contained in:
@@ -1,16 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
import geopy.distance
|
||||
|
||||
|
||||
@dataclass
|
||||
class DAF:
|
||||
"""
|
||||
"Datenaufzeichnung für automatisiertes Fahren" (DAF), see 2021_DSE_Exercise_V1.0_Final.pdf page 7
|
||||
"""
|
||||
|
||||
vehicle_identification_number: str
|
||||
gps_location: geopy.Point
|
||||
velocity: float
|
||||
near_crash_event: bool
|
||||
timestamp: datetime
|
||||
@@ -1,71 +0,0 @@
|
||||
import time
|
||||
from threading import Thread
|
||||
|
||||
import pika
|
||||
|
||||
|
||||
class MBWrapper:
|
||||
host: str
|
||||
exchange_type: str
|
||||
exchange_name: str
|
||||
callback: callable
|
||||
|
||||
_type: str
|
||||
_connection: pika.BlockingConnection
|
||||
_channel: pika.BlockingConnection.channel
|
||||
|
||||
def __init__(self,
|
||||
host: str = 'localhost',
|
||||
exchange_type: str = 'fanout',
|
||||
exchange_name: str = None,
|
||||
callback: callable = None):
|
||||
assert exchange_name, 'Please define an exchange name'
|
||||
|
||||
self.host = host
|
||||
self.exchange_type = exchange_type
|
||||
self.exchange_name = exchange_name
|
||||
self.callback = callback
|
||||
|
||||
def setup_sender(self):
|
||||
assert self._type != 'receiver', 'MBWrapper is already a receiver. Use another MBWrapper.'
|
||||
self._type = 'sender'
|
||||
self._setup_channel()
|
||||
|
||||
def setup_receiver(self):
|
||||
assert self._type != 'sender', 'MBWrapper is already a sender. Use another MBWrapper.'
|
||||
assert callback, 'Please setup MBWrapper with "on response" self.callback which can handle a byte string as input.'
|
||||
|
||||
def consumer():
|
||||
self._setup_channel()
|
||||
result = self._channel.queue_declare(queue='', exclusive=True)
|
||||
queue_name = result.method.queue
|
||||
|
||||
self._channel.queue_bind(exchange=self.exchange_name, queue=queue_name)
|
||||
|
||||
print(' [*] Waiting for messages. To exit press CTRL+C')
|
||||
|
||||
self._channel.basic_consume(
|
||||
queue=queue_name, on_message_callback=self._receive, auto_ack=True)
|
||||
|
||||
self._channel.start_consuming()
|
||||
|
||||
Thread(target=consumer).start()
|
||||
|
||||
def send(self, message: bytes = b"info: Hello World!"):
|
||||
if type(message) is not bytes:
|
||||
message = str(message).encode()
|
||||
self._channel.basic_publish(exchange=self.exchange_name, routing_key='', body=message)
|
||||
print(" [x] Sent %r" % message)
|
||||
|
||||
def close(self):
|
||||
self._connection.close()
|
||||
|
||||
def _setup_channel(self):
|
||||
self._connection = pika.BlockingConnection(
|
||||
pika.ConnectionParameters(host=self.host))
|
||||
self._channel = self._connection.channel()
|
||||
|
||||
self._channel.exchange_declare(exchange=self.exchange_name, exchange_type=self.exchange_type)
|
||||
|
||||
def _receive(self, ch, method, properties, body):
|
||||
self.callback(body)
|
||||
@@ -1,2 +1,3 @@
|
||||
circuitbreaker # fault tolerance
|
||||
geopy
|
||||
pika
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import pickle
|
||||
import threading
|
||||
import time
|
||||
from datetime import datetime
|
||||
@@ -6,7 +7,9 @@ from typing import Union
|
||||
import geopy
|
||||
import geopy.distance
|
||||
from circuitbreaker import circuit
|
||||
from daf import DAF
|
||||
from wrappers.daf import DAF
|
||||
|
||||
from wrappers.message_broker_wrapper import MBWrapper
|
||||
|
||||
# Lat, Long
|
||||
STARTING_POINT = geopy.Point(48.853, 2.349)
|
||||
@@ -17,7 +20,7 @@ BEARING = 0
|
||||
# Scale speed of vehicles by factor x
|
||||
SCALING = 100
|
||||
# Interval between status updates in seconds (is not scaled)
|
||||
UPDATE_INTERVAL = 1
|
||||
UPDATE_INTERVAL = 2
|
||||
# At x km the NCE shall happen
|
||||
NCE_KM = 30
|
||||
# Time in seconds to recover from NCE (will be scaled)
|
||||
@@ -47,11 +50,17 @@ class Vehicle:
|
||||
_nce_possible = True
|
||||
# stores if nce already happened, it only happens (up to) once
|
||||
_nce_happened = False
|
||||
|
||||
# continuous driving thread
|
||||
_t: threading.Thread
|
||||
# NCE recovery thread
|
||||
_rt: threading.Thread
|
||||
|
||||
# outgoing daf info MBWrapper
|
||||
_daf_mb: MBWrapper
|
||||
# incoming target velocity MBWrapper
|
||||
_velocity_mb: MBWrapper
|
||||
|
||||
def __init__(self,
|
||||
vin: str,
|
||||
starting_point: geopy.Point = STARTING_POINT,
|
||||
@@ -61,6 +70,12 @@ class Vehicle:
|
||||
self._gps_location = starting_point
|
||||
self.velocity = starting_velocity
|
||||
|
||||
self._daf_mb = MBWrapper(exchange_name='vehicle_daf_{}'.format(vin))
|
||||
self._daf_mb.setup_sender()
|
||||
|
||||
self._velocity_mb = MBWrapper(exchange_name='vehicle_velocity_{}'.format(self.vin), callback=self.new_velocity)
|
||||
self._velocity_mb.setup_receiver()
|
||||
|
||||
@property
|
||||
def nce(self):
|
||||
"""
|
||||
@@ -148,7 +163,7 @@ class Vehicle:
|
||||
Starts a thread responsible for driving. This thread continuously updates internal values and
|
||||
informs the message broker about the current state (DAF) of the vehicle.
|
||||
"""
|
||||
print('Start driving ... SCALING: x{}\n\n'.format(SCALING))
|
||||
print('{} starts driving ... SCALING: x{}\n\n'.format(self.vin, SCALING))
|
||||
self.last_update = datetime.now()
|
||||
self._driven_kms = 0
|
||||
|
||||
@@ -187,15 +202,20 @@ class Vehicle:
|
||||
|
||||
@circuit(failure_threshold=10, expected_exception=ConnectionError)
|
||||
def send_status_update(self):
|
||||
# TODO inform the message broker about the current status
|
||||
print(self.driven_kms, '\t', self.daf)
|
||||
self._daf_mb.send(pickle.dumps(self.daf))
|
||||
|
||||
# TODO adapt the vehicle's velocity to the suggestion of the orchestration service
|
||||
def new_velocity(self):
|
||||
...
|
||||
def new_velocity(self, velocity: bytes):
|
||||
velocity = float(velocity)
|
||||
print('Received new velocity {}'.format(velocity))
|
||||
self.velocity = velocity
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
v1 = Vehicle(vin='SB164ABN1PE082986')
|
||||
v1 = Vehicle(vin='SB164ABN1PE082000')
|
||||
v1.start_driving()
|
||||
|
||||
time.sleep(1)
|
||||
v2 = Vehicle(vin='SB999ABN1PE082111')
|
||||
v2.start_driving()
|
||||
# stop manually
|
||||
|
||||
Reference in New Issue
Block a user