Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

samuel-ng: Add all used datasets and Notebook #12

Open
wants to merge 49 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e800cfb
Updated files to yulin-zhuang
YoriMaster Aug 7, 2024
adbcdc2
hue-minh-nguyen: Create a python function to calculate % battery cons…
nghminh2002 Aug 10, 2024
9ce056e
Add files via upload
ebi-benny Aug 11, 2024
2792319
Add files via upload
Bgoutham-krishna Aug 11, 2024
a04c4ad
DRAFTV1.0 Documentation
JCS360 Aug 13, 2024
f34e65f
Add dataset of available EV in AU & US, and dataset of electricity pr…
noob2cook Aug 13, 2024
57d72ab
Mychargingstationfile
nouman392 Aug 14, 2024
90d3317
nouman ali: write a python function to extract valuable data
nouman392 Aug 14, 2024
02431e4
Add files via upload
surajrnair Aug 23, 2024
3ece57f
Add files via upload
ajayofficial1998 Aug 25, 2024
3876d54
Add files via upload
Jaskaranvir7 Aug 25, 2024
202c095
hue-minh-nguyen: set up backend codebase with API to add favourite st…
nghminh2002 Sep 1, 2024
6dec5b2
hue-minh-nguyen: delete unnecessary file
nghminh2002 Sep 1, 2024
2df2aa9
Merge pull request #17 from Chameleon-company/ajayofficial1998-patch-1
Jaskaranvir7 Sep 3, 2024
72c2a2b
Updated Code
nouman392 Sep 3, 2024
77b4e38
hue-minh-nguyen: update code with new db url and fix bugs
nghminh2002 Sep 7, 2024
9cf8d24
hue-minh-nguyen: build docker
nghminh2002 Sep 7, 2024
b8f0907
Cost Analysis of EV charging Station
nouman392 Sep 10, 2024
57d2c21
Merge pull request #22 from Chameleon-company/hue-minh-nguyen/set-up-…
nghminh2002 Sep 14, 2024
df13d17
Merge pull request #14 from Chameleon-company/surajrnair-patch-1
nghminh2002 Sep 14, 2024
b58a83b
Merge pull request #7 from Chameleon-company/ebi-benny-patch-1
nghminh2002 Sep 14, 2024
9dad756
Merge pull request #1 from Chameleon-company/YoriMaster-patch-1
chanshut Sep 15, 2024
90bdda2
hue-minh-nguyen: get nearest station api
nghminh2002 Sep 15, 2024
5eb788b
hue-minh-nguyen: fix bugs
nghminh2002 Sep 15, 2024
c76d942
feat: create ci yml
nghminh2002 Sep 16, 2024
ffc617b
Merge pull request #27 from Chameleon-company/nghminh2002-patch-1
nghminh2002 Sep 16, 2024
0c36a2a
hue-minh-nguyen: ci/cd
nghminh2002 Sep 16, 2024
05ab7b6
Merge pull request #25 from Chameleon-company/hue-minh-nguyen/get-nea…
nghminh2002 Sep 16, 2024
66e5ec9
hue-minh-nguyen: ci/cd
nghminh2002 Sep 16, 2024
7216834
Merge pull request #28 from Chameleon-company/hue-minh-nguyen/ci-cd
nghminh2002 Sep 16, 2024
6e3b881
hue-minh-nguyen: ci/cd
nghminh2002 Sep 17, 2024
ae8557d
Merge pull request #18 from Chameleon-company/Jaskaranvir7-patch-1
Jaskaranvir7 Sep 17, 2024
7d10a11
final file with exploratory data analysis
Jaskaranvir7 Sep 17, 2024
9e6db53
hue-minh-nguyen-update-ci (#31)
nghminh2002 Sep 17, 2024
b9d11e1
Merge pull request #9 from Chameleon-company/Bgoutham-krishna
jamesdaviesdeveloper Sep 17, 2024
16a5af1
Merge pull request #11 from Chameleon-company/john-collins-documentation
jamesdaviesdeveloper Sep 17, 2024
26a949c
Batch function to extract EV station data
Bgoutham-krishna Sep 17, 2024
3fc6585
Machine learning models to predict the operational status and cost
Bgoutham-krishna Sep 17, 2024
716a1c6
Function to find nearest charging station
Bgoutham-krishna Sep 17, 2024
d38be3c
Merge pull request #32 from Bgoutham-krishna/main
Bgoutham-krishna Sep 17, 2024
5bff3f9
Update Charging_Station_Analysis_Using_Machine_Learning.ipynb
Bgoutham-krishna Sep 17, 2024
b2f8cdd
Delete personal-work/goutham-bala-murali-krishna directory
Bgoutham-krishna Sep 17, 2024
e48310d
Create goutham-bala-murali-krishna
Bgoutham-krishna Sep 17, 2024
500d908
Delete personal-work/goutham-bala-murali-krishna
Bgoutham-krishna Sep 17, 2024
28acbd2
Merge pull request #13 from Chameleon-company/Nouman_ali
nouman392 Sep 17, 2024
9e10761
hue-minh-nguyen-ci-cd-update-env (#33)
nghminh2002 Sep 17, 2024
ef11317
hue-minh-nguyen: create new folder for goutham (#35)
nghminh2002 Sep 17, 2024
027fb01
Added all datasets and notebook I worked
noob2cook Sep 18, 2024
1c45c52
Merge remote-tracking branch 'origin/samuel-ng' into samuel-ng
noob2cook Sep 18, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: CI

on:
push:
branches:
- main
pull_request:
branches:
- main
# Build and Deploy
jobs:
build-production:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Login to docker hub
uses: docker/login-action@v3
with:
username: ${{secrets.CI_DOCKER_USERNAME}}
password: ${{secrets.CI_DOCKER_PASSWORD}}

- name: Build the docker image
run: |
ls -la
docker build . -f Dockerfile -t ${{ secrets.CI_DOCKER_USERNAME }}/${{ secrets.APP_NAME }}:${{ github.sha }}

- name: Push the docker image
run: |
docker push ${{ secrets.CI_DOCKER_USERNAME }}/${{ secrets.APP_NAME }}:${{ github.sha }}

deploy-production:
runs-on: ubuntu-latest
needs: build-production

steps:
- name: Deploy to Production
uses: appleboy/ssh-action@v0.1.7
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.USER_NAME }}
key: ${{ secrets.SERVER_PROD_KEY }}
script: |
echo '${{ secrets.CI_DOCKER_PASSWORD }}' | sudo docker login --username '${{ secrets.CI_DOCKER_USERNAME }}' --password-stdin;
sudo docker stop '${{ secrets.APP_NAME }}';
sudo docker rm '${{ secrets.APP_NAME }}';
sudo docker pull '${{ secrets.CI_DOCKER_USERNAME }}'/'${{ secrets.APP_NAME }}':'${{ github.sha }}';
sudo docker run -d -p 5000:5000 --name "${{ secrets.APP_NAME }}" -e GOOGLE_MAP_API_KEY="${{ secrets.GOOGLE_MAP_API_KEY }}" -e DATABASE_URL="${{ secrets.DATABASE_URL }}" "${{ secrets.CI_DOCKER_USERNAME }}"/"${{ secrets.APP_NAME }}":"${{ github.sha }}";
sudo docker system prune -a -f;
sudo docker logout;

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.venv/
__pycache__
.env
28 changes: 28 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FROM python:3.12.3

# Set the working directory
WORKDIR /main

# Copy the requirements file from 'main'
COPY ./main/requirements.txt /main/requirements.txt

# Install the dependencies
RUN pip install --no-cache-dir --upgrade -r /main/requirements.txt

# Copy the application code from the 'main/app' directory
# COPY ./main/app /main/app
COPY ./main /main

# # Copy the run.py script
# COPY ./main/run.py /main/run.py

# Set environment variables
ENV FLASK_APP=run.py
ENV FLASK_RUN_HOST=0.0.0.0
ENV FLASK_RUN_PORT=5000

# Expose port 5000
EXPOSE 5000

# Define the default command (assuming you want to run run.py)
CMD ["flask", "run"]
33 changes: 33 additions & 0 deletions main/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from flask import Flask
from pymongo import MongoClient
from app.models.station import Station
from app.models.user import User
from app.controllers.station_controller import station_controller
from app.controllers.user_controller import user_controller
from dotenv import load_dotenv
import os

def create_app():
app = Flask(__name__)

# Load environment variables from .env file
load_dotenv()

# Access environment variables
app.config['GOOGLE_MAP_API_KEY'] = os.getenv('GOOGLE_MAP_API_KEY')
app.config['DATABASE_URL'] = os.getenv('DATABASE_URL')

# Set up MongoDB connection
client = MongoClient(app.config['DATABASE_URL'], tls=True, tlsAllowInvalidCertificates=True)

db = client['EVAT']

# Initialize the models
app.charging_stations = Station(db)
app.users = User(db)

# Register the controller blueprints
app.register_blueprint(station_controller)
app.register_blueprint(user_controller)

return app
77 changes: 77 additions & 0 deletions main/app/controllers/station_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from flask import Blueprint, request, jsonify, current_app
from app.services.station_service import StationService
import requests
import os

station_controller = Blueprint('station_controller', __name__)

@station_controller.route('/stations', methods=['GET'])
def get_stations():
page = int(request.args.get('page', 1))
size = int(request.args.get('size', 10))

station_service = StationService(current_app.charging_stations)
stations = station_service.get_stations(page, size)

return jsonify(stations), 200

@station_controller.route('/nearest_station', methods=['GET'])
def nearest_station():
GOOGLE_MAP_API_KEY = os.getenv('GOOGLE_MAP_API_KEY')
# Fetch user location via Geolocation API
geo_url = f'https://www.googleapis.com/geolocation/v1/geolocate?key={GOOGLE_MAP_API_KEY}'
geo_response = requests.post(geo_url, json={})

if geo_response.status_code != 200:
return jsonify({'error': 'Unable to fetch user location'}), 500

location_data = geo_response.json()
user_lat = location_data['location']['lat']
user_lng = location_data['location']['lng']

# Get the threshold from query parameters (default to 0.1 if not provided)
threshold = request.args.get('threshold', default=0.1, type=float)

# Find nearest charging stations using MongoDB geospatial query with the threshold
station_service = StationService(current_app.charging_stations)
nearest_stations = station_service.get_nearest_station(user_lat, user_lng, threshold)

if not nearest_stations:
return jsonify({'error': 'No charging stations found nearby'}), 404

# Calculate distance using Google Distance Matrix API
distance_matrix_url = 'https://maps.googleapis.com/maps/api/distancematrix/json'

# Iterate through nearest stations and calculate distance for each
station_distances = []
for station in nearest_stations:
station_lat = station['latitude']
station_lng = station['longitude']

# Prepare API parameters
params = {
'origins': f"{user_lat},{user_lng}",
'destinations': f"{station_lat},{station_lng}",
'key': GOOGLE_MAP_API_KEY
}

# Send request to Google Distance Matrix API
distance_response = requests.get(distance_matrix_url, params=params)

if distance_response.status_code != 200:
return jsonify({'error': 'Unable to calculate distance for station'}), 500

# Parse distance data
distance_data = distance_response.json()
distance_info = distance_data['rows'][0]['elements'][0]

# Append station info with distance details
station_distances.append({
'station_info': station,
'distance_text': distance_info['distance']['text'],
'distance_exact_value': distance_info['distance']['value'], # Distance in meters
'duration': distance_info['duration']['text']
})

# Return the list of stations with distance info
return jsonify(station_distances)
56 changes: 56 additions & 0 deletions main/app/controllers/user_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from flask import Blueprint, request, jsonify, current_app
from app.services.user_service import UserService

user_controller = Blueprint('user_controller', __name__)

@user_controller.route('/users', methods=['POST'])
def add_user():
data = request.json
username = data.get('username')
password = data.get('password')

try:
user_service = UserService(current_app.users, current_app.charging_stations)
user_id = user_service.add_user(username, password)
return jsonify({"message": f"User '{username}' added", "id": str(user_id)}), 201
except ValueError as e:
return jsonify({"error": str(e)}), 400

@user_controller.route('/users', methods=['GET'])
def get_users():
user_service = UserService(current_app.users, current_app.charging_stations)
users = user_service.get_users()
return jsonify(users), 200

@user_controller.route('/users/<user_id>/favorites', methods=['POST'])
def add_favorite_station(user_id):
data = request.json
station_id = data.get('station_id')

try:
user_service = UserService(current_app.users, current_app.charging_stations)
user_service.add_favorite_station(user_id, station_id)
return jsonify({"message": f"Station '{station_id}' added to favorites"}), 201
except ValueError as e:
return jsonify({"error": str(e)}), 400

@user_controller.route('/users/<user_id>/favorites', methods=['DELETE'])
def remove_favorite_station(user_id):
data = request.json
station_id = data.get('station_id')

try:
user_service = UserService(current_app.users, current_app.charging_stations)
user_service.remove_favorite_station(user_id, station_id)
return jsonify({"message": f"Station '{station_id}' removed from favorites"}), 200
except ValueError as e:
return jsonify({"error": str(e)}), 400

@user_controller.route('/users/<user_id>/favorites', methods=['GET'])
def get_favorite_stations(user_id):
try:
user_service = UserService(current_app.users, current_app.charging_stations)
stations = user_service.get_favorite_stations(user_id)
return jsonify(stations), 200
except ValueError as e:
return jsonify({"error": str(e)}), 400
51 changes: 51 additions & 0 deletions main/app/models/station.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from pymongo import MongoClient, GEOSPHERE
from bson import ObjectId

class Station:
def __init__(self, db):
self.collection = db['charging_stations']
self.collection.create_index([("location", GEOSPHERE)])

def to_dict(self, station):
return {
"id": str(station["_id"]),
"cost": station["cost"],
"charging_points": station["charging_points"],
"pay_at_location": station["pay_at_location"],
"membership_required": station["membership_required"],
"access_key_required": station["access_key_required"],
"is_operational": station["is_operational"],
"latitude": station["latitude"],
"longitude": station["longitude"],
"operator": station["operator"],
"connection_type": station["connection_type"],
"current_type": station["current_type"],
"charging_points_flag": station["charging_points_flag"]
}

def find_all(self, page, size):
offset = (page - 1) * size
return list(self.collection.find().skip(offset).limit(size))

def find_by_id(self, station_id):
return self.collection.find_one({"_id": ObjectId(station_id)})

def find_nearest(self, user_lat, user_lng, threshold):
nearest_stations = self.collection.find({
"$expr": {
"$lt": [
{
"$sqrt": {
"$add": [
{ "$pow": [{ "$subtract": ["$longitude", user_lng] }, 2] },
{ "$pow": [{ "$subtract": ["$latitude", user_lat] }, 2] }
]
}
},
threshold
]
}
})

nearest_stations = [self.to_dict(station) for station in nearest_stations]
return nearest_stations if nearest_stations else None
44 changes: 44 additions & 0 deletions main/app/models/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from pymongo import MongoClient
from bson import ObjectId

class User:
def __init__(self, db):
self.collection = db['users']

def to_dict(self, user):
return {
"id": str(user["_id"]),
"username": user["username"],
"make": user.get("make", ""),
"model": user.get("model", ""),
"variant": user.get("variant", ""),
"connection_type": user.get("connection_type", ""),
"favorite_stations": user["favorite_stations"]
}

def find_all(self):
return list(self.collection.find())

def find_by_id(self, user_id):
return self.collection.find_one({"_id": ObjectId(user_id)})

def insert(self, username, password):
user = {
"username": username,
"password": password,
"favorite_stations": []
}
result = self.collection.insert_one(user)
return result.inserted_id

def add_favorite_station(self, user_id, station_id):
return self.collection.update_one(
{"_id": ObjectId(user_id)},
{"$push": {"favorite_stations": station_id}}
)

def remove_favorite_station(self, user_id, station_id):
return self.collection.update_one(
{"_id": ObjectId(user_id)},
{"$pull": {"favorite_stations": station_id}}
)
11 changes: 11 additions & 0 deletions main/app/services/station_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class StationService:
def __init__(self, charging_stations):
self.charging_stations = charging_stations

def get_stations(self, page, size):
stations = self.charging_stations.find_all(page, size)
return [self.charging_stations.to_dict(station) for station in stations]

def get_nearest_station(self, latitude, longitude, threshold):
stations = self.charging_stations.find_nearest(latitude, longitude, threshold)
return stations
Loading
Loading