15 Commits
Author SHA1 Message Date
[email protected] 0d55d9e9de fix things, thread loop 2024-09-15 22:50:22 -04:00
Mathieu Moran 7fbd427516 Merge pull request #1 from quoije/main
working branch
2024-09-15 21:25:49 -04:00
[email protected] f087478736 fix things, some things should work 2024-09-15 21:21:39 -04:00
Mathieu Moran 646bdd32b5 delete __pycache__ directory 2024-04-02 19:53:37 -04:00
quoije ada68ed6ac wip sql 2024-04-01 21:29:12 -04:00
quoije 286649e9c3 restructure 2024-04-01 20:21:52 -04:00
quoije 792c170fd6 first tsv commit 2024-04-01 12:52:27 -04:00
quoije c4c10972a1 add raw to tsv, mangodb first commit, restructure 2024-04-01 11:37:13 -04:00
quoije bdf6bb477b add gps function 2024-03-17 22:37:25 -04:00
quoije 4bc184fcdf rm temp files 2024-03-09 15:44:57 -05:00
quoije 5e8e3cf603 put prod server 2024-03-09 15:37:12 -05:00
quoije 651c798d3a test inputs 2024-03-02 13:40:52 -05:00
Mathieu Moran e9f204d6bd loopy loop, doesn't work, too many loops 2023-11-28 23:04:06 -05:00
Mathieu Moran 9aa32584e6 add readme.md 2023-11-18 14:11:19 -05:00
Mathieu Moran 698adee415 add ui pics for readme 2023-11-18 14:08:04 -05:00
30 changed files with 9987 additions and 9867 deletions
+25 -18
View File
@@ -1,21 +1,33 @@
import app_obd, app_car, app_account, time, app_events, threading
from flask import Flask, render_template, make_response, json from flask import Flask, render_template, make_response, json
from app_events import socketio from modules import app_gps, app_events, app_car, app_account, app_gps,app_obd
import time
from gevent.pywsgi import WSGIServer
port_number = 8000
app = Flask(__name__) app = Flask(__name__)
app_events.socketio.init_app(app)
account = app_account.Account()
obd = app_obd.OBD()
car = app_car.Car()
gps = app_gps.get_gps()
@app.route('/') @app.route('/')
def index(): def index():
print("hello") print("hello "+ account.name)
return render_template('index.html') print("you're car model is:" + car.model)
return render_template('index.html', account = account, car = car)
@app.route('/dtc') @app.route('/dtc')
def dtc(): def dtc():
return render_template('dtc.html') return render_template('dtc.html', account = account, car = car)
@app.route('/dash')
def dash():
return render_template('dash.html', account = account, car = car)
# not sure if im gonna use this # not sure if im gonna use this
@app.route('/api/obd_speed') @app.route('/api/obd_speed/')
def data(): def data():
data = app_obd.speed data = app_obd.speed
response = make_response(json.dumps(data)) response = make_response(json.dumps(data))
@@ -23,15 +35,10 @@ def data():
return response return response
if __name__ == '__main__': if __name__ == '__main__':
socketio.init_app(app) # Debug/Development
# app.run(debug=True, host="0.0.0.0", port="5000")
# Production
http_server = WSGIServer(('', 5000), app)
print("server on http://localhost:5000")
http_server.serve_forever()
p_obd_connection = threading.Thread(target=app_obd.obd_connection)
p_obd_connection.start()
print("allo?")
##
## only debug, remove in prod
##
app.run(host='localhost', port=port_number)
##
-18
View File
@@ -1,18 +0,0 @@
import app_car as Car
import threading, app_events
from threading import Thread
socketio = app_events.SocketIO()
account_name = "quoije"
account_pp_image = "static\img\image.png"
account_car = Car
account_car.model = "YARIS"
account_lock = threading.Lock()
class Account:
def __init__(self):
self.name = account_name
self.pp_image = account_pp_image
self.car = account_car
def info():
return [name, pp_image, car.model]
-3
View File
@@ -1,3 +0,0 @@
class Car:
def __init__(self):
self.model = None
-44
View File
@@ -1,44 +0,0 @@
from flask_socketio import SocketIO
from threading import Thread
import app_obd, app_account, time, threading
socketio = SocketIO()
uptime_lock = threading.Lock()
os_type = ["Linux","Windows"]
@socketio.on('connect')
def connect_event():
print('Client connected')
print('Getting OBD status...')
uptime()
def uptime():
thread = Thread(target=loop_uptime(os_type[1]))
thread.daemon = True
thread.start()
def loop_uptime(os):
loop = True
uptime_lock.acquire()
if os == "Linux":
try:
while loop == True:
boottime = time.clock_gettime(time.CLOCK_BOOTTIME)
# Convert to hours, minutes, and seconds
seconds = int(boottime)
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
time.sleep(1)
uptime = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
socketio.emit("rpi_uptime", uptime)
finally:
uptime_lock.release()
elif os == "Windows":
while loop == True:
time.sleep(1)
socketio.emit("rpi_uptime", "1")
-148
View File
@@ -1,148 +0,0 @@
import obd, time, threading
from datetime import datetime
from app_events import socketio
from threading import Thread
status = None
speed = 0
rpm = 0
coonnection = None
class OBD:
def __init__(self):
self.status = status
self.rpm = rpm
self.speed = speed
obd_status = ["Disconnected", "Connected", "Connection...", "wtf"]
obd_speed_lock = threading.Lock()
obd_rpm_lock = threading.Lock()
obd_dtc_lock = threading.Lock()
obd_state_lock = threading.Lock()
def get_speedtime():
global speed
date = datetime.now()
today = str(date.today())
time_now = str(date.strftime("%H:%M:%S"))
return [str(time_now), speed]
def obd_connection():
global connection
try:
print(obd_status[2])
connection = obd.OBD() # put linux /dev/rfi... something in () for the rpi bluetooth adpater
except Exception as e:
print("An error occurred:", str(e))
if connection.is_connected():
print(obd_status[1])
print("OBD connection established.")
obd_events(1)
else:
print("OBD connection failed.")
print(obd_status[0])
obd_events(2)
@socketio.on('obd')
def obd_events(status):
if status == 1:
thread_speed = Thread(target=obd_state(1))
thread_speed.daemon = True
thread_speed.start()
elif status == 2:
thread_speed = Thread(target=obd_state(2))
thread_speed.daemon = True
thread_speed.start()
# debug speed for testing
thread_speed = Thread(target=obd_speed)
thread_speed.daemon = True
thread_speed.start()
# debug rpm for testing
thread_rpm = Thread(target=obd_rpm)
thread_rpm.daemon = True
thread_rpm.start()
else:
thread_speed = Thread(target=obd_state(0))
thread_speed.daemon = True
thread_speed.start()
def obd_state(status):
obd_state_lock.acquire()
loop = True
try:
while loop == True:
print(obd_status[status])
socketio.emit('obd_status', obd_status[status])
time.sleep(2)
finally:
obd_state_lock.release()
def obd_speed():
obd_speed_lock.acquire()
cmd = obd.commands.SPEED # select an OBD command (sensor)
response = connection.query(cmd) # send the command and parse the response
loop = True
try:
while loop == True:
print(obd_status[3])
socketio.emit('obd_status', obd_status[3])
global speed
speed = speed + 1
time.sleep(1)
if response.is_null():
print("No data received. #"+ str(get_speedtime()))
socketio.emit('obd_speed', get_speedtime())
else:
print("Original value:", response.value)
print("Value in kph:", response.value.to("kph"))
socketio.emit('obd_speed', response.value.to("kph"))
finally:
obd_speed_lock.release()
def obd_rpm():
obd_rpm_lock.acquire()
cmd = obd.commands.RPM # select an OBD command (sensor)
response = connection.query(cmd) # send the command and parse the response
loop = True
try:
while loop == True:
global rpm
rpm = rpm + 1
time.sleep(1)
if response.is_null():
print("No data received. #"+"RPM :"+str(rpm))
socketio.emit('obd_rpm', rpm)
else:
print("RPM:", response.value)
socketio.emit('obd_rpm', response.value.to("kph"))
finally:
obd_rpm_lock.release()
def obd_dtc():
obd_dtc_lock.acquire()
cmd = obd.commands.GET_DTC # select an OBD command (sensor)
response = connection.query(cmd) # send the command and parse the response
try:
if response.is_null():
error_txt = "No data received."
print(error_txt)
socketio.emit('obd_dtc', error_txt)
else:
print(response.value)
socketio.emit('obd_dtc', response.value)
finally:
obd_dtc_lock.release()
def kill_obd(obd_type):
if obd_type == "speed":
obd_speed.loop = False
elif obd_type == "rpm":
obd_rpm.loop = False
+7
View File
@@ -0,0 +1,7 @@
##
## MangoDB server connection details
##
mangosrv_user = ""
mangosrv_pass = ""
mangosrv_db = ""
+5
View File
@@ -0,0 +1,5 @@
class Account:
def __init__(self):
self.name = "quoije"
self.pp_image = None
self.car = None
+4
View File
@@ -0,0 +1,4 @@
class Car:
def __init__(self):
self.model = "Yaris 2013"
self.obd = None
View File
+23
View File
@@ -0,0 +1,23 @@
from pymongo import MongoClient
from dotenv import load_dotenv
import os
load_dotenv("../db/creds.env")
mUser = os.getenv()
mPass = os.getenv()
mDB = os.getenv()
def get_database():
# Provide the mongodb atlas url to connect python to mongodb using pymongo
CONNECTION_STRING = "mongodb+srv://"+ mUser + ":" + mPass + "@cluster.mongodb.net/" + mDB
# Create a connection using MongoClient. You can import MongoClient or use pymongo.MongoClient
client = MongoClient(CONNECTION_STRING)
# This is added so that many files can reuse the function get_database()
if __name__ == "__main__":
# Get the database
dbname = get_database()
+45
View File
@@ -0,0 +1,45 @@
from flask_socketio import SocketIO
from threading import Thread
from modules import app_obd
import time, threading
socketio = SocketIO()
uptime_lock = threading.Lock()
thread_uptime = None
@socketio.on('connect')
def connect_event():
print('Client connected')
print('Getting OBD status...')
app_obd.obd_connection()
uptime()
def uptime():
global thread_uptime
if thread_uptime is None or not thread_uptime.is_alive():
thread_uptime = Thread(target=loop_uptime)
thread_uptime.daemon = True
thread_uptime.start()
print(f"Uptime thread started, alive: {thread_uptime.is_alive()}")
else:
print(f"Uptime thread already running, alive: {thread_uptime.is_alive()}")
def loop_uptime():
uptime_lock.acquire()
try:
loop = True
while loop == True:
boottime = time.clock_gettime(time.CLOCK_BOOTTIME)
# Convert to hours, minutes, and seconds
seconds = int(boottime)
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
time.sleep(1)
uptime = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
socketio.emit("rpi_uptime", uptime)
finally:
uptime_lock.release()
+22
View File
@@ -0,0 +1,22 @@
from modules.app_events import socketio
from threading import Thread
class GPS:
def __init__(self):
self.LocationX = None
self.LocationY= None
@socketio.on('gps')
def get_gps():
global LocationX
global LocationY
LocationX = "45.5202844"
LocationY = "-73.5493208"
Location = [LocationX, LocationY]
socketio.emit('gps_location', Location)
print("websocket should be sent now")
return print("socket.io emitted")
+109
View File
@@ -0,0 +1,109 @@
from modules import app_gps, app_sql, app_events
import obd, time, threading
from datetime import datetime
from threading import Thread
status = None
speed = 0
rpm = None
class OBD:
def __init__(self):
self.status = status
self.rpm = rpm
self.speed = speed
obd_status = ["Disconnected", "Connected", "Connection...", "wtf"]
obd_speed_lock = threading.Lock()
obd_rpm_lock = threading.Lock()
thread_speed = None
thread_rpm = None
try:
print(obd_status[2])
connection = obd.OBD() # put linux /dev/rfi... something in () for the rpi bluetooth adpater
except Exception as e:
print("An error occurred:", str(e))
def get_speedtime():
global speed
date = datetime.now()
today = str(date.today())
time_now = str(date.strftime("%H:%M:%S"))
return [str(time_now), speed]
def obd_connection():
global thread_speed, thread_rpm
if connection.is_connected():
print(obd_status[1])
app_events.socketio.emit('obd_status', obd_status[1])
print("OBD connection established.")
else:
print("OBD connection failed.")
print(obd_status[0])
app_events.socketio.emit('obd_status', obd_status[0])
app_events.socketio.emit('obd_speed', "-")
app_events.socketio.emit('obm_error', "-")
app_events.socketio.emit('obd_rpm', "-")
if thread_speed is None or not thread_speed.is_alive():
thread_speed = Thread(target=obd_speed)
print(f'thread_speed alive? {thread_speed.is_alive()}')
thread_speed.daemon = True
thread_speed.start()
if thread_rpm is None or not thread_rpm.is_alive():
thread_rpm = Thread(target=obd_rpm)
print(f'thread_rpm alive? {thread_rpm.is_alive()}')
thread_rpm.daemon = True
thread_rpm.start()
def obd_speed():
obd_speed_lock.acquire()
cmd = obd.commands.SPEED # select an OBD command (sensor)
response = connection.query(cmd) # send the command and parse the response
loop = True
try:
while loop == True:
global speed
speed = speed + 1
time.sleep(2)
if response.is_null():
print("No data received. #"+ str(get_speedtime()))
print(app_gps.get_gps())
app_events.socketio.emit('obd_speed', get_speedtime())
else:
print("Original value:", response.value)
print("Value in kph:", response.value.to("kph"))
app_events.socketio.emit('obd_speed', response.value.to("kph"))
finally:
obd_speed_lock.release()
def obd_rpm():
obd_speed_lock.acquire()
cmd = obd.commands.RPM # select an OBD command (sensor)
response = connection.query(cmd) # send the command and parse the response
loop = True
try:
while loop == True:
global rpm
speed = speed + 1
time.sleep(1)
if response.is_null():
print("No data received. #"+ str(get_speedtime()))
app_events.socketio.emit('obd_speed', get_speedtime())
else:
print("RPM:", response.value)
app_events.socketio.emit('obd_speed', response.value.to("kph"))
finally:
obd_rpm_lock.release()
def kill_obd(obd_type):
if obd_type == "speed":
obd_speed.loop = False
elif obd_type == "rpm":
obd_rpm.loop = False
+78
View File
@@ -0,0 +1,78 @@
import sqlite3
from modules import app_obd, app_car, app_account, app_gps
from datetime import datetime
from sqlite3 import Error
currentdatetime = datetime.now()
account = app_account.Account()
car = app_car.Car()
sCarModel = ''.join(letter for letter in car.model if letter.isalnum())
sql_file = account.name + "_" + sCarModel + ".db"
sql_path = "../db/sql/" + sql_file
def create_conn(db_file):
conn = None
try:
conn = sqlite3.connect(db_file)
print(sqlite3.version)
except Error as e:
print(e)
finally:
if conn:
conn.close()
def create_table(conn, create_table_sql):
""" create a table from the create_table_sql statement
:param conn: Connection object
:param create_table_sql: a CREATE TABLE statement
:return:
"""
try:
c = conn.cursor()
c.execute(create_table_sql)
except Error as e:
print(e)
def main():
db = sql_path
sql_create_tracking_table = """CREATE TABLE IF NOT EXISTS tracking (
id integer PRIMARY KEY,
VN text NOT NULL,
NAME text NOT NULL,
DATETIME datetime,
GPSX float,
GPSY float,
SPEED float,
ODOMETER float
);"""
sql_create_dtc_table = """CREATE TABLE IF NOT EXISTS dtc (
id integer PRIMARY KEY,
NAME text NOT NULL,
STATUS text,
DTC_ID text
);"""
# create a database connection
conn = create_conn(db)
# create tables
if conn is not None:
# create diagnostics table
create_table(conn, sql_create_tracking_table)
# create diagnostics table
create_table(conn, sql_create_dtc_table)
else:
print("Error! cannot create the database connection.")
if __name__ == '__main__':
create_conn(sql_path)
# ## VN, NAME, DATE, TIME, GPS_X, GPS_Y, SPEED, ODOMETER
# (["VN", "NAME", "DATE", "TIME", "GPSX", "GPSY", "SPEED", "ODOMETER"])
# ([car.model, account.name, currentday, currenttime, GPSX, GPSY, SPEED, ODOMETER])
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

