From 67331d506e8ca6e1c843fd8364c6aea141d2a5a7 Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Thu, 16 Nov 2023 17:16:21 +0100 Subject: [PATCH 01/20] Added HTTP Server --- app/HTTPServer/endpoints.py | 60 ++++++++++++++++++++++ app/HTTPServer/helpers/__pycache__/main.py | 23 +++++++++ app/HTTPServer/main.py | 44 ++++++++++++++++ app/HTTPServer/monitor_data.json | 7 +++ app/HTTPServer/readme.md | 5 ++ 5 files changed, 139 insertions(+) create mode 100644 app/HTTPServer/endpoints.py create mode 100644 app/HTTPServer/helpers/__pycache__/main.py create mode 100644 app/HTTPServer/main.py create mode 100644 app/HTTPServer/monitor_data.json create mode 100644 app/HTTPServer/readme.md diff --git a/app/HTTPServer/endpoints.py b/app/HTTPServer/endpoints.py new file mode 100644 index 0000000..c032f85 --- /dev/null +++ b/app/HTTPServer/endpoints.py @@ -0,0 +1,60 @@ +from flask import Flask, jsonify, request +import json + + +def get_monitor(): + file_path = "./monitor_data.json" + + try: + with open(file_path, 'r') as json_file: + data = json.load(json_file) + return data + + except FileNotFoundError: + raise FileNotFoundError("Monitor data not found") + + except Exception as e: + raise e + + +# Construct the path to the knobs.json file, assuming it's two directories back +json_file_path = '../../knobs.json' + +# Open the JSON file in read mode ('r') +with open(json_file_path, 'r') as json_file: + # Use json.load() to read data from the file + adaptation_options_data = json.load(json_file) + + # Now 'data' contains the contents of the JSON file as a Python dictionary + print(adaptation_options_data) + + + + +def getexecute(): + try: + # Get the JSON data from the request body + request_data = request.get_json() + + # Check if the required adaptation fields are present in the request data + required_fields = ["routeRandomSigma", "explorationPercentage", "maxSpeedAndLengthFactor", + "averageEdgeDurationFactor", "freshnessUpdateFactor", "freshnessCutOffValue", + "reRouteEveryTicks"] + if not all(field in request_data for field in required_fields): + return jsonify({"error": "Missing required fields in the adaptation request"}), 400 + + # Implement your adaptation logic here based on the received data + # For demonstration, we'll print the received data + print('Received adaptation data: {request_data}') + + # Return a response indicating the success of the adaptation + return jsonify({"message": "Adaptation executed successfully"}) + + except Exception as e: + # Handle exceptions and return an error response + return jsonify({"error": str(e)}), 500 + +def getAdaptationOptions(): + return adaptation_options_data + + diff --git a/app/HTTPServer/helpers/__pycache__/main.py b/app/HTTPServer/helpers/__pycache__/main.py new file mode 100644 index 0000000..b54e674 --- /dev/null +++ b/app/HTTPServer/helpers/__pycache__/main.py @@ -0,0 +1,23 @@ +from flask import jsonify + +def getMonitor(): + # Specify the file path + file_path = "./monitor_data.json" + + try: + # Open the file in read mode ('r') + with open(file_path, 'r') as json_file: + # Use json.load() to read data from the file + data = json.load(json_file) + + # Now 'data' contains the contents of the JSON file as a Python dictionary + return jsonify(data) + + except FileNotFoundError: + # Return a 404 Not Found response if the file is not found + return jsonify({"error": "Monitor data not found"}), 404 + + except Exception as e: + # Handle other exceptions and return a 500 Internal Server Error response + return jsonify({"error": str(e)}), 500 + diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py new file mode 100644 index 0000000..2545698 --- /dev/null +++ b/app/HTTPServer/main.py @@ -0,0 +1,44 @@ +from flask import Flask , jsonify +from endpoints import get_monitor , getAdaptationOptions , getexecute + +app = Flask(__name__) + +@app.route('/monitor', methods=['GET']) +def monitor(): + try: + data = get_monitor() + return jsonify(data) + + except FileNotFoundError: + return jsonify({"error": "Monitor data not found"}), 404 + + except Exception as e: + return jsonify({"error": str(e)}), 500 + +@app.route('/execute', methods=['PUT']) +def execute_adaptation(): + data = getexecute() + return jsonify(data) + + +@app.route('/adaptation_options', methods=['GET']) +def get_adaptation_options(): + data= getAdaptationOptions() + return jsonify(data) + +@app.route('/monitor_schema', methods=['GET']) +def get_monitor_schema(): + field_types = {key: type(value).__name__ for key, value in get_monitor().items()} + return field_types + +@app.route('/execute_schema', methods=['GET']) +def get_execute_schema(): + return jsonify({"execute_schema": "This is /execute_schema endpoint"}) + +@app.route('/adaptation_options_schema', methods=['GET']) +def get_adaptation_options_schema(): + return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) + +if __name__ == '__main__': + app.run(debug=True) + diff --git a/app/HTTPServer/monitor_data.json b/app/HTTPServer/monitor_data.json new file mode 100644 index 0000000..1439b13 --- /dev/null +++ b/app/HTTPServer/monitor_data.json @@ -0,0 +1,7 @@ +{ + "totalCarCounter":2, + "carIndexCounter": 1, + "totalTrips": 1, + "totalTripAverage": 4, + "totalTripOverheadAverage": 44 +} \ No newline at end of file diff --git a/app/HTTPServer/readme.md b/app/HTTPServer/readme.md new file mode 100644 index 0000000..76e4977 --- /dev/null +++ b/app/HTTPServer/readme.md @@ -0,0 +1,5 @@ +In order to run the HTTP server: + +pip install fastapi +pip install "uvicorn[standard]" +python -m uvicorn main:app --reload \ No newline at end of file From afd2aedd8d37301a8637f6bbe0c3a2c7dd926dec Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Fri, 17 Nov 2023 01:22:42 +0100 Subject: [PATCH 02/20] Made changes to endpoints.py and main.py --- app/HTTPServer/endpoints.py | 21 +++++++++------------ app/HTTPServer/main.py | 16 +++++++++------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/app/HTTPServer/endpoints.py b/app/HTTPServer/endpoints.py index c032f85..f3bebbd 100644 --- a/app/HTTPServer/endpoints.py +++ b/app/HTTPServer/endpoints.py @@ -1,20 +1,16 @@ from flask import Flask, jsonify, request -import json +import json +from app.simulation.Simulation import Simulation -def get_monitor(): - file_path = "./monitor_data.json" - try: - with open(file_path, 'r') as json_file: - data = json.load(json_file) - return data +@app.route('/monitor', methods=['GET']) +def monitor(): + # Retrieve real-time data from the simulation + real_time_data = Simulation.get_real_time_data() - except FileNotFoundError: - raise FileNotFoundError("Monitor data not found") - - except Exception as e: - raise e + # Return the real-time data as JSON + return jsonify(real_time_data) # Construct the path to the knobs.json file, assuming it's two directories back @@ -58,3 +54,4 @@ def getAdaptationOptions(): return adaptation_options_data + diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index 2545698..ec2bca7 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -1,19 +1,20 @@ from flask import Flask , jsonify +from app.simulation.Simulation import Simulation from endpoints import get_monitor , getAdaptationOptions , getexecute app = Flask(__name__) @app.route('/monitor', methods=['GET']) def monitor(): - try: - data = get_monitor() - return jsonify(data) + Simulation.start() - except FileNotFoundError: - return jsonify({"error": "Monitor data not found"}), 404 +while True: + # Retrieve real-time data from the simulation + real_time_data = Simulation.get_real_time_data() + print("Real-time data from simulation:", real_time_data) + + time.sleep(5) # Adjust the sleep duration based on your requirements - except Exception as e: - return jsonify({"error": str(e)}), 500 @app.route('/execute', methods=['PUT']) def execute_adaptation(): @@ -42,3 +43,4 @@ def get_adaptation_options_schema(): if __name__ == '__main__': app.run(debug=True) + From 28408d28ba82218497110f68793fc91c4127f051 Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Fri, 17 Nov 2023 18:01:05 +0100 Subject: [PATCH 03/20] Made changes to HTTPServer, and Dockerfile --- Dockerfile | 49 ++++++++++++++++++++++++------------- app/HTTPServer/endpoints.py | 29 +++++++++++++--------- app/HTTPServer/main.py | 26 ++++++++++++-------- 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/Dockerfile b/Dockerfile index c16308e..476fe77 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,23 +1,38 @@ -FROM python:2.7 +FROM starofall/crowdnav +ADD /app/HTTPServer /app/HTTPServer +COPY knobs.json knobs.json -RUN apt-get update && \ - apt-get install -y \ - build-essential \ - git \ - libxerces-c-dev +COPY /app/simulation /app/simulation -RUN mkdir -p /opt -RUN (cd /opt; git clone https://github.com/radiganm/sumo.git) -RUN (cd /opt/sumo; ./configure) -RUN (cd /opt/sumo; make) -RUN (cd /opt/sumo; make install) +WORKDIR /../app +RUN python run.py -ENV SUMO_HOME /opt/sumo +WORKDIR /app/HTTPServer +RUN pip install flask + +CMD [ "python" , "/app/HTTPServer/main.py" ] + + + + +# RUN apt-get update && \ +# apt-get install -y \ + # build-essential \ + # git \ + # libxerces-c-dev + +#RUN mkdir -p /opt +#RUN (cd /opt; git clone https://github.com/radiganm/sumo.git) +#RUN (cd /opt/sumo; ./configure) +#RUN (cd /opt/sumo; make) +#RUN (cd /opt/sumo; make install) + +#ENV SUMO_HOME /opt/sumo # First cache dependencies -ADD ./setup.py /app/setup.py -RUN python /app/setup.py install +#ADD ./setup.py /app/setup.py +#RUN python /app/setup.py install # Add sources -ADD ./ /app/ -WORKDIR /app -CMD ["python","/app/forever.py"] +#ADD ./ /app/ +#WORKDIR /app +#CMD ["python","/app/forever.py"] diff --git a/app/HTTPServer/endpoints.py b/app/HTTPServer/endpoints.py index f3bebbd..ccb2be6 100644 --- a/app/HTTPServer/endpoints.py +++ b/app/HTTPServer/endpoints.py @@ -1,17 +1,25 @@ from flask import Flask, jsonify, request -import json +import json -from app.simulation.Simulation import Simulation +import sys +import sys +import os +# Get the path to the parent directory of the package +package_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) -@app.route('/monitor', methods=['GET']) -def monitor(): - # Retrieve real-time data from the simulation - real_time_data = Simulation.get_real_time_data() - - # Return the real-time data as JSON - return jsonify(real_time_data) - +# Add the parent directory to the Python path +sys.path.append(package_path) + +# Now you can import your module +from simulation.Simulation import Simulation + +def get_monitor(): + # Retrieve monitored data from the simulation + monitored_data = Simulation.get_monitored_data() + + # Return the monitored data as JSON + return jsonify(monitored_data) # Construct the path to the knobs.json file, assuming it's two directories back json_file_path = '../../knobs.json' @@ -54,4 +62,3 @@ def getAdaptationOptions(): return adaptation_options_data - diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index ec2bca7..4d5a4ec 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -1,20 +1,27 @@ from flask import Flask , jsonify -from app.simulation.Simulation import Simulation from endpoints import get_monitor , getAdaptationOptions , getexecute +import os +import sys + +# Get the path to the parent directory of the package +package_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + +# Add the parent directory to the Python path +sys.path.append(package_path) + +# Now you can import your module +from simulation.Simulation import Simulation + app = Flask(__name__) @app.route('/monitor', methods=['GET']) def monitor(): - Simulation.start() - -while True: - # Retrieve real-time data from the simulation - real_time_data = Simulation.get_real_time_data() - print("Real-time data from simulation:", real_time_data) - - time.sleep(5) # Adjust the sleep duration based on your requirements + # Retrieve monitored data from the simulation + monitored_data = Simulation.get_monitored_data() + # Return the monitored data as JSON + return jsonify(monitored_data) @app.route('/execute', methods=['PUT']) def execute_adaptation(): @@ -43,4 +50,3 @@ def get_adaptation_options_schema(): if __name__ == '__main__': app.run(debug=True) - From 8b6c31eaf6e1d74354dd571f2f958a8c27e50e36 Mon Sep 17 00:00:00 2001 From: yoBoyio Date: Fri, 17 Nov 2023 21:18:26 +0200 Subject: [PATCH 04/20] feat: a lot of breaking changes --- Dockerfile | 16 +++++++++++++--- app/HTTPServer/endpoints.py | 32 +++++++++++++++---------------- app/HTTPServer/main.py | 33 ++++++++++++++++---------------- app/HTTPServer/monitor_data.json | 7 ------- app/simulation/Simulation.py | 31 +++++++++++++++++++++++++++++- app/simulation/monitor_data.json | 0 read_data.py | 33 ++++++++++++++++++++++++++++++++ 7 files changed, 108 insertions(+), 44 deletions(-) delete mode 100644 app/HTTPServer/monitor_data.json create mode 100644 app/simulation/monitor_data.json create mode 100644 read_data.py diff --git a/Dockerfile b/Dockerfile index 476fe77..55a4b39 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,15 +3,25 @@ FROM starofall/crowdnav ADD /app/HTTPServer /app/HTTPServer COPY knobs.json knobs.json -COPY /app/simulation /app/simulation +# WORKDIR /app + +ADD app/simulation/Simulation.py app/simulation/Simulation.py +ADD app/simulation/monitor_data.json app/simulation/monitor_data.json + +# ADD /Config.py /Config.py -WORKDIR /../app -RUN python run.py WORKDIR /app/HTTPServer RUN pip install flask +# WORKDIR /app/HTTPServer +# COPY read_data.py /app/read_data.py +# CMD ["python", "/app/read_data.py"] + +# CMD [ "python" , "forever.py" ] CMD [ "python" , "/app/HTTPServer/main.py" ] +# RUN python main.py + diff --git a/app/HTTPServer/endpoints.py b/app/HTTPServer/endpoints.py index ccb2be6..e3ad469 100644 --- a/app/HTTPServer/endpoints.py +++ b/app/HTTPServer/endpoints.py @@ -6,31 +6,31 @@ import os # Get the path to the parent directory of the package -package_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +# package_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) # Add the parent directory to the Python path -sys.path.append(package_path) +# sys.path.append(package_path) # Now you can import your module -from simulation.Simulation import Simulation +# from simulation.Simulation import Simulation -def get_monitor(): - # Retrieve monitored data from the simulation - monitored_data = Simulation.get_monitored_data() +# def get_monitor(): +# # Retrieve monitored data from the simulation +# monitored_data = Simulation.get_monitored_data() - # Return the monitored data as JSON - return jsonify(monitored_data) +# # Return the monitored data as JSON +# return jsonify(monitored_data) # Construct the path to the knobs.json file, assuming it's two directories back -json_file_path = '../../knobs.json' +# json_file_path = '../../knobs.json' -# Open the JSON file in read mode ('r') -with open(json_file_path, 'r') as json_file: - # Use json.load() to read data from the file - adaptation_options_data = json.load(json_file) +# # Open the JSON file in read mode ('r') +# with open(json_file_path, 'r') as json_file: +# # Use json.load() to read data from the file +# adaptation_options_data = json.load(json_file) - # Now 'data' contains the contents of the JSON file as a Python dictionary - print(adaptation_options_data) +# # Now 'data' contains the contents of the JSON file as a Python dictionary +# print(adaptation_options_data) @@ -59,6 +59,6 @@ def getexecute(): return jsonify({"error": str(e)}), 500 def getAdaptationOptions(): - return adaptation_options_data + return 33 diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index 4d5a4ec..6fd1119 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -1,27 +1,26 @@ from flask import Flask , jsonify -from endpoints import get_monitor , getAdaptationOptions , getexecute - +from endpoints import getAdaptationOptions , getexecute +import json import os import sys -# Get the path to the parent directory of the package -package_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) - -# Add the parent directory to the Python path -sys.path.append(package_path) - -# Now you can import your module -from simulation.Simulation import Simulation app = Flask(__name__) @app.route('/monitor', methods=['GET']) def monitor(): + # Retrieve monitored data from the simulation - monitored_data = Simulation.get_monitored_data() - + # monitored_data = Simulation.get_monitored_data() + # monitored_data= read_monitored_data() + file_path = "../simulation/monitor_data.json" + + with open(file_path, "r") as json_file: + # Load the JSON data + data = json.load(json_file) # Return the monitored data as JSON - return jsonify(monitored_data) + print(data) + return jsonify(data) @app.route('/execute', methods=['PUT']) def execute_adaptation(): @@ -34,10 +33,10 @@ def get_adaptation_options(): data= getAdaptationOptions() return jsonify(data) -@app.route('/monitor_schema', methods=['GET']) -def get_monitor_schema(): - field_types = {key: type(value).__name__ for key, value in get_monitor().items()} - return field_types +# @app.route('/monitor_schema', methods=['GET']) +# def get_monitor_schema(): +# field_types = {key: type(value).__name__ for key, value in get_monitor().items()} +# return field_types @app.route('/execute_schema', methods=['GET']) def get_execute_schema(): diff --git a/app/HTTPServer/monitor_data.json b/app/HTTPServer/monitor_data.json deleted file mode 100644 index 1439b13..0000000 --- a/app/HTTPServer/monitor_data.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "totalCarCounter":2, - "carIndexCounter": 1, - "totalTrips": 1, - "totalTripAverage": 4, - "totalTripOverheadAverage": 44 -} \ No newline at end of file diff --git a/app/simulation/Simulation.py b/app/simulation/Simulation.py index afc44f2..6697062 100644 --- a/app/simulation/Simulation.py +++ b/app/simulation/Simulation.py @@ -136,7 +136,25 @@ def loop(cls): CarRegistry.totalTripAverage) + "(" + str( CarRegistry.totalTrips) + ")" + " # avgTripOverhead: " + str( CarRegistry.totalTripOverheadAverage)) - + file_path = "./monitor_data.json" + data = { + 'totalCarCounter': CarRegistry.totalCarCounter, + 'carIndexCounter': CarRegistry.carIndexCounter, + 'totalTrips': CarRegistry.totalTrips, + 'totalTripAverage': CarRegistry.totalTripAverage, + 'totalTripOverheadAverage': CarRegistry.totalTripOverheadAverage + } + # Open the file in write mode ('w') + with open(file_path, 'w') as json_file: + # Use json.dump() to write data to the file + json.dump(data, json_file) + + + with open(file_path, "r") as json_file: + # Load the JSON data + data = json.load(json_file) + + print("####JSON file", data) # @depricated -> will be removed # # if we are in paralllel mode we end the simulation after 10000 ticks with a result output # if (cls.tick % 10000) == 0 and Config.parallelMode: @@ -148,3 +166,14 @@ def loop(cls): # CarRegistry.totalTrips) + ")" + " # avgTripOverhead: " + str( # CarRegistry.totalTripOverheadAverage)) # return + @classmethod + def get_monitored_data(cls): + # Add logic here to collect the data you want to monitor + monitored_data = { + 'vehicle_count': traci.vehicle.getIDCount(), + 'avg_trip_duration': CarRegistry.totalTripAverage, + 'total_trips': CarRegistry.totalTrips, + 'avg_trip_overhead': CarRegistry.totalTripOverheadAverage + # Add more data as needed + } + return monitored_data \ No newline at end of file diff --git a/app/simulation/monitor_data.json b/app/simulation/monitor_data.json new file mode 100644 index 0000000..e69de29 diff --git a/read_data.py b/read_data.py new file mode 100644 index 0000000..ce1c244 --- /dev/null +++ b/read_data.py @@ -0,0 +1,33 @@ +import threading +import time +# import os , sys +# package_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + +# # Add the parent directory to the Python path +# sys.path.append(package_path) +from app.simulation.Simulation import Simulation +from app.streaming import RTXConnector + + + +def read_data_thread(thread_id): + for i in range(5): + print('Thread', {thread_id}) + time.sleep(1) + +if __name__ == "__main__": + threads = [] + + # Create and start multiple threads + newConf = RTXConnector.checkForNewConfiguration() + print(RTXConnector) + for i in range(3): + thread = threading.Thread(target=read_data_thread, args=(i,)) + thread.start() + threads.append(thread) + + # Wait for all threads to finish + for thread in threads: + thread.join() + + print("All threads have finished reading data.") From be58261977b831a54c1073a2eeed2f0fe7e6291e Mon Sep 17 00:00:00 2001 From: yoBoyio Date: Sun, 19 Nov 2023 00:25:57 +0200 Subject: [PATCH 05/20] feat: starting HTTP server from simulation file --- Dockerfile | 34 ++--------- app/HTTPServer/main.py | 106 ++++++++++++++++++++++------------- app/simulation/Simulation.py | 15 +++++ app/simulation/views.py | 30 ++++++++++ 4 files changed, 118 insertions(+), 67 deletions(-) create mode 100644 app/simulation/views.py diff --git a/Dockerfile b/Dockerfile index 55a4b39..9453b1a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,42 +7,18 @@ COPY knobs.json knobs.json ADD app/simulation/Simulation.py app/simulation/Simulation.py ADD app/simulation/monitor_data.json app/simulation/monitor_data.json +ADD app/simulation/views.py app/simulation/views.py # ADD /Config.py /Config.py -WORKDIR /app/HTTPServer +# WORKDIR /app/HTTPServer RUN pip install flask # WORKDIR /app/HTTPServer # COPY read_data.py /app/read_data.py # CMD ["python", "/app/read_data.py"] -# CMD [ "python" , "forever.py" ] -CMD [ "python" , "/app/HTTPServer/main.py" ] -# RUN python main.py - - - - - -# RUN apt-get update && \ -# apt-get install -y \ - # build-essential \ - # git \ - # libxerces-c-dev - -#RUN mkdir -p /opt -#RUN (cd /opt; git clone https://github.com/radiganm/sumo.git) -#RUN (cd /opt/sumo; ./configure) -#RUN (cd /opt/sumo; make) -#RUN (cd /opt/sumo; make install) - -#ENV SUMO_HOME /opt/sumo -# First cache dependencies -#ADD ./setup.py /app/setup.py -#RUN python /app/setup.py install -# Add sources -#ADD ./ /app/ -#WORKDIR /app -#CMD ["python","/app/forever.py"] +CMD [ "python" , "forever.py" ] +# CMD [ "python" , "/app/HTTPServer/main.py" ] +# RUN python main.py \ No newline at end of file diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index 6fd1119..84e11a0 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -1,51 +1,81 @@ -from flask import Flask , jsonify -from endpoints import getAdaptationOptions , getexecute -import json -import os -import sys +# from flask import Flask , jsonify +# from endpoints import getAdaptationOptions , getexecute +# import json +# import os +# import sys -app = Flask(__name__) +# app = Flask(__name__) -@app.route('/monitor', methods=['GET']) -def monitor(): +# @app.route('/monitor', methods=['GET']) +# def monitor(): - # Retrieve monitored data from the simulation - # monitored_data = Simulation.get_monitored_data() - # monitored_data= read_monitored_data() - file_path = "../simulation/monitor_data.json" +# # Retrieve monitored data from the simulation +# # monitored_data = Simulation.get_monitored_data() +# # monitored_data= read_monitored_data() +# file_path = "../simulation/monitor_data.json" - with open(file_path, "r") as json_file: - # Load the JSON data - data = json.load(json_file) - # Return the monitored data as JSON - print(data) - return jsonify(data) +# with open(file_path, "r") as json_file: +# # Load the JSON data +# data = json.load(json_file) +# # Return the monitored data as JSON +# print(data) +# return jsonify(data) -@app.route('/execute', methods=['PUT']) -def execute_adaptation(): - data = getexecute() - return jsonify(data) +# @app.route('/execute', methods=['PUT']) +# def execute_adaptation(): +# data = getexecute() +# return jsonify(data) + + +# @app.route('/adaptation_options', methods=['GET']) +# def get_adaptation_options(): +# data= getAdaptationOptions() +# return jsonify(data) + +# # @app.route('/monitor_schema', methods=['GET']) +# # def get_monitor_schema(): +# # field_types = {key: type(value).__name__ for key, value in get_monitor().items()} +# # return field_types +# @app.route('/execute_schema', methods=['GET']) +# def get_execute_schema(): +# return jsonify({"execute_schema": "This is /execute_schema endpoint"}) -@app.route('/adaptation_options', methods=['GET']) -def get_adaptation_options(): - data= getAdaptationOptions() - return jsonify(data) +# @app.route('/adaptation_options_schema', methods=['GET']) +# def get_adaptation_options_schema(): +# return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) + +# if __name__ == '__main__': +# app.run(debug=True) +# views.py +from flask import jsonify +from flask.views import MethodView +from endpoints import getAdaptationOptions, getexecute +import json + +class MonitorAPI(MethodView): + def get(self): + file_path = "./monitor_data.json" + with open(file_path, "r") as json_file: + data = json.load(json_file) + return jsonify(data) -# @app.route('/monitor_schema', methods=['GET']) -# def get_monitor_schema(): -# field_types = {key: type(value).__name__ for key, value in get_monitor().items()} -# return field_types +class ExecuteAPI(MethodView): + def put(self): + data = getexecute() + return jsonify(data) -@app.route('/execute_schema', methods=['GET']) -def get_execute_schema(): - return jsonify({"execute_schema": "This is /execute_schema endpoint"}) +class AdaptationOptionsAPI(MethodView): + def get(self): + data = getAdaptationOptions() + return jsonify(data) -@app.route('/adaptation_options_schema', methods=['GET']) -def get_adaptation_options_schema(): - return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) +class ExecuteSchemaAPI(MethodView): + def get(self): + return jsonify({"execute_schema": "This is /execute_schema endpoint"}) -if __name__ == '__main__': - app.run(debug=True) +class AdaptationOptionsSchemaAPI(MethodView): + def get(self): + return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) diff --git a/app/simulation/Simulation.py b/app/simulation/Simulation.py index 6697062..a6c9da8 100644 --- a/app/simulation/Simulation.py +++ b/app/simulation/Simulation.py @@ -2,6 +2,8 @@ import traci import traci.constants as tc from app.network.Network import Network +from flask import Flask , jsonify +from views import MonitorAPI, ExecuteAPI, AdaptationOptionsAPI, ExecuteSchemaAPI, AdaptationOptionsSchemaAPI from app.streaming import RTXForword from colorama import Fore @@ -21,6 +23,7 @@ class Simulation(object): """ here we run the simulation in """ + app = Flask(__name__) # the current tick of the simulation tick = 0 @@ -41,6 +44,17 @@ def applyFileConfig(cls): CustomRouter.reRouteEveryTicks = config['reRouteEveryTicks'] except: pass + + @classmethod + def registerHTTPServer(cls): + # Register the views with the app + cls.app.add_url_rule('/monitor', view_func=MonitorAPI.as_view('monitor')) + cls.app.add_url_rule('/execute', view_func=ExecuteAPI.as_view('execute')) + cls.app.add_url_rule('/adaptation_options', view_func=AdaptationOptionsAPI.as_view('adaptation_options')) + cls.app.add_url_rule('/execute_schema', view_func=ExecuteSchemaAPI.as_view('execute_schema')) + cls.app.add_url_rule('/adaptation_options_schema', view_func=AdaptationOptionsSchemaAPI.as_view('adaptation_options_schema')) + cls.app.run(debug=True) + @classmethod def start(cls): @@ -49,6 +63,7 @@ def start(cls): # apply the configuration from the json file cls.applyFileConfig() CarRegistry.applyCarCounter() + cls.registerHTTPServer() cls.loop() @classmethod diff --git a/app/simulation/views.py b/app/simulation/views.py new file mode 100644 index 0000000..60ebf69 --- /dev/null +++ b/app/simulation/views.py @@ -0,0 +1,30 @@ +from flask import jsonify +from flask.views import MethodView +# from endpoints import getAdaptationOptions, getexecute +import json + +class MonitorAPI(MethodView): + def get(self): + file_path = "./monitor_data.json" + with open(file_path, "r") as json_file: + data = json.load(json_file) + return jsonify(data) + +class ExecuteAPI(MethodView): + def put(self): + # data = getexecute() + return jsonify({"execute_schema": "This is /execute_schema endpoint"}) + +class AdaptationOptionsAPI(MethodView): + def get(self): + # data = getAdaptationOptions() + return jsonify({"AdaptationOptionsAPI": "This is /AdaptationOptionsAPI endpoint"}) + +class ExecuteSchemaAPI(MethodView): + def get(self): + return jsonify({"execute_schema": "This is /execute_schema endpoint"}) + +class AdaptationOptionsSchemaAPI(MethodView): + def get(self): + return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) + From f3c57951bed71c0ca619a18663850b989c04a55a Mon Sep 17 00:00:00 2001 From: yoBoyio Date: Sun, 19 Nov 2023 15:09:53 +0200 Subject: [PATCH 06/20] feat: add docker-compose --- docker-compose.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2d04a15 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3' + +services: + flask-app: + build: + context: . + ports: + - "5000:5000" + command: python /app/HTTPServer/main.py + network_mode: host + depends_on: + - kafka + + kafka: + image: newcrowdnav:latest + environment: + KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092,OUTSIDE://localhost:9092 + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT + KAFKA_LISTENERS: INSIDE://0.0.0.0:9092,OUTSIDE://0.0.0.0:9092 + KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE \ No newline at end of file From 4266878788ea653cc74951e87118cfd80ce049d4 Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Sun, 19 Nov 2023 17:08:17 +0100 Subject: [PATCH 07/20] Made changes to Dockerfile and the endpoints --- Dockerfile | 28 +++++--- app/Boot.py | 7 +- app/Config.py | 2 +- app/HTTPServer/__init__.py | 0 app/HTTPServer/main.py | 126 +++++++++++++++++++---------------- app/simulation/Simulation.py | 5 +- 6 files changed, 94 insertions(+), 74 deletions(-) create mode 100644 app/HTTPServer/__init__.py diff --git a/Dockerfile b/Dockerfile index 9453b1a..7aabc9e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,22 +3,34 @@ FROM starofall/crowdnav ADD /app/HTTPServer /app/HTTPServer COPY knobs.json knobs.json -# WORKDIR /app +WORKDIR /app + +COPY . /app -ADD app/simulation/Simulation.py app/simulation/Simulation.py -ADD app/simulation/monitor_data.json app/simulation/monitor_data.json -ADD app/simulation/views.py app/simulation/views.py -# ADD /Config.py /Config.py -# WORKDIR /app/HTTPServer RUN pip install flask -# WORKDIR /app/HTTPServer + +# ADD /Config.py /Config.py + + + + + +#WORKDIR /app/ +#RUN python forever.py + +WORKDIR /app/ +RUN python forever.py + +WORKDIR /app/HTTPServer +CMD [ "python" , "main.py" ] + # COPY read_data.py /app/read_data.py # CMD ["python", "/app/read_data.py"] -CMD [ "python" , "forever.py" ] + # CMD [ "python" , "/app/HTTPServer/main.py" ] # RUN python main.py \ No newline at end of file diff --git a/app/Boot.py b/app/Boot.py index 8c79d30..572a1b2 100644 --- a/app/Boot.py +++ b/app/Boot.py @@ -8,12 +8,11 @@ from app.routing.CustomRouter import CustomRouter from app.network.Network import Network from app.simulation.Simulation import Simulation -from streaming import RTXForword +from app.streaming import RTXForword from colorama import Fore -from sumo import SUMOConnector, SUMODependency -import Config +from app.sumo import SUMOConnector, SUMODependency +from app import Config import traci, sys, os -import thread import time diff --git a/app/Config.py b/app/Config.py index 15dcae2..f7cc6fd 100644 --- a/app/Config.py +++ b/app/Config.py @@ -9,7 +9,7 @@ mqttUpdates = False mqttHost = "localhost" -mqttPort = "1883" +mqttPort = "1883" #1883 # the topic we send the kafka messages to kafkaTopicTrips = "crowd-nav-trips" diff --git a/app/HTTPServer/__init__.py b/app/HTTPServer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index 84e11a0..3321197 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -1,75 +1,73 @@ -# from flask import Flask , jsonify -# from endpoints import getAdaptationOptions , getexecute -# import json -# import os -# import sys - - -# app = Flask(__name__) - -# @app.route('/monitor', methods=['GET']) -# def monitor(): - -# # Retrieve monitored data from the simulation -# # monitored_data = Simulation.get_monitored_data() -# # monitored_data= read_monitored_data() -# file_path = "../simulation/monitor_data.json" - -# with open(file_path, "r") as json_file: -# # Load the JSON data -# data = json.load(json_file) -# # Return the monitored data as JSON -# print(data) -# return jsonify(data) - -# @app.route('/execute', methods=['PUT']) -# def execute_adaptation(): -# data = getexecute() -# return jsonify(data) - +from flask import Flask, jsonify, request +from flask.views import MethodView +import json -# @app.route('/adaptation_options', methods=['GET']) -# def get_adaptation_options(): -# data= getAdaptationOptions() -# return jsonify(data) +app = Flask(__name__) -# # @app.route('/monitor_schema', methods=['GET']) -# # def get_monitor_schema(): -# # field_types = {key: type(value).__name__ for key, value in get_monitor().items()} -# # return field_types +knobs_path = '../../knobs.json' +monitor_data_path = 'app/simulation/monitor_data.json' -# @app.route('/execute_schema', methods=['GET']) -# def get_execute_schema(): -# return jsonify({"execute_schema": "This is /execute_schema endpoint"}) +def read_knobs(): + """Read the knobs.json file.""" + try: + with open(knobs_path, 'r') as file: + knobs_data = json.load(file) + return knobs_data + except FileNotFoundError: + return None -# @app.route('/adaptation_options_schema', methods=['GET']) -# def get_adaptation_options_schema(): -# return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) - -# if __name__ == '__main__': -# app.run(debug=True) -# views.py -from flask import jsonify -from flask.views import MethodView -from endpoints import getAdaptationOptions, getexecute -import json +def write_knobs(data): + """Write data to the knobs.json file.""" + with open(knobs_path, 'w') as file: + json.dump(data, file, indent=2) class MonitorAPI(MethodView): def get(self): - file_path = "./monitor_data.json" - with open(file_path, "r") as json_file: - data = json.load(json_file) - return jsonify(data) + try: + with open(monitor_data_path, "r") as json_file: + data = json.load(json_file) + return jsonify(data) + except FileNotFoundError: + return jsonify({'error': 'monitor_data.json not found'}), 404 class ExecuteAPI(MethodView): def put(self): - data = getexecute() - return jsonify(data) + try: + data = request.get_json() + + return jsonify({'success': True}) + except Exception as e: + return jsonify({'error': str(e)}), 500 class AdaptationOptionsAPI(MethodView): def get(self): - data = getAdaptationOptions() - return jsonify(data) + knobs_data = read_knobs() + if knobs_data is not None: + return jsonify(knobs_data) + else: + return jsonify({'error': 'knobs.json not found'}), 404 + + def put(self): + try: + data = request.get_json() + write_knobs(data) + return jsonify({'success': True}) + except Exception as e: + return jsonify({'error': str(e)}), 500 + +class MonitorSchemaAPI(MethodView): + def monitor_schema(): + schema = { + 'type': 'object', + 'properties': { + 'vehicle_count': {'type': 'integer'}, + 'avg_trip_duration': {'type': 'number'}, + 'total_trips': {'type': 'integer'}, + 'avg_trip_overhead': {'type': 'number'} + }, + 'required': ['vehicle_count', 'avg_trip_duration', 'total_trips', 'avg_trip_overhead'] + } + return jsonify(schema) class ExecuteSchemaAPI(MethodView): def get(self): @@ -79,3 +77,13 @@ class AdaptationOptionsSchemaAPI(MethodView): def get(self): return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) +# Registering the views +app.add_url_rule('/monitor', view_func=MonitorAPI.as_view('monitor_api')) +app.add_url_rule('/execute', view_func=ExecuteAPI.as_view('execute_api')) +app.add_url_rule('/adaptation_options', view_func=AdaptationOptionsAPI.as_view('adaptation_options_api')) +app.add_url_rule('/execute_schema', view_func=ExecuteSchemaAPI.as_view('execute_schema_api')) +app.add_url_rule('/adaptation_options_schema', view_func=AdaptationOptionsSchemaAPI.as_view('adaptation_options_schema_api')) +app.add_url_rule('/monitor_schema', view_func=MonitorSchemaAPI.as_view('monitor_schema_api')) + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) diff --git a/app/simulation/Simulation.py b/app/simulation/Simulation.py index a6c9da8..cc99b24 100644 --- a/app/simulation/Simulation.py +++ b/app/simulation/Simulation.py @@ -2,8 +2,8 @@ import traci import traci.constants as tc from app.network.Network import Network -from flask import Flask , jsonify -from views import MonitorAPI, ExecuteAPI, AdaptationOptionsAPI, ExecuteSchemaAPI, AdaptationOptionsSchemaAPI +from flask import Flask , jsonify , views +from app.HTTPServer.main import MonitorAPI, ExecuteAPI, AdaptationOptionsAPI, ExecuteSchemaAPI, AdaptationOptionsSchemaAPI from app.streaming import RTXForword from colorama import Fore @@ -181,6 +181,7 @@ def loop(cls): # CarRegistry.totalTrips) + ")" + " # avgTripOverhead: " + str( # CarRegistry.totalTripOverheadAverage)) # return + @classmethod def get_monitored_data(cls): # Add logic here to collect the data you want to monitor From e611cd1c42534e264626b8109161bb5b69e98707 Mon Sep 17 00:00:00 2001 From: yoBoyio Date: Mon, 20 Nov 2023 03:56:12 +0200 Subject: [PATCH 08/20] feat: add monitor jsondata --- app/simulation/monitor_data.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/simulation/monitor_data.json b/app/simulation/monitor_data.json index e69de29..2fc45b7 100644 --- a/app/simulation/monitor_data.json +++ b/app/simulation/monitor_data.json @@ -0,0 +1,7 @@ +{ + "totalCarCounter": 100, + "carIndexCounter": 4, + "totalTrips": 45, + "totalTripAverage": 4, + "totalTripOverheadAverage": 20 +} \ No newline at end of file From 899f7029dad9fd356d91e6bdfc4b67de175d4c3d Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Mon, 20 Nov 2023 03:00:44 +0100 Subject: [PATCH 09/20] New Changes --- Dockerfile | 4 +- app/HTTPServer/main.py | 88 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7aabc9e..5eb8c30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,8 +21,8 @@ RUN pip install flask #WORKDIR /app/ #RUN python forever.py -WORKDIR /app/ -RUN python forever.py +#WORKDIR /app/ +#RUN python forever.py WORKDIR /app/HTTPServer CMD [ "python" , "main.py" ] diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index 3321197..80f2ac6 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -71,11 +71,95 @@ def monitor_schema(): class ExecuteSchemaAPI(MethodView): def get(self): - return jsonify({"execute_schema": "This is /execute_schema endpoint"}) + schema = { + 'type': 'object', + 'properties': { + 'routeRandomSigma': { + 'type': 'number', + 'description': 'The randomization sigma of edge weights' + }, + 'explorationPercentage': { + 'type': 'number', + 'description': 'The percentage of routes used for exploration' + }, + 'maxSpeedAndLengthFactor': { + 'type': 'integer', + 'description': 'How much the length/speed influences the routing' + }, + 'averageEdgeDurationFactor': { + 'type': 'integer', + 'description': 'How much the average edge factor influences the routing' + }, + 'freshnessUpdateFactor': { + 'type': 'integer', + 'description': 'How much the freshness update factor influences the routing' + },'freshnessCutOffValue': { + 'type': 'integer', + 'description': 'If data is older than this, it is not considered in the algorithm' + }, + 'reRouteEveryTicks': { + 'type': 'integer', + 'description': 'Check for a new route every x times after the car starts' + }, + # Add more properties as needed + }, + 'required': [ + 'routeRandomSigma', + 'explorationPercentage', + 'maxSpeedAndLengthFactor', + 'averageEdgeDurationFactor', + 'freshnessUpdateFactor', + 'freshnessCutOffValue', + 'reRouteEveryTicks' + ], + } + return jsonify(schema) class AdaptationOptionsSchemaAPI(MethodView): def get(self): - return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) + schema = { + 'type': 'object', + 'properties': { + 'routeRandomSigma': { + 'type': 'number', + 'description': 'The randomization sigma of edge weights' + }, + 'explorationPercentage': { + 'type': 'number', + 'description': 'The percentage of routes used for exploration' + }, + 'maxSpeedAndLengthFactor': { + 'type': 'integer', + 'description': 'How much the length/speed influences the routing' + }, + 'averageEdgeDurationFactor': { + 'type': 'integer', + 'description': 'How much the average edge factor influences the routing' + }, + 'freshnessUpdateFactor': { + 'type': 'integer', + 'description': 'How much the freshness update factor influences the routing' + },'freshnessCutOffValue': { + 'type': 'integer', + 'description': 'If data is older than this, it is not considered in the algorithm' + }, + 'reRouteEveryTicks': { + 'type': 'integer', + 'description': 'Check for a new route every x times after the car starts' + }, + # Add more properties as needed + }, + 'required': [ + 'routeRandomSigma', + 'explorationPercentage', + 'maxSpeedAndLengthFactor', + 'averageEdgeDurationFactor', + 'freshnessUpdateFactor', + 'freshnessCutOffValue', + 'reRouteEveryTicks' + ], + } + return jsonify(schema) # Registering the views app.add_url_rule('/monitor', view_func=MonitorAPI.as_view('monitor_api')) From f2ebd0b819b51f0eb0f41768675df35cd8e86264 Mon Sep 17 00:00:00 2001 From: yoBoyio Date: Mon, 20 Nov 2023 04:02:41 +0200 Subject: [PATCH 10/20] feat: improvements on some files --- Dockerfile | 24 ------------------------ app/HTTPServer/main.py | 31 +++++++++++++++---------------- app/simulation/Simulation.py | 19 +------------------ 3 files changed, 16 insertions(+), 58 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5eb8c30..2ebade9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,31 +6,7 @@ COPY knobs.json knobs.json WORKDIR /app COPY . /app - - - - RUN pip install flask -# ADD /Config.py /Config.py - - - - - -#WORKDIR /app/ -#RUN python forever.py - -#WORKDIR /app/ -#RUN python forever.py - WORKDIR /app/HTTPServer CMD [ "python" , "main.py" ] - -# COPY read_data.py /app/read_data.py - -# CMD ["python", "/app/read_data.py"] - - -# CMD [ "python" , "/app/HTTPServer/main.py" ] -# RUN python main.py \ No newline at end of file diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index 80f2ac6..0d51226 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -1,12 +1,11 @@ from flask import Flask, jsonify, request from flask.views import MethodView import json - +import os app = Flask(__name__) knobs_path = '../../knobs.json' -monitor_data_path = 'app/simulation/monitor_data.json' - +monitor_data_path = os.path.join(os.path.dirname(__file__), '..', 'simulation', 'monitor_data.json') def read_knobs(): """Read the knobs.json file.""" try: @@ -23,12 +22,12 @@ def write_knobs(data): class MonitorAPI(MethodView): def get(self): - try: - with open(monitor_data_path, "r") as json_file: - data = json.load(json_file) - return jsonify(data) - except FileNotFoundError: - return jsonify({'error': 'monitor_data.json not found'}), 404 + # try: + with open(monitor_data_path, "r") as json_file: + data = json.load(json_file) + return jsonify(data) + # except FileNotFoundError: + # return jsonify({'error': 'monitor_data.json not found'}), 404 class ExecuteAPI(MethodView): def put(self): @@ -161,13 +160,13 @@ def get(self): } return jsonify(schema) -# Registering the views -app.add_url_rule('/monitor', view_func=MonitorAPI.as_view('monitor_api')) -app.add_url_rule('/execute', view_func=ExecuteAPI.as_view('execute_api')) -app.add_url_rule('/adaptation_options', view_func=AdaptationOptionsAPI.as_view('adaptation_options_api')) -app.add_url_rule('/execute_schema', view_func=ExecuteSchemaAPI.as_view('execute_schema_api')) -app.add_url_rule('/adaptation_options_schema', view_func=AdaptationOptionsSchemaAPI.as_view('adaptation_options_schema_api')) -app.add_url_rule('/monitor_schema', view_func=MonitorSchemaAPI.as_view('monitor_schema_api')) if __name__ == '__main__': + # Registering the views + app.add_url_rule('/monitor', view_func=MonitorAPI.as_view('monitor_api')) + app.add_url_rule('/execute', view_func=ExecuteAPI.as_view('execute_api')) + app.add_url_rule('/adaptation_options', view_func=AdaptationOptionsAPI.as_view('adaptation_options_api')) + app.add_url_rule('/execute_schema', view_func=ExecuteSchemaAPI.as_view('execute_schema_api')) + app.add_url_rule('/adaptation_options_schema', view_func=AdaptationOptionsSchemaAPI.as_view('adaptation_options_schema_api')) + app.add_url_rule('/monitor_schema', view_func=MonitorSchemaAPI.as_view('monitor_schema_api')) app.run(host='0.0.0.0', port=5000) diff --git a/app/simulation/Simulation.py b/app/simulation/Simulation.py index cc99b24..94db101 100644 --- a/app/simulation/Simulation.py +++ b/app/simulation/Simulation.py @@ -53,7 +53,7 @@ def registerHTTPServer(cls): cls.app.add_url_rule('/adaptation_options', view_func=AdaptationOptionsAPI.as_view('adaptation_options')) cls.app.add_url_rule('/execute_schema', view_func=ExecuteSchemaAPI.as_view('execute_schema')) cls.app.add_url_rule('/adaptation_options_schema', view_func=AdaptationOptionsSchemaAPI.as_view('adaptation_options_schema')) - cls.app.run(debug=True) + cls.app.run(host='0.0.0.0', port=5000) @classmethod @@ -165,11 +165,6 @@ def loop(cls): json.dump(data, json_file) - with open(file_path, "r") as json_file: - # Load the JSON data - data = json.load(json_file) - - print("####JSON file", data) # @depricated -> will be removed # # if we are in paralllel mode we end the simulation after 10000 ticks with a result output # if (cls.tick % 10000) == 0 and Config.parallelMode: @@ -181,15 +176,3 @@ def loop(cls): # CarRegistry.totalTrips) + ")" + " # avgTripOverhead: " + str( # CarRegistry.totalTripOverheadAverage)) # return - - @classmethod - def get_monitored_data(cls): - # Add logic here to collect the data you want to monitor - monitored_data = { - 'vehicle_count': traci.vehicle.getIDCount(), - 'avg_trip_duration': CarRegistry.totalTripAverage, - 'total_trips': CarRegistry.totalTrips, - 'avg_trip_overhead': CarRegistry.totalTripOverheadAverage - # Add more data as needed - } - return monitored_data \ No newline at end of file From c1758e5354e16431508dbff2b02a08479cce04aa Mon Sep 17 00:00:00 2001 From: yoBoyio Date: Mon, 20 Nov 2023 04:05:36 +0200 Subject: [PATCH 11/20] fix: delete unused file --- app/HTTPServer/endpoints.py | 64 ------------------------------------- 1 file changed, 64 deletions(-) delete mode 100644 app/HTTPServer/endpoints.py diff --git a/app/HTTPServer/endpoints.py b/app/HTTPServer/endpoints.py deleted file mode 100644 index e3ad469..0000000 --- a/app/HTTPServer/endpoints.py +++ /dev/null @@ -1,64 +0,0 @@ -from flask import Flask, jsonify, request -import json - -import sys -import sys -import os - -# Get the path to the parent directory of the package -# package_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) - -# Add the parent directory to the Python path -# sys.path.append(package_path) - -# Now you can import your module -# from simulation.Simulation import Simulation - -# def get_monitor(): -# # Retrieve monitored data from the simulation -# monitored_data = Simulation.get_monitored_data() - -# # Return the monitored data as JSON -# return jsonify(monitored_data) - -# Construct the path to the knobs.json file, assuming it's two directories back -# json_file_path = '../../knobs.json' - -# # Open the JSON file in read mode ('r') -# with open(json_file_path, 'r') as json_file: -# # Use json.load() to read data from the file -# adaptation_options_data = json.load(json_file) - -# # Now 'data' contains the contents of the JSON file as a Python dictionary -# print(adaptation_options_data) - - - - -def getexecute(): - try: - # Get the JSON data from the request body - request_data = request.get_json() - - # Check if the required adaptation fields are present in the request data - required_fields = ["routeRandomSigma", "explorationPercentage", "maxSpeedAndLengthFactor", - "averageEdgeDurationFactor", "freshnessUpdateFactor", "freshnessCutOffValue", - "reRouteEveryTicks"] - if not all(field in request_data for field in required_fields): - return jsonify({"error": "Missing required fields in the adaptation request"}), 400 - - # Implement your adaptation logic here based on the received data - # For demonstration, we'll print the received data - print('Received adaptation data: {request_data}') - - # Return a response indicating the success of the adaptation - return jsonify({"message": "Adaptation executed successfully"}) - - except Exception as e: - # Handle exceptions and return an error response - return jsonify({"error": str(e)}), 500 - -def getAdaptationOptions(): - return 33 - - From f03c34c394843f41b99ea81ccd40fb02631e795f Mon Sep 17 00:00:00 2001 From: r0han0908 <150334840+r0han0908@users.noreply.github.com> Date: Fri, 22 Dec 2023 01:56:13 +0100 Subject: [PATCH 12/20] Add files via upload --- Dockerfile | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2ebade9..acd0cbb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,20 @@ FROM starofall/crowdnav -ADD /app/HTTPServer /app/HTTPServer -COPY knobs.json knobs.json +COPY . . -WORKDIR /app +# WORKDIR /app -COPY . /app +# COPY . /app RUN pip install flask -WORKDIR /app/HTTPServer -CMD [ "python" , "main.py" ] +COPY ./start.sh /app + +# WORKDIR /app + +EXPOSE 5000 + +WORKDIR /app + +RUN chmod 777 ./start.sh + +CMD ["bash", "start.sh"] From 05ee2c77b2fb32f16df3742dd1a49ebc173cbb5d Mon Sep 17 00:00:00 2001 From: r0han0908 <150334840+r0han0908@users.noreply.github.com> Date: Fri, 22 Dec 2023 01:57:23 +0100 Subject: [PATCH 13/20] Add files via upload --- app/HTTPServer/endpoints.py | 60 ++++++++++++++ app/HTTPServer/main.py | 129 +++++++++---------------------- app/HTTPServer/monitor_data.json | 7 ++ app/HTTPServer/readme.md | 8 +- 4 files changed, 109 insertions(+), 95 deletions(-) create mode 100644 app/HTTPServer/endpoints.py create mode 100644 app/HTTPServer/monitor_data.json diff --git a/app/HTTPServer/endpoints.py b/app/HTTPServer/endpoints.py new file mode 100644 index 0000000..c032f85 --- /dev/null +++ b/app/HTTPServer/endpoints.py @@ -0,0 +1,60 @@ +from flask import Flask, jsonify, request +import json + + +def get_monitor(): + file_path = "./monitor_data.json" + + try: + with open(file_path, 'r') as json_file: + data = json.load(json_file) + return data + + except FileNotFoundError: + raise FileNotFoundError("Monitor data not found") + + except Exception as e: + raise e + + +# Construct the path to the knobs.json file, assuming it's two directories back +json_file_path = '../../knobs.json' + +# Open the JSON file in read mode ('r') +with open(json_file_path, 'r') as json_file: + # Use json.load() to read data from the file + adaptation_options_data = json.load(json_file) + + # Now 'data' contains the contents of the JSON file as a Python dictionary + print(adaptation_options_data) + + + + +def getexecute(): + try: + # Get the JSON data from the request body + request_data = request.get_json() + + # Check if the required adaptation fields are present in the request data + required_fields = ["routeRandomSigma", "explorationPercentage", "maxSpeedAndLengthFactor", + "averageEdgeDurationFactor", "freshnessUpdateFactor", "freshnessCutOffValue", + "reRouteEveryTicks"] + if not all(field in request_data for field in required_fields): + return jsonify({"error": "Missing required fields in the adaptation request"}), 400 + + # Implement your adaptation logic here based on the received data + # For demonstration, we'll print the received data + print('Received adaptation data: {request_data}') + + # Return a response indicating the success of the adaptation + return jsonify({"message": "Adaptation executed successfully"}) + + except Exception as e: + # Handle exceptions and return an error response + return jsonify({"error": str(e)}), 500 + +def getAdaptationOptions(): + return adaptation_options_data + + diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index 0d51226..d013b8b 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -1,11 +1,13 @@ -from flask import Flask, jsonify, request +from flask import Flask, jsonify from flask.views import MethodView import json -import os +from endpoints import get_monitor + app = Flask(__name__) knobs_path = '../../knobs.json' -monitor_data_path = os.path.join(os.path.dirname(__file__), '..', 'simulation', 'monitor_data.json') + + def read_knobs(): """Read the knobs.json file.""" try: @@ -15,105 +17,47 @@ def read_knobs(): except FileNotFoundError: return None + def write_knobs(data): """Write data to the knobs.json file.""" with open(knobs_path, 'w') as file: json.dump(data, file, indent=2) + class MonitorAPI(MethodView): def get(self): - # try: - with open(monitor_data_path, "r") as json_file: - data = json.load(json_file) - return jsonify(data) - # except FileNotFoundError: - # return jsonify({'error': 'monitor_data.json not found'}), 404 - -class ExecuteAPI(MethodView): - def put(self): try: - data = request.get_json() - - return jsonify({'success': True}) - except Exception as e: - return jsonify({'error': str(e)}), 500 + file_path = "./monitor_data.json" + with open(file_path, "r") as json_file: + data = json.load(json_file) + return jsonify(data) + except FileNotFoundError: + return jsonify({'error': 'monitor_data.json not found'}), 404 -class AdaptationOptionsAPI(MethodView): - def get(self): - knobs_data = read_knobs() - if knobs_data is not None: - return jsonify(knobs_data) - else: - return jsonify({'error': 'knobs.json not found'}), 404 - def put(self): - try: - data = request.get_json() - write_knobs(data) - return jsonify({'success': True}) - except Exception as e: - return jsonify({'error': str(e)}), 500 +app.add_url_rule('/monitor', view_func=MonitorAPI.as_view('monitor')) -class MonitorSchemaAPI(MethodView): - def monitor_schema(): - schema = { - 'type': 'object', - 'properties': { - 'vehicle_count': {'type': 'integer'}, - 'avg_trip_duration': {'type': 'number'}, - 'total_trips': {'type': 'integer'}, - 'avg_trip_overhead': {'type': 'number'} - }, - 'required': ['vehicle_count', 'avg_trip_duration', 'total_trips', 'avg_trip_overhead'] - } - return jsonify(schema) -class ExecuteSchemaAPI(MethodView): +@app.route('/execute', methods=['PUT']) +def execute_adaptation(): + data = get_execute() + return jsonify(data) + + +class MonitorSchemaAPI(MethodView): def get(self): schema = { - 'type': 'object', - 'properties': { - 'routeRandomSigma': { - 'type': 'number', - 'description': 'The randomization sigma of edge weights' - }, - 'explorationPercentage': { - 'type': 'number', - 'description': 'The percentage of routes used for exploration' - }, - 'maxSpeedAndLengthFactor': { - 'type': 'integer', - 'description': 'How much the length/speed influences the routing' - }, - 'averageEdgeDurationFactor': { - 'type': 'integer', - 'description': 'How much the average edge factor influences the routing' - }, - 'freshnessUpdateFactor': { - 'type': 'integer', - 'description': 'How much the freshness update factor influences the routing' - },'freshnessCutOffValue': { - 'type': 'integer', - 'description': 'If data is older than this, it is not considered in the algorithm' - }, - 'reRouteEveryTicks': { - 'type': 'integer', - 'description': 'Check for a new route every x times after the car starts' - }, - # Add more properties as needed - }, - 'required': [ - 'routeRandomSigma', - 'explorationPercentage', - 'maxSpeedAndLengthFactor', - 'averageEdgeDurationFactor', - 'freshnessUpdateFactor', - 'freshnessCutOffValue', - 'reRouteEveryTicks' - ], + 'vehicle_count': 'number', + 'avg_trip_duration': 'number', + 'total_trips': 'number', + 'avg_trip_overhead': 'number' } return jsonify(schema) + +app.add_url_rule('/monitor_schema', view_func=MonitorSchemaAPI.as_view('monitor_schema')) + + class AdaptationOptionsSchemaAPI(MethodView): def get(self): schema = { @@ -138,7 +82,8 @@ def get(self): 'freshnessUpdateFactor': { 'type': 'integer', 'description': 'How much the freshness update factor influences the routing' - },'freshnessCutOffValue': { + }, + 'freshnessCutOffValue': { 'type': 'integer', 'description': 'If data is older than this, it is not considered in the algorithm' }, @@ -161,12 +106,8 @@ def get(self): return jsonify(schema) +app.add_url_rule('/adaptation_options_schema', view_func=AdaptationOptionsSchemaAPI.as_view('adaptation_options_schema')) + + if __name__ == '__main__': - # Registering the views - app.add_url_rule('/monitor', view_func=MonitorAPI.as_view('monitor_api')) - app.add_url_rule('/execute', view_func=ExecuteAPI.as_view('execute_api')) - app.add_url_rule('/adaptation_options', view_func=AdaptationOptionsAPI.as_view('adaptation_options_api')) - app.add_url_rule('/execute_schema', view_func=ExecuteSchemaAPI.as_view('execute_schema_api')) - app.add_url_rule('/adaptation_options_schema', view_func=AdaptationOptionsSchemaAPI.as_view('adaptation_options_schema_api')) - app.add_url_rule('/monitor_schema', view_func=MonitorSchemaAPI.as_view('monitor_schema_api')) - app.run(host='0.0.0.0', port=5000) + app.run(host='0.0.0.0') diff --git a/app/HTTPServer/monitor_data.json b/app/HTTPServer/monitor_data.json new file mode 100644 index 0000000..1439b13 --- /dev/null +++ b/app/HTTPServer/monitor_data.json @@ -0,0 +1,7 @@ +{ + "totalCarCounter":2, + "carIndexCounter": 1, + "totalTrips": 1, + "totalTripAverage": 4, + "totalTripOverheadAverage": 44 +} \ No newline at end of file diff --git a/app/HTTPServer/readme.md b/app/HTTPServer/readme.md index 76e4977..8e7686e 100644 --- a/app/HTTPServer/readme.md +++ b/app/HTTPServer/readme.md @@ -2,4 +2,10 @@ In order to run the HTTP server: pip install fastapi pip install "uvicorn[standard]" -python -m uvicorn main:app --reload \ No newline at end of file +python -m uvicorn main:app --reload + + +after building the docker image: + +docker run -p 3000:5000 -it --link kafka:kafka +"then access the port 3000" \ No newline at end of file From d6af5abf7a5f8b7979bc45af982e374602254e0a Mon Sep 17 00:00:00 2001 From: r0han0908 <150334840+r0han0908@users.noreply.github.com> Date: Fri, 22 Dec 2023 01:58:19 +0100 Subject: [PATCH 14/20] Add files via upload --- app/strategy.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 app/strategy.py diff --git a/app/strategy.py b/app/strategy.py new file mode 100644 index 0000000..f1c2ab7 --- /dev/null +++ b/app/strategy.py @@ -0,0 +1,49 @@ +import traci +import csv +from statistics import mean + +##need to implement this onto upisas + +class CrowdNavAdaptationStrategy: + def __init__(self, rerouting_threshold=0.4): + self.rerouting_threshold = rerouting_threshold + self.edge_density = {} + + def monitor(self): + #this should be retrived from the endpoints + for edge_id in traci.edge.getIDList(): + vehicle_ids = traci.edge.getLastStepVehicleIDs(edge_id) + density = len(vehicle_ids) + self.edge_density[edge_id] = density + + def analyze(self): + overloaded_streets = [] + for edge_id, density in self.edge_density.items(): + mean_density = mean(density) + if mean_density > self.rerouting_threshold: + overloaded_streets.append(edge_id) + return overloaded_streets + + def plan(self, overloaded_streets): + avoid_streets_signal = [] + for _ in range(traci.simulation.getDeltaT()): + signal_value = 0 if traci.simulation.getCurrentEdgeID() in overloaded_streets else 1 + avoid_streets_signal.append(signal_value) + return avoid_streets_signal + + def execute(self, avoid_streets_signal): + if 0 in avoid_streets_signal: + print("Sending signal to avoid overloaded streets!") + with open('signal.target', 'w') as signal_file: + signal_writer = csv.writer(signal_file, dialect='excel') + signal_writer.writerow(avoid_streets_signal) + + def update_knowledge_base(self): + # You can update the knowledge base based on the feedback from the simulation. + # This might involve adjusting thresholds, exploring different rerouting strategies, or updating other parameters. + pass + + +# Example usage +strategy = CrowdNavAdaptationStrategy() +strategy.run_strategy() From 1ef6db965302dffa1b0b86142c7a67b79ceeec35 Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Fri, 22 Dec 2023 02:01:14 +0100 Subject: [PATCH 15/20] Updated --- app/Boot.py | 1 + app/Config.py | 2 +- app/Strategy/strategy.py | 49 ++++++++++++++++++++++++++++++++++++ app/simulation/Simulation.py | 23 ++++------------- start.sh | 9 +++++++ 5 files changed, 65 insertions(+), 19 deletions(-) create mode 100644 app/Strategy/strategy.py create mode 100644 start.sh diff --git a/app/Boot.py b/app/Boot.py index 572a1b2..fe07f62 100644 --- a/app/Boot.py +++ b/app/Boot.py @@ -13,6 +13,7 @@ from app.sumo import SUMOConnector, SUMODependency from app import Config import traci, sys, os +#import thread import time diff --git a/app/Config.py b/app/Config.py index f7cc6fd..15dcae2 100644 --- a/app/Config.py +++ b/app/Config.py @@ -9,7 +9,7 @@ mqttUpdates = False mqttHost = "localhost" -mqttPort = "1883" #1883 +mqttPort = "1883" # the topic we send the kafka messages to kafkaTopicTrips = "crowd-nav-trips" diff --git a/app/Strategy/strategy.py b/app/Strategy/strategy.py new file mode 100644 index 0000000..f1c2ab7 --- /dev/null +++ b/app/Strategy/strategy.py @@ -0,0 +1,49 @@ +import traci +import csv +from statistics import mean + +##need to implement this onto upisas + +class CrowdNavAdaptationStrategy: + def __init__(self, rerouting_threshold=0.4): + self.rerouting_threshold = rerouting_threshold + self.edge_density = {} + + def monitor(self): + #this should be retrived from the endpoints + for edge_id in traci.edge.getIDList(): + vehicle_ids = traci.edge.getLastStepVehicleIDs(edge_id) + density = len(vehicle_ids) + self.edge_density[edge_id] = density + + def analyze(self): + overloaded_streets = [] + for edge_id, density in self.edge_density.items(): + mean_density = mean(density) + if mean_density > self.rerouting_threshold: + overloaded_streets.append(edge_id) + return overloaded_streets + + def plan(self, overloaded_streets): + avoid_streets_signal = [] + for _ in range(traci.simulation.getDeltaT()): + signal_value = 0 if traci.simulation.getCurrentEdgeID() in overloaded_streets else 1 + avoid_streets_signal.append(signal_value) + return avoid_streets_signal + + def execute(self, avoid_streets_signal): + if 0 in avoid_streets_signal: + print("Sending signal to avoid overloaded streets!") + with open('signal.target', 'w') as signal_file: + signal_writer = csv.writer(signal_file, dialect='excel') + signal_writer.writerow(avoid_streets_signal) + + def update_knowledge_base(self): + # You can update the knowledge base based on the feedback from the simulation. + # This might involve adjusting thresholds, exploring different rerouting strategies, or updating other parameters. + pass + + +# Example usage +strategy = CrowdNavAdaptationStrategy() +strategy.run_strategy() diff --git a/app/simulation/Simulation.py b/app/simulation/Simulation.py index 94db101..fd528b7 100644 --- a/app/simulation/Simulation.py +++ b/app/simulation/Simulation.py @@ -2,8 +2,6 @@ import traci import traci.constants as tc from app.network.Network import Network -from flask import Flask , jsonify , views -from app.HTTPServer.main import MonitorAPI, ExecuteAPI, AdaptationOptionsAPI, ExecuteSchemaAPI, AdaptationOptionsSchemaAPI from app.streaming import RTXForword from colorama import Fore @@ -23,7 +21,6 @@ class Simulation(object): """ here we run the simulation in """ - app = Flask(__name__) # the current tick of the simulation tick = 0 @@ -45,17 +42,6 @@ def applyFileConfig(cls): except: pass - @classmethod - def registerHTTPServer(cls): - # Register the views with the app - cls.app.add_url_rule('/monitor', view_func=MonitorAPI.as_view('monitor')) - cls.app.add_url_rule('/execute', view_func=ExecuteAPI.as_view('execute')) - cls.app.add_url_rule('/adaptation_options', view_func=AdaptationOptionsAPI.as_view('adaptation_options')) - cls.app.add_url_rule('/execute_schema', view_func=ExecuteSchemaAPI.as_view('execute_schema')) - cls.app.add_url_rule('/adaptation_options_schema', view_func=AdaptationOptionsSchemaAPI.as_view('adaptation_options_schema')) - cls.app.run(host='0.0.0.0', port=5000) - - @classmethod def start(cls): """ start the simulation """ @@ -63,7 +49,6 @@ def start(cls): # apply the configuration from the json file cls.applyFileConfig() CarRegistry.applyCarCounter() - cls.registerHTTPServer() cls.loop() @classmethod @@ -151,17 +136,19 @@ def loop(cls): CarRegistry.totalTripAverage) + "(" + str( CarRegistry.totalTrips) + ")" + " # avgTripOverhead: " + str( CarRegistry.totalTripOverheadAverage)) - file_path = "./monitor_data.json" + + # Write monitoring data to json file + file_path = "app/HTTPServer/monitor_data.json" data = { + 'step': str(Config.processID), + 'currentCars': traci.vehicle.getIDCount(), 'totalCarCounter': CarRegistry.totalCarCounter, 'carIndexCounter': CarRegistry.carIndexCounter, 'totalTrips': CarRegistry.totalTrips, 'totalTripAverage': CarRegistry.totalTripAverage, 'totalTripOverheadAverage': CarRegistry.totalTripOverheadAverage } - # Open the file in write mode ('w') with open(file_path, 'w') as json_file: - # Use json.dump() to write data to the file json.dump(data, json_file) diff --git a/start.sh b/start.sh new file mode 100644 index 0000000..dd5c07b --- /dev/null +++ b/start.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# cd /app/HTTPServer +echo "Docker started." +python forever.py & + +cd /app/app/HTTPServer + +python main.py \ No newline at end of file From 1c10297f54ba4f7572ae3b655254542dffbcaed5 Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Mon, 5 Feb 2024 12:07:30 +0100 Subject: [PATCH 16/20] Added Docker Compose file --- docker-compose.yml | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 2d04a15..db2f2e9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,20 +1,32 @@ version: '3' services: - flask-app: + upisas: build: - context: . - ports: - - "5000:5000" - command: python /app/HTTPServer/main.py - network_mode: host - depends_on: - - kafka + context: ./Dockerfile # Path to Crowdnav Dockerfile + networks: + - mynetwork + + crowdnav: + build: + context: Desktop/UPISAS-students/Dockerfile # Path to UPISAS Dockerfile + networks: + - mynetwork kafka: - image: newcrowdnav:latest + image: spotify/kafka + ports: + - "9092:9092" environment: - KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092,OUTSIDE://localhost:9092 + ADVERTISED_LISTENER: INSIDE://kafka:9092,OUTSIDE://localhost:9092 + LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT KAFKA_LISTENERS: INSIDE://0.0.0.0:9092,OUTSIDE://0.0.0.0:9092 - KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE \ No newline at end of file + KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092,OUTSIDE://localhost:9092 + KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE + KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 + networks: + - mynetwork + +networks: + mynetwork: From 8b4a22beaf414ee34e1a2617a9395d8510911a01 Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Tue, 6 Feb 2024 14:24:21 +0100 Subject: [PATCH 17/20] Changes in docker-compose --- docker-compose.yml | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index db2f2e9..5355cb4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,32 +1,11 @@ version: '3' - services: - upisas: - build: - context: ./Dockerfile # Path to Crowdnav Dockerfile - networks: - - mynetwork - - crowdnav: - build: - context: Desktop/UPISAS-students/Dockerfile # Path to UPISAS Dockerfile - networks: - - mynetwork - + app: + image: crowdnav:latest #Image name change it accordingly + depends_on: + - Upisas + - kafka + Upisas: + image: upisasstudents:latest #Image name kafka: - image: spotify/kafka - ports: - - "9092:9092" - environment: - ADVERTISED_LISTENER: INSIDE://kafka:9092,OUTSIDE://localhost:9092 - LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT - KAFKA_LISTENERS: INSIDE://0.0.0.0:9092,OUTSIDE://0.0.0.0:9092 - KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092,OUTSIDE://localhost:9092 - KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE - KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 - networks: - - mynetwork - -networks: - mynetwork: + image: spotify/kafka:latest #image name From 0da0e9724cf013a900311bbf1e26c0299c071477 Mon Sep 17 00:00:00 2001 From: yoBoyio Date: Sat, 10 Feb 2024 01:31:35 +0100 Subject: [PATCH 18/20] fix:file paths and container structure --- Dockerfile | 2 +- app/HTTPServer/endpoints.py | 2 +- app/HTTPServer/helpers/__pycache__/main.py | 23 ----------------- app/HTTPServer/main.py | 2 +- app/simulation/monitor_data.json | 7 ----- app/simulation/views.py | 30 ---------------------- start.sh | 6 +---- 7 files changed, 4 insertions(+), 68 deletions(-) delete mode 100644 app/HTTPServer/helpers/__pycache__/main.py delete mode 100644 app/simulation/monitor_data.json delete mode 100644 app/simulation/views.py diff --git a/Dockerfile b/Dockerfile index acd0cbb..2977a89 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM starofall/crowdnav -COPY . . +ADD ./ /app/ # WORKDIR /app diff --git a/app/HTTPServer/endpoints.py b/app/HTTPServer/endpoints.py index c032f85..3bc20a6 100644 --- a/app/HTTPServer/endpoints.py +++ b/app/HTTPServer/endpoints.py @@ -18,7 +18,7 @@ def get_monitor(): # Construct the path to the knobs.json file, assuming it's two directories back -json_file_path = '../../knobs.json' +json_file_path = './knobs.json' # Open the JSON file in read mode ('r') with open(json_file_path, 'r') as json_file: diff --git a/app/HTTPServer/helpers/__pycache__/main.py b/app/HTTPServer/helpers/__pycache__/main.py deleted file mode 100644 index b54e674..0000000 --- a/app/HTTPServer/helpers/__pycache__/main.py +++ /dev/null @@ -1,23 +0,0 @@ -from flask import jsonify - -def getMonitor(): - # Specify the file path - file_path = "./monitor_data.json" - - try: - # Open the file in read mode ('r') - with open(file_path, 'r') as json_file: - # Use json.load() to read data from the file - data = json.load(json_file) - - # Now 'data' contains the contents of the JSON file as a Python dictionary - return jsonify(data) - - except FileNotFoundError: - # Return a 404 Not Found response if the file is not found - return jsonify({"error": "Monitor data not found"}), 404 - - except Exception as e: - # Handle other exceptions and return a 500 Internal Server Error response - return jsonify({"error": str(e)}), 500 - diff --git a/app/HTTPServer/main.py b/app/HTTPServer/main.py index d013b8b..7a16280 100644 --- a/app/HTTPServer/main.py +++ b/app/HTTPServer/main.py @@ -27,7 +27,7 @@ def write_knobs(data): class MonitorAPI(MethodView): def get(self): try: - file_path = "./monitor_data.json" + file_path = "app/HTTPServer/monitor_data.json" with open(file_path, "r") as json_file: data = json.load(json_file) return jsonify(data) diff --git a/app/simulation/monitor_data.json b/app/simulation/monitor_data.json deleted file mode 100644 index 2fc45b7..0000000 --- a/app/simulation/monitor_data.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "totalCarCounter": 100, - "carIndexCounter": 4, - "totalTrips": 45, - "totalTripAverage": 4, - "totalTripOverheadAverage": 20 -} \ No newline at end of file diff --git a/app/simulation/views.py b/app/simulation/views.py deleted file mode 100644 index 60ebf69..0000000 --- a/app/simulation/views.py +++ /dev/null @@ -1,30 +0,0 @@ -from flask import jsonify -from flask.views import MethodView -# from endpoints import getAdaptationOptions, getexecute -import json - -class MonitorAPI(MethodView): - def get(self): - file_path = "./monitor_data.json" - with open(file_path, "r") as json_file: - data = json.load(json_file) - return jsonify(data) - -class ExecuteAPI(MethodView): - def put(self): - # data = getexecute() - return jsonify({"execute_schema": "This is /execute_schema endpoint"}) - -class AdaptationOptionsAPI(MethodView): - def get(self): - # data = getAdaptationOptions() - return jsonify({"AdaptationOptionsAPI": "This is /AdaptationOptionsAPI endpoint"}) - -class ExecuteSchemaAPI(MethodView): - def get(self): - return jsonify({"execute_schema": "This is /execute_schema endpoint"}) - -class AdaptationOptionsSchemaAPI(MethodView): - def get(self): - return jsonify({"adaptation_options_schema": "This is /adaptation_options_schema endpoint"}) - diff --git a/start.sh b/start.sh index dd5c07b..5fbc556 100644 --- a/start.sh +++ b/start.sh @@ -1,9 +1,5 @@ #!/bin/bash -# cd /app/HTTPServer echo "Docker started." python forever.py & - -cd /app/app/HTTPServer - -python main.py \ No newline at end of file +python /app/app/HTTPServer/main.py \ No newline at end of file From 7cbdc4d706dddc6942415251111158a66dea7043 Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Mon, 12 Feb 2024 00:44:36 +0100 Subject: [PATCH 19/20] Made changes to the Simulation.py --- app/simulation/Simulation.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/app/simulation/Simulation.py b/app/simulation/Simulation.py index fd528b7..0416e76 100644 --- a/app/simulation/Simulation.py +++ b/app/simulation/Simulation.py @@ -11,7 +11,7 @@ from app.logging import info from app.routing.CustomRouter import CustomRouter from app.streaming import RTXConnector -import time +import time , random # get the current system time from app.routing.RoutingEdge import RoutingEdge @@ -25,6 +25,8 @@ class Simulation(object): # the current tick of the simulation tick = 0 + edge_density = {} + # last tick time lastTick = current_milli_time() @@ -32,7 +34,7 @@ class Simulation(object): def applyFileConfig(cls): """ reads configs from a json and applies it at realtime to the simulation """ try: - config = json.load(open('./knobs.json')) + config = json.load(open('../../knobs.json')) CustomRouter.explorationPercentage = config['explorationPercentage'] CustomRouter.averageEdgeDurationFactor = config['averageEdgeDurationFactor'] CustomRouter.maxSpeedAndLengthFactor = config['maxSpeedAndLengthFactor'] @@ -50,7 +52,18 @@ def start(cls): cls.applyFileConfig() CarRegistry.applyCarCounter() cls.loop() - + + + ##Find's the density on the first 30 Edges{For Demonstartion Purpose, you can delete the } + @classmethod + def monitor_edge_density(cls): + """ Monitor and update the density of vehicles on specific edges """ + cls.edge_density.clear() # Clear the existing data + edge_ids = traci.edge.getIDList()[:30] # Get the first 30 edge IDs + for edge_id in edge_ids: + density = traci.edge.getLastStepVehicleNumber(edge_id) + cls.edge_density[edge_id] = density + @classmethod # @profile def loop(cls): @@ -69,7 +82,7 @@ def loop(cls): msg = dict() msg["duration"] = duration RTXForword.publish(msg, Config.kafkaTopicPerformance) - + # Check for removed cars and re-add them into the system for removedCarId in traci.simulation.getSubscriptionResults()[122]: CarRegistry.findById(removedCarId).setArrived(cls.tick) @@ -81,6 +94,9 @@ def loop(cls): msg = dict() msg["duration"] = current_milli_time() - timeBeforeCarProcess RTXForword.publish(msg, Config.kafkaTopicRouting) + + # Monitor vehicle density for each edge + cls.monitor_edge_density() # if we enable this we get debug information in the sumo-gui using global traveltime # should not be used for normal running, just for debugging @@ -127,21 +143,26 @@ def loop(cls): if "edge_average_influence" in newConf: RoutingEdge.edgeAverageInfluence = newConf["edge_average_influence"] print("setting edgeAverageInfluence: " + str(newConf["edge_average_influence"])) + # print status update if we are not running in parallel mode if (cls.tick % 100) == 0 and Config.parallelMode is False: print(str(Config.processID) + " -> Step:" + str(cls.tick) + " # Driving cars: " + str( - traci.vehicle.getIDCount()) + "/" + str( + traci.vehicle.getIDCount()) + "EdgeID" + str(random.choice(traci.edge.getIDList()[:30]))+ + "EdgeDensity" + str(cls.monitor_edge_density()) +"/" + str( CarRegistry.totalCarCounter) + " # avgTripDuration: " + str( CarRegistry.totalTripAverage) + "(" + str( CarRegistry.totalTrips) + ")" + " # avgTripOverhead: " + str( CarRegistry.totalTripOverheadAverage)) - + + # Write monitoring data to json file file_path = "app/HTTPServer/monitor_data.json" data = { 'step': str(Config.processID), 'currentCars': traci.vehicle.getIDCount(), + 'EdgeID': random.choice(traci.edge.getIDList()[:30]), + 'EdgeDensity': cls.monitor_edge_density(), 'totalCarCounter': CarRegistry.totalCarCounter, 'carIndexCounter': CarRegistry.carIndexCounter, 'totalTrips': CarRegistry.totalTrips, From 6dc7f0f1ebad5d99ed6b9f4c46554f5d8c419b81 Mon Sep 17 00:00:00 2001 From: Rohan Nair Date: Mon, 12 Feb 2024 00:45:14 +0100 Subject: [PATCH 20/20] Updated JSON --- app/HTTPServer/monitor_data.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/HTTPServer/monitor_data.json b/app/HTTPServer/monitor_data.json index 1439b13..8972566 100644 --- a/app/HTTPServer/monitor_data.json +++ b/app/HTTPServer/monitor_data.json @@ -1,4 +1,11 @@ { + "step":1, + "EdgeID": 2, + "EdgeDensity":{ + "edge1": 10, + "edge2": 8, + "edge3": 15 + }, "totalCarCounter":2, "carIndexCounter": 1, "totalTrips": 1,