+5
View File
@@ -0,0 +1,5 @@
# yaris-obd #
![UI](https://github.com/quoije/yaris-obd/blob/698adee41532fed0ba1a7fe0ab83b26d569764cb/pics/ui.png)
python3 app.py
+5 -57
View File
@@ -1,57 +1,5 @@
Babel==2.8.0 Flask
bidict==0.22.1 Flask-SocketIO
blinker==1.4 gevent
click==8.0.3 pymongo
colorama==0.4.4 python-dotenv
command-not-found==0.3
cryptography==3.4.8
dbus-python==1.2.18
distro==1.7.0
distro-info===1.1build1
Flask==2.0.1
Flask-SocketIO==5.3.6
h11==0.14.0
httplib2==0.20.2
importlib-metadata==4.6.4
itsdangerous==2.1.0
jeepney==0.7.1
Jinja2==3.0.3
keyring==23.5.0
launchpadlib==1.10.16
lazr.restfulclient==0.14.4
lazr.uri==1.0.6
lxml==4.9.3
MarkupSafe==2.0.1
more-itertools==8.10.0
netifaces==0.11.0
oauthlib==3.2.0
obd==0.7.2
Pint==0.20.1
pycairo==1.20.1
PyGObject==3.42.1
pyinotify==0.9.6
PyJWT==2.3.0
pyOpenSSL==21.0.0
pyparsing==2.4.7
pyserial==3.5
python-apt==2.4.0+ubuntu1
python-engineio==4.8.0
python-socketio==5.10.0
pytils==0.4.1
pytz==2022.1
PyYAML==5.4.1
SecretStorage==3.3.1
simple-websocket==1.0.0
simplejson==3.17.6
six==1.16.0
systemd-python==234
tools==0.1.9
tqdm==4.66.1
ubuntu-advantage-tools==8001
ufw==0.36.1
unattended-upgrades==0.1
wadllib==1.3.6
Werkzeug==2.0.2
wget==3.2
wsproto==1.2.0
zipp==1.0.0
+18 -18
View File
@@ -1,4 +1,13 @@
const socket = io(); const socket = io();
// map
var map = L.map('map').setView([48.505, -0.09], 13);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
L.marker([51.5, -0.09]).addTo(map)
.bindPopup('your car... soon(tm)')
.openPopup();
// charts // charts
@@ -32,24 +41,12 @@ chart = new Chart(ctx, {
} }
}); });
// account
// websockets // websockets
socket.on('connect', function(data) { socket.on('connect', function(data) {
console.log('socket.io is connected') console.log('socket.io is connected')
}); });
socket.on('account_info', function(data) {
console.log(data);
// car model
const car_model = document.getElementById('index-car-model');
car_model.innerHTML = data;
});
socket.on('obd_status', function(data) { socket.on('obd_status', function(data) {
console.log(data); console.log(data);
const status = document.getElementById('obd-status'); const status = document.getElementById('obd-status');
@@ -87,12 +84,6 @@ socket.on('obd_rpm', function(data) {
status.innerHTML = data; status.innerHTML = data;
}); });
socket.on('obd_dtc', function(data) {
console.log("obd dtc "+data);
const status = document.getElementById('obd-dtc');
status.innerHTML = data;
});
socket.on('obd_error', function(data) { socket.on('obd_error', function(data) {
console.log("obd errors "+data); console.log("obd errors "+data);
const status = document.getElementById('obd-error'); const status = document.getElementById('obd-error');
@@ -103,3 +94,12 @@ socket.on('rpi_uptime', function(data) {
const status = document.getElementById('rpi-uptime'); const status = document.getElementById('rpi-uptime');
status.innerHTML = data; status.innerHTML = data;
}); });
socket.on('gps_location', function(data) {
console.log("location received")
const LocationX = document.getElementById('gpsLocationX');
const LocationY = document.getElementById('gpsLocationY');
LocationX.innerHTML = data[0];
LocationY.innerHTML = data[1];
});
+83
View File
@@ -0,0 +1,83 @@
<!DOCTYPE html>
<html data-bs-theme="light" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Dashboard - yaris vroom vroom de course</title>
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='yaris.css') }}">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.0/css/all.css">
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
</head>
<body id="page-top">
<div id="wrapper">
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="color: var(--bs-accordion-btn-focus-border-color);background: rgb(0,0,0);filter: blur(0px);backdrop-filter: blur(0px) hue-rotate(0deg);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="#">
<div class="sidebar-brand-icon rotate-n-15"><i class="fas fa-car"></i></div>
<div id="index-car-model" class="sidebar-brand-text mx-3"><span>{{ car.model }}</span></div>
</a>
<hr class="sidebar-divider my-0">
<ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"></li>
<li class="nav-item"><a class="nav-link active" href="/dash"><i class="fas fa-table"></i><span>Dashcam&nbsp;</span></a></li>
<li class="nav-item"></li>
<li class="nav-item"><a class="nav-link" href="/dtc"><i class="fas fa-table"></i><span>DTC&nbsp;</span></a></li>
</ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
</div>
</nav>
<div class="d-flex flex-column" id="content-wrapper">
<div id="content">
<nav class="navbar navbar-expand bg-white shadow mb-4 topbar static-top navbar-light">
<div class="container-fluid"><button class="btn btn-link d-md-none rounded-circle me-3" id="sidebarToggleTop" type="button"><i class="fas fa-bars"></i></button>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group"></div>
</form>
<ul class="navbar-nav flex-nowrap ms-auto">
<li class="nav-item dropdown d-sm-none no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><i class="fas fa-search"></i></a>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<form class="me-auto navbar-search w-100">
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div>
</form>
</div>
</li>
<div class="d-none d-sm-block topbar-divider"></div>
<li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span id="index-pp" class="d-none d-lg-inline me-2 text-gray-600 small">{{ account.name }}</span><img class="border rounded-circle img-profile" src="{{ url_for('static', filename='img/yaris.png') }}"></a>
</div>
<div class="shadow dropdown-list dropdown-menu dropdown-menu-end" aria-labelledby="alertsDropdown"></div>
</li>
<div class="d-none d-sm-block topbar-divider"></div>
</ul>
</div>
</nav>
<div class="container-fluid">
<h3 class="text-dark mb-4">DTC Codes</h3>
<div class="card shadow">
<div class="card-header py-3">
<p class="text-primary m-0 fw-bold">Output</p>
</div>
<div class="card-body"></div>
</div>
</div>
</div>
<footer class="bg-white sticky-footer">
<div class="container my-auto">
<div class="text-center my-auto copyright"><span>Copyright © yaris vroom vroom de course 2023</span></div>
</div>
</footer>
</div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a>
</div>
<script src="{{ url_for('static', filename='js/yaris.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/bs-init.js') }}"></script>
<script src="{{ url_for('static', filename='js/theme.js') }}"></script>
</body>
</html>
+11 -8
View File
@@ -4,10 +4,12 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Table - yaris vroom vroom de course</title> <title>Dashboard - yaris vroom vroom de course</title>
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}"> <link rel="stylesheet" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='yaris.css') }}">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap"> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&amp;display=swap">
<link rel="stylesheet" href="{{ url_for('static', filename='fonts/fontawesome-all.min.css') }}"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.12.0/css/all.css">
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
</head> </head>
<body id="page-top"> <body id="page-top">
@@ -15,12 +17,14 @@
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="color: var(--bs-accordion-btn-focus-border-color);background: rgb(0,0,0);filter: blur(0px);backdrop-filter: blur(0px) hue-rotate(0deg);"> <nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="color: var(--bs-accordion-btn-focus-border-color);background: rgb(0,0,0);filter: blur(0px);backdrop-filter: blur(0px) hue-rotate(0deg);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="#"> <div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="#">
<div class="sidebar-brand-icon rotate-n-15"><i class="fas fa-car"></i></div> <div class="sidebar-brand-icon rotate-n-15"><i class="fas fa-car"></i></div>
<div id="index-car-model" class="sidebar-brand-text mx-3"><span>CAR MODEL</span></div> <div id="index-car-model" class="sidebar-brand-text mx-3"><span>{{ car.model }}</span></div>
</a> </a>
<hr class="sidebar-divider my-0"> <hr class="sidebar-divider my-0">
<ul class="navbar-nav text-light" id="accordionSidebar"> <ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li> <li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"></li> <li class="nav-item"></li>
<li class="nav-item"><a class="nav-link" href="/dash"><i class="fas fa-table"></i><span>Dashcam&nbsp;</span></a></li>
<li class="nav-item"></li>
<li class="nav-item"><a class="nav-link active" href="/dtc"><i class="fas fa-table"></i><span>DTC&nbsp;</span></a></li> <li class="nav-item"><a class="nav-link active" href="/dtc"><i class="fas fa-table"></i><span>DTC&nbsp;</span></a></li>
</ul> </ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div> <div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
@@ -43,8 +47,9 @@
</form> </form>
</div> </div>
</li> </li>
<li class="nav-item dropdown no-arrow mx-1"> <div class="d-none d-sm-block topbar-divider"></div>
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="badge bg-danger badge-counter"></span></a> <li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span id="index-pp" class="d-none d-lg-inline me-2 text-gray-600 small">{{ account.name }}</span><img class="border rounded-circle img-profile" src="{{ url_for('static', filename='img/yaris.png') }}"></a>
</div> </div>
<div class="shadow dropdown-list dropdown-menu dropdown-menu-end" aria-labelledby="alertsDropdown"></div> <div class="shadow dropdown-list dropdown-menu dropdown-menu-end" aria-labelledby="alertsDropdown"></div>
</li> </li>
@@ -58,9 +63,7 @@
<div class="card-header py-3"> <div class="card-header py-3">
<p class="text-primary m-0 fw-bold">Output</p> <p class="text-primary m-0 fw-bold">Output</p>
</div> </div>
<div class="card-body"> <div class="card-body"></div>
<p id="obd-dtc"></p>
</div>
</div> </div>
</div> </div>
</div> </div>
+7 -13
View File
@@ -17,12 +17,14 @@
<nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="color: var(--bs-accordion-btn-focus-border-color);background: rgb(0,0,0);filter: blur(0px);backdrop-filter: blur(0px) hue-rotate(0deg);"> <nav class="navbar align-items-start sidebar sidebar-dark accordion bg-gradient-primary p-0 navbar-dark" style="color: var(--bs-accordion-btn-focus-border-color);background: rgb(0,0,0);filter: blur(0px);backdrop-filter: blur(0px) hue-rotate(0deg);">
<div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="#"> <div class="container-fluid d-flex flex-column p-0"><a class="navbar-brand d-flex justify-content-center align-items-center sidebar-brand m-0" href="#">
<div class="sidebar-brand-icon rotate-n-15"><i class="fas fa-car"></i></div> <div class="sidebar-brand-icon rotate-n-15"><i class="fas fa-car"></i></div>
<div id="index-car-model" class="sidebar-brand-text mx-3"><span>CAR MODEL</span></div> <div id="index-car-model" class="sidebar-brand-text mx-3"><span>{{ car.model }}</span></div>
</a> </a>
<hr class="sidebar-divider my-0"> <hr class="sidebar-divider my-0">
<ul class="navbar-nav text-light" id="accordionSidebar"> <ul class="navbar-nav text-light" id="accordionSidebar">
<li class="nav-item"><a class="nav-link active" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li> <li class="nav-item"><a class="nav-link active" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
<li class="nav-item"></li> <li class="nav-item"></li>
<li class="nav-item"><a class="nav-link" href="/dash"><i class="fas fa-table"></i><span>Dashcam&nbsp;</span></a></li>
<li class="nav-item"></li>
<li class="nav-item"><a class="nav-link" href="/dtc"><i class="fas fa-table"></i><span>DTC&nbsp;</span></a></li> <li class="nav-item"><a class="nav-link" href="/dtc"><i class="fas fa-table"></i><span>DTC&nbsp;</span></a></li>
</ul> </ul>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div> <div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
@@ -47,7 +49,7 @@
</li> </li>
<div class="d-none d-sm-block topbar-divider"></div> <div class="d-none d-sm-block topbar-divider"></div>
<li class="nav-item dropdown no-arrow"> <li class="nav-item dropdown no-arrow">
<div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span class="d-none d-lg-inline me-2 text-gray-600 small">Profile name</span><img class="border rounded-circle img-profile" src="{{ url_for('static', filename='img/yaris.png') }}"></a> <div class="nav-item dropdown no-arrow"><a class="dropdown-toggle nav-link" aria-expanded="false" data-bs-toggle="dropdown" href="#"><span id="index-pp" class="d-none d-lg-inline me-2 text-gray-600 small">{{ account.name }}</span><img class="border rounded-circle img-profile" src="{{ url_for('static', filename='img/yaris.png') }}"></a>
<div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="#"><i class="fas fa-user fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Profile</a><a class="dropdown-item" href="#"><i class="fas fa-cogs fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Settings</a><a class="dropdown-item" href="#"><i class="fas fa-list fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Activity log</a> <div class="dropdown-menu shadow dropdown-menu-end animated--grow-in"><a class="dropdown-item" href="#"><i class="fas fa-user fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Profile</a><a class="dropdown-item" href="#"><i class="fas fa-cogs fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Settings</a><a class="dropdown-item" href="#"><i class="fas fa-list fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Activity log</a>
<div class="dropdown-divider"></div><a class="dropdown-item" href="#"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a> <div class="dropdown-divider"></div><a class="dropdown-item" href="#"><i class="fas fa-sign-out-alt fa-sm fa-fw me-2 text-gray-400"></i>&nbsp;Logout</a>
</div> </div>
@@ -163,8 +165,8 @@
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
<p>GPS X:</p> <p>GPS X: <span id="gpsLocationX"></span></p>
<p>GPS Y:</p> <p>GPS Y: <span id="gpsLocationY"></span></p>
</div> </div>
</div> </div>
</div> </div>
@@ -180,18 +182,10 @@
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.js"></script>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script src="{{ url_for('static', filename='js/yaris.js') }}"></script> <script src="{{ url_for('static', filename='js/yaris.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}"></script> <script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/bs-init.js') }}"></script> <script src="{{ url_for('static', filename='js/bs-init.js') }}"></script>
<script src="{{ url_for('static', filename='js/theme.js') }}"></script> <script src="{{ url_for('static', filename='js/theme.js') }}"></script>
<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script>var map = L.map('map').setView([48.505, -0.09], 13);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
L.marker([51.5, -0.09]).addTo(map)
.bindPopup('your car... soon(tm)')
.openPopup();
</script>
</body> </body>
</html> </html>