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
+44 -37
View File
@@ -1,37 +1,44 @@
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 modules import app_gps, app_events, app_car, app_account, app_gps,app_obd
from app_events import socketio import time
from gevent.pywsgi import WSGIServer
port_number = 8000
app = Flask(__name__) app = Flask(__name__)
@app.route('/') app_events.socketio.init_app(app)
def index():
print("hello") account = app_account.Account()
return render_template('index.html') obd = app_obd.OBD()
car = app_car.Car()
@app.route('/dtc') gps = app_gps.get_gps()
def dtc():
return render_template('dtc.html') @app.route('/')
def index():
# not sure if im gonna use this print("hello "+ account.name)
@app.route('/api/obd_speed') print("you're car model is:" + car.model)
def data(): return render_template('index.html', account = account, car = car)
data = app_obd.speed
response = make_response(json.dumps(data)) @app.route('/dtc')
response.content_type = 'application/json' def dtc():
return response return render_template('dtc.html', account = account, car = car)
if __name__ == '__main__': @app.route('/dash')
socketio.init_app(app) def dash():
return render_template('dash.html', account = account, car = car)
p_obd_connection = threading.Thread(target=app_obd.obd_connection)
p_obd_connection.start() # not sure if im gonna use this
@app.route('/api/obd_speed/')
print("allo?") def data():
data = app_obd.speed
## response = make_response(json.dumps(data))
## only debug, remove in prod response.content_type = 'application/json'
## return response
app.run(host='localhost', port=port_number)
## if __name__ == '__main__':
# 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()
-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
+37 -37
View File
@@ -1,38 +1,38 @@
import os import os
import shutil import shutil
from tqdm import tqdm from tqdm import tqdm
def mount_device(device, mount_point): def mount_device(device, mount_point):
os.system(f"sudo mount {device} {mount_point}") os.system(f"sudo mount {device} {mount_point}")
def unmount_device(mount_point): def unmount_device(mount_point):
os.system(f"sudo umount {mount_point}") os.system(f"sudo umount {mount_point}")
def copy_files(source_folder, destination_folder): def copy_files(source_folder, destination_folder):
if not os.path.exists(destination_folder): if not os.path.exists(destination_folder):
os.makedirs(destination_folder) os.makedirs(destination_folder)
for root, dirs, files in os.walk(source_folder): for root, dirs, files in os.walk(source_folder):
for file in tqdm(files, desc="Copying files", unit="file"): for file in tqdm(files, desc="Copying files", unit="file"):
source_path = os.path.join(root, file) source_path = os.path.join(root, file)
destination_path = os.path.join(destination_folder, file) destination_path = os.path.join(destination_folder, file)
# Check if the file already exists in the destination folder # Check if the file already exists in the destination folder
if not os.path.exists(destination_path): if not os.path.exists(destination_path):
shutil.copy2(source_path, destination_folder) shutil.copy2(source_path, destination_folder)
if __name__ == "__main__": if __name__ == "__main__":
source_device = "/dev/sda" source_device = "/dev/sda"
mount_point = "/mnt/dash" mount_point = "/mnt/dash"
destination_folder = "~/yaris-obd/dash/videos" destination_folder = "~/yaris-obd/dash/videos"
try: try:
# Mount the device # Mount the device
mount_device(source_device, mount_point) mount_device(source_device, mount_point)
# Copy files from source to destination # Copy files from source to destination
copy_files(os.path.join(mount_point, "DCIM"), os.path.expanduser(destination_folder)) copy_files(os.path.join(mount_point, "DCIM"), os.path.expanduser(destination_folder))
finally: finally:
# Unmount the device (even if an exception occurs) # Unmount the device (even if an exception occurs)
unmount_device(mount_point) unmount_device(mount_point)
+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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 692 KiB

After

Width:  |  Height:  |  Size: 696 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 142 KiB

+4700 -4700
View File
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 829 KiB

After

Width:  |  Height:  |  Size: 834 KiB

File diff suppressed because one or more lines are too long
+7 -7
View File
@@ -1,8 +1,8 @@
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
var charts = document.querySelectorAll('[data-bss-chart]'); var charts = document.querySelectorAll('[data-bss-chart]');
for (var chart of charts) { for (var chart of charts) {
chart.chart = new Chart(chart, JSON.parse(chart.dataset.bssChart)); chart.chart = new Chart(chart, JSON.parse(chart.dataset.bssChart));
} }
}, false); }, false);
+7 -7
View File
File diff suppressed because one or more lines are too long
+76 -76
View File
@@ -1,76 +1,76 @@
(function() { (function() {
"use strict"; // Start of use strict "use strict"; // Start of use strict
var sidebar = document.querySelector('.sidebar'); var sidebar = document.querySelector('.sidebar');
var sidebarToggles = document.querySelectorAll('#sidebarToggle, #sidebarToggleTop'); var sidebarToggles = document.querySelectorAll('#sidebarToggle, #sidebarToggleTop');
if (sidebar) { if (sidebar) {
var collapseEl = sidebar.querySelector('.collapse'); var collapseEl = sidebar.querySelector('.collapse');
var collapseElementList = [].slice.call(document.querySelectorAll('.sidebar .collapse')) var collapseElementList = [].slice.call(document.querySelectorAll('.sidebar .collapse'))
var sidebarCollapseList = collapseElementList.map(function (collapseEl) { var sidebarCollapseList = collapseElementList.map(function (collapseEl) {
return new bootstrap.Collapse(collapseEl, { toggle: false }); return new bootstrap.Collapse(collapseEl, { toggle: false });
}); });
for (var toggle of sidebarToggles) { for (var toggle of sidebarToggles) {
// Toggle the side navigation // Toggle the side navigation
toggle.addEventListener('click', function(e) { toggle.addEventListener('click', function(e) {
document.body.classList.toggle('sidebar-toggled'); document.body.classList.toggle('sidebar-toggled');
sidebar.classList.toggle('toggled'); sidebar.classList.toggle('toggled');
if (sidebar.classList.contains('toggled')) { if (sidebar.classList.contains('toggled')) {
for (var bsCollapse of sidebarCollapseList) { for (var bsCollapse of sidebarCollapseList) {
bsCollapse.hide(); bsCollapse.hide();
} }
}; };
}); });
} }
// Close any open menu accordions when window is resized below 768px // Close any open menu accordions when window is resized below 768px
window.addEventListener('resize', function() { window.addEventListener('resize', function() {
var vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0); var vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
if (vw < 768) { if (vw < 768) {
for (var bsCollapse of sidebarCollapseList) { for (var bsCollapse of sidebarCollapseList) {
bsCollapse.hide(); bsCollapse.hide();
} }
}; };
}); });
} }
// Prevent the content wrapper from scrolling when the fixed side navigation hovered over // Prevent the content wrapper from scrolling when the fixed side navigation hovered over
var fixedNaigation = document.querySelector('body.fixed-nav .sidebar'); var fixedNaigation = document.querySelector('body.fixed-nav .sidebar');
if (fixedNaigation) { if (fixedNaigation) {
fixedNaigation.on('mousewheel DOMMouseScroll wheel', function(e) { fixedNaigation.on('mousewheel DOMMouseScroll wheel', function(e) {
var vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0); var vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
if (vw > 768) { if (vw > 768) {
var e0 = e.originalEvent, var e0 = e.originalEvent,
delta = e0.wheelDelta || -e0.detail; delta = e0.wheelDelta || -e0.detail;
this.scrollTop += (delta < 0 ? 1 : -1) * 30; this.scrollTop += (delta < 0 ? 1 : -1) * 30;
e.preventDefault(); e.preventDefault();
} }
}); });
} }
var scrollToTop = document.querySelector('.scroll-to-top'); var scrollToTop = document.querySelector('.scroll-to-top');
if (scrollToTop) { if (scrollToTop) {
// Scroll to top button appear // Scroll to top button appear
window.addEventListener('scroll', function() { window.addEventListener('scroll', function() {
var scrollDistance = window.pageYOffset; var scrollDistance = window.pageYOffset;
//check if user is scrolling up //check if user is scrolling up
if (scrollDistance > 100) { if (scrollDistance > 100) {
scrollToTop.style.display = 'block'; scrollToTop.style.display = 'block';
} else { } else {
scrollToTop.style.display = 'none'; scrollToTop.style.display = 'none';
} }
}); });
} }
})(); // End of use strict })(); // End of use strict
+104 -104
View File
@@ -1,105 +1,105 @@
const socket = io(); const socket = io();
// map
// charts
var map = L.map('map').setView([48.505, -0.09], 13);
const ctx = document.getElementById('speedGraph').getContext('2d'); L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
chart = new Chart(ctx, { attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
type: 'line', }).addTo(map);
data: { L.marker([51.5, -0.09]).addTo(map)
datasets: [{ .bindPopup('your car... soon(tm)')
label: 'Vehicle speed', .openPopup();
borderColor: 'rgba(75, 192, 192, 1)',
fill: false, // charts
}]
}, const ctx = document.getElementById('speedGraph').getContext('2d');
options: { chart = new Chart(ctx, {
responsive: true, type: 'line',
scales: { data: {
x: { datasets: [{
reverse: true, label: 'Vehicle speed',
title: { borderColor: 'rgba(75, 192, 192, 1)',
display: true, fill: false,
text: 'Time', }]
} },
}, options: {
y: { responsive: true,
title: { scales: {
display: true, x: {
text: 'Speed' reverse: true,
} title: {
} display: true,
} text: 'Time',
} }
}); },
y: {
// account title: {
display: true,
text: 'Speed'
}
// websockets }
}
socket.on('connect', function(data) { }
console.log('socket.io is connected') });
});
// websockets
socket.on('account_info', function(data) {
console.log(data); socket.on('connect', function(data) {
console.log('socket.io is connected')
// car model });
const car_model = document.getElementById('index-car-model');
car_model.innerHTML = data; socket.on('obd_status', function(data) {
}); console.log(data);
const status = document.getElementById('obd-status');
socket.on('obd_status', function(data) { status.innerHTML = data;
console.log(data); });
const status = document.getElementById('obd-status');
status.innerHTML = data; socket.on('obd_speed', function(data) {
});
const time = data[0]; // Assuming data[0] is the time value
socket.on('obd_speed', function(data) { const speed = data[1]; // Assuming data[1] is the speed value
const maxDataPoints = 8; // Adjust this value as needed
const time = data[0]; // Assuming data[0] is the time value
const speed = data[1]; // Assuming data[1] is the speed value const status = document.getElementById('obd-speed');
const maxDataPoints = 8; // Adjust this value as needed status.innerHTML = speed;
const status = document.getElementById('obd-speed'); // Get a reference to the chart's data
status.innerHTML = speed; const chartData = chart.data.datasets[0].data;
// Get a reference to the chart's data // Unshift the new data points to the beginning of the chart dataset
const chartData = chart.data.datasets[0].data; chartData.unshift({ x: time, y: speed });
// Unshift the new data points to the beginning of the chart dataset // Remove data points if the number of data points exceeds maxDataPoints
chartData.unshift({ x: time, y: speed }); while (chartData.length > maxDataPoints) {
chartData.pop(); // Remove the oldest data point from the end
// Remove data points if the number of data points exceeds maxDataPoints }
while (chartData.length > maxDataPoints) {
chartData.pop(); // Remove the oldest data point from the end // Update the chart
} chart.update();
// Update the chart });
chart.update();
socket.on('obd_rpm', function(data) {
}); console.log("obd rpm "+data);
const status = document.getElementById('obd-rpm');
socket.on('obd_rpm', function(data) { status.innerHTML = data;
console.log("obd rpm "+data); });
const status = document.getElementById('obd-rpm');
status.innerHTML = data; socket.on('obd_error', function(data) {
}); console.log("obd errors "+data);
const status = document.getElementById('obd-error');
socket.on('obd_dtc', function(data) { status.innerHTML = data;
console.log("obd dtc "+data); });
const status = document.getElementById('obd-dtc');
status.innerHTML = data; socket.on('rpi_uptime', function(data) {
}); const status = document.getElementById('rpi-uptime');
status.innerHTML = data;
socket.on('obd_error', function(data) { });
console.log("obd errors "+data);
const status = document.getElementById('obd-error'); socket.on('gps_location', function(data) {
status.innerHTML = data; console.log("location received")
}); const LocationX = document.getElementById('gpsLocationX');
const LocationY = document.getElementById('gpsLocationY');
socket.on('rpi_uptime', function(data) { LocationX.innerHTML = data[0];
const status = document.getElementById('rpi-uptime'); LocationY.innerHTML = data[1];
status.innerHTML = data;
}); });
+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>
+82 -79
View File
@@ -1,80 +1,83 @@
<!DOCTYPE html> <!DOCTYPE html>
<html data-bs-theme="light" lang="en"> <html data-bs-theme="light" lang="en">
<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="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='yaris.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='fonts/fontawesome-all.min.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">
</head> <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=""/>
<body id="page-top"> </head>
<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);"> <body id="page-top">
<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 id="wrapper">
<div class="sidebar-brand-icon rotate-n-15"><i class="fas fa-car"></i></div> <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 id="index-car-model" class="sidebar-brand-text mx-3"><span>CAR MODEL</span></div> <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="#">
</a> <div class="sidebar-brand-icon rotate-n-15"><i class="fas fa-car"></i></div>
<hr class="sidebar-divider my-0"> <div id="index-car-model" class="sidebar-brand-text mx-3"><span>{{ car.model }}</span></div>
<ul class="navbar-nav text-light" id="accordionSidebar"> </a>
<li class="nav-item"><a class="nav-link" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li> <hr class="sidebar-divider my-0">
<li class="nav-item"></li> <ul class="navbar-nav text-light" id="accordionSidebar">
<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" href="/"><i class="fas fa-tachometer-alt"></i><span>Dashboard</span></a></li>
</ul> <li class="nav-item"></li>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div> <li class="nav-item"><a class="nav-link" href="/dash"><i class="fas fa-table"></i><span>Dashcam&nbsp;</span></a></li>
</div> <li class="nav-item"></li>
</nav> <li class="nav-item"><a class="nav-link active" href="/dtc"><i class="fas fa-table"></i><span>DTC&nbsp;</span></a></li>
<div class="d-flex flex-column" id="content-wrapper"> </ul>
<div id="content"> <div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
<nav class="navbar navbar-expand bg-white shadow mb-4 topbar static-top navbar-light"> </div>
<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> </nav>
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search"> <div class="d-flex flex-column" id="content-wrapper">
<div class="input-group"></div> <div id="content">
</form> <nav class="navbar navbar-expand bg-white shadow mb-4 topbar static-top navbar-light">
<ul class="navbar-nav flex-nowrap ms-auto"> <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>
<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> <form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown"> <div class="input-group"></div>
<form class="me-auto navbar-search w-100"> </form>
<div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..."> <ul class="navbar-nav flex-nowrap ms-auto">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div> <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> <div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
</form> <form class="me-auto navbar-search w-100">
</div> <div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
</li> <div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
<li class="nav-item dropdown no-arrow mx-1"> </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> </form>
</div> </div>
<div class="shadow dropdown-list dropdown-menu dropdown-menu-end" aria-labelledby="alertsDropdown"></div> </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">
</ul> <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>
</nav> <div class="shadow dropdown-list dropdown-menu dropdown-menu-end" aria-labelledby="alertsDropdown"></div>
<div class="container-fluid"> </li>
<h3 class="text-dark mb-4">DTC Codes</h3> <div class="d-none d-sm-block topbar-divider"></div>
<div class="card shadow"> </ul>
<div class="card-header py-3"> </div>
<p class="text-primary m-0 fw-bold">Output</p> </nav>
</div> <div class="container-fluid">
<div class="card-body"> <h3 class="text-dark mb-4">DTC Codes</h3>
<p id="obd-dtc"></p> <div class="card shadow">
</div> <div class="card-header py-3">
</div> <p class="text-primary m-0 fw-bold">Output</p>
</div> </div>
</div> <div class="card-body"></div>
<footer class="bg-white sticky-footer"> </div>
<div class="container my-auto"> </div>
<div class="text-center my-auto copyright"><span>Copyright © yaris vroom vroom de course 2023</span></div> </div>
</div> <footer class="bg-white sticky-footer">
</footer> <div class="container my-auto">
</div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a> <div class="text-center my-auto copyright"><span>Copyright © yaris vroom vroom de course 2023</span></div>
</div> </div>
<script src="{{ url_for('static', filename='js/yaris.js') }}"></script> </footer>
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}"></script> </div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a>
<script src="{{ url_for('static', filename='js/bs-init.js') }}"></script> </div>
<script src="{{ url_for('static', filename='js/theme.js') }}"></script> <script src="{{ url_for('static', filename='js/yaris.js') }}"></script>
</body> <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> </html>
+190 -196
View File
@@ -1,197 +1,191 @@
<!DOCTYPE html> <!DOCTYPE html>
<html data-bs-theme="light" lang="en"> <html data-bs-theme="light" lang="en">
<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>Dashboard - 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="{{ 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="https://use.fontawesome.com/releases/v5.12.0/css/all.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=""/> <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">
<div id="wrapper"> <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);"> <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="/dtc"><i class="fas fa-table"></i><span>DTC&nbsp;</span></a></li> <li class="nav-item"><a class="nav-link" href="/dash"><i class="fas fa-table"></i><span>Dashcam&nbsp;</span></a></li>
</ul> <li class="nav-item"></li>
<div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div> <li class="nav-item"><a class="nav-link" href="/dtc"><i class="fas fa-table"></i><span>DTC&nbsp;</span></a></li>
</div> </ul>
</nav> <div class="text-center d-none d-md-inline"><button class="btn rounded-circle border-0" id="sidebarToggle" type="button"></button></div>
<div class="d-flex flex-column" id="content-wrapper"> </div>
<div id="content"> </nav>
<nav class="navbar navbar-expand bg-white shadow mb-4 topbar static-top navbar-light"> <div class="d-flex flex-column" id="content-wrapper">
<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> <div id="content">
<form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search"> <nav class="navbar navbar-expand bg-white shadow mb-4 topbar static-top navbar-light">
<div class="input-group"></div> <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> <form class="d-none d-sm-inline-block me-auto ms-md-3 my-2 my-md-0 mw-100 navbar-search">
<ul class="navbar-nav flex-nowrap ms-auto"> <div class="input-group"></div>
<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> </form>
<div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown"> <ul class="navbar-nav flex-nowrap ms-auto">
<form class="me-auto navbar-search w-100"> <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="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ..."> <div class="dropdown-menu dropdown-menu-end p-3 animated--grow-in" aria-labelledby="searchDropdown">
<div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div> <form class="me-auto navbar-search w-100">
</div> <div class="input-group"><input class="bg-light form-control border-0 small" type="text" placeholder="Search for ...">
</form> <div class="input-group-append"><button class="btn btn-primary py-0" type="button"><i class="fas fa-search"></i></button></div>
</div> </div>
</li> </form>
<div class="d-none d-sm-block topbar-divider"></div> </div>
<li class="nav-item dropdown no-arrow"> </li>
<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="d-none d-sm-block topbar-divider"></div>
<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> <li class="nav-item dropdown no-arrow">
<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="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="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> <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>
</li> </div>
</ul> </div>
</div> </li>
</nav> </ul>
<div class="container-fluid"> </div>
<div class="d-sm-flex justify-content-between align-items-center mb-4"> </nav>
<h3 class="text-dark mb-0">Dashboard</h3><a class="btn btn-primary btn-sm d-none d-sm-inline-block" role="button" href="#"><i class="fas fa-download fa-sm text-white-50"></i>&nbsp;Placeholder button</a> <div class="container-fluid">
</div> <div class="d-sm-flex justify-content-between align-items-center mb-4">
<div class="row"> <h3 class="text-dark mb-0">Dashboard</h3><a class="btn btn-primary btn-sm d-none d-sm-inline-block" role="button" href="#"><i class="fas fa-download fa-sm text-white-50"></i>&nbsp;Placeholder button</a>
<div class="col-md-6 col-xl-3 mb-4"> </div>
<div class="card shadow border-start-primary py-2"> <div class="row">
<div class="card-body"> <div class="col-md-6 col-xl-3 mb-4">
<div class="row align-items-center no-gutters"> <div class="card shadow border-start-primary py-2">
<div class="col me-2"> <div class="card-body">
<div class="text-uppercase text-primary fw-bold text-xs mb-1"><span>OBD Status</span></div> <div class="row align-items-center no-gutters">
<div id="obd-status" class="text-dark fw-bold h5 mb-0"><span>unknown</span></div> <div class="col me-2">
</div> <div class="text-uppercase text-primary fw-bold text-xs mb-1"><span>OBD Status</span></div>
<div class="col-auto"><i class="fas fa-calendar fa-2x text-gray-300"></i></div> <div id="obd-status" class="text-dark fw-bold h5 mb-0"><span>unknown</span></div>
</div> </div>
</div> <div class="col-auto"><i class="fas fa-calendar fa-2x text-gray-300"></i></div>
</div> </div>
</div> </div>
<div class="col-md-6 col-xl-3 mb-4"> </div>
<div class="card shadow border-start-success py-2"> </div>
<div class="card-body"> <div class="col-md-6 col-xl-3 mb-4">
<div class="row align-items-center no-gutters"> <div class="card shadow border-start-success py-2">
<div class="col me-2"> <div class="card-body">
<div class="text-uppercase text-success fw-bold text-xs mb-1"><span>VEHICLE SPEED</span></div> <div class="row align-items-center no-gutters">
<div id="obd-speed" class="text-dark fw-bold h5 mb-0"><span>unknown</span></div> <div class="col me-2">
</div> <div class="text-uppercase text-success fw-bold text-xs mb-1"><span>VEHICLE SPEED</span></div>
<div class="col-auto"><i class="fas fa-dollar-sign fa-2x text-gray-300"></i></div> <div id="obd-speed" class="text-dark fw-bold h5 mb-0"><span>unknown</span></div>
</div> </div>
</div> <div class="col-auto"><i class="fas fa-dollar-sign fa-2x text-gray-300"></i></div>
</div> </div>
</div> </div>
<div class="col-md-6 col-xl-3 mb-4"> </div>
<div class="card shadow border-start-info py-2"> </div>
<div class="card-body"> <div class="col-md-6 col-xl-3 mb-4">
<div class="row align-items-center no-gutters"> <div class="card shadow border-start-info py-2">
<div class="col me-2"> <div class="card-body">
<div class="text-uppercase text-warning fw-bold text-xs mb-1" style="color: rgb(246,62,62);"><span style="color: rgb(246,62,62);">RPM</span></div> <div class="row align-items-center no-gutters">
<div id="obd-rpm" class="text-dark fw-bold h5 mb-0"><span>unknown</span></div> <div class="col me-2">
</div> <div class="text-uppercase text-warning fw-bold text-xs mb-1" style="color: rgb(246,62,62);"><span style="color: rgb(246,62,62);">RPM</span></div>
<div class="col-auto"><i class="fas fa-comments fa-2x text-gray-300"></i></div> <div id="obd-rpm" class="text-dark fw-bold h5 mb-0"><span>unknown</span></div>
</div> </div>
</div> <div class="col-auto"><i class="fas fa-comments fa-2x text-gray-300"></i></div>
</div> </div>
</div> </div>
<div class="col-md-6 col-xl-3 mb-4"> </div>
<div class="card shadow border-start-warning py-2"> </div>
<div class="card-body"> <div class="col-md-6 col-xl-3 mb-4">
<div class="row align-items-center no-gutters"> <div class="card shadow border-start-warning py-2">
<div class="col me-2"> <div class="card-body">
<div class="text-uppercase text-info fw-bold text-xs mb-1"><span>UPTIME</span></div> <div class="row align-items-center no-gutters">
<div class="row g-0 align-items-center"> <div class="col me-2">
<div class="col-auto"> <div class="text-uppercase text-info fw-bold text-xs mb-1"><span>UPTIME</span></div>
<div id="rpi-uptime" class="text-dark fw-bold h5 mb-0 me-3"><span>unknown</span></div> <div class="row g-0 align-items-center">
</div> <div class="col-auto">
</div> <div id="rpi-uptime" class="text-dark fw-bold h5 mb-0 me-3"><span>unknown</span></div>
</div> </div>
<div class="col-auto"><i class="fas fa-clipboard-list fa-2x text-gray-300"></i></div> </div>
</div> </div>
</div> <div class="col-auto"><i class="fas fa-clipboard-list fa-2x text-gray-300"></i></div>
</div> </div>
</div> </div>
</div> </div>
<div class="row"> </div>
<div class="col-lg-7 col-xl-8"> </div>
<div class="card shadow mb-4"> <div class="row">
<div class="card-header d-flex justify-content-between align-items-center"> <div class="col-lg-7 col-xl-8">
<h6 class="text-primary fw-bold m-0">Speed Graph</h6> <div class="card shadow mb-4">
<div class="dropdown no-arrow"><button class="btn btn-link btn-sm dropdown-toggle" aria-expanded="false" data-bs-toggle="dropdown" type="button"><i class="fas fa-ellipsis-v text-gray-400"></i></button> <div class="card-header d-flex justify-content-between align-items-center">
<div class="dropdown-menu shadow dropdown-menu-end animated--fade-in"> <h6 class="text-primary fw-bold m-0">Speed Graph</h6>
<p class="text-center dropdown-header">dropdown header:</p><a class="dropdown-item" href="#">&nbsp;Action</a><a class="dropdown-item" href="#">&nbsp;Another action</a> <div class="dropdown no-arrow"><button class="btn btn-link btn-sm dropdown-toggle" aria-expanded="false" data-bs-toggle="dropdown" type="button"><i class="fas fa-ellipsis-v text-gray-400"></i></button>
<div class="dropdown-divider"></div><a class="dropdown-item" href="#">&nbsp;Something else here</a> <div class="dropdown-menu shadow dropdown-menu-end animated--fade-in">
</div> <p class="text-center dropdown-header">dropdown header:</p><a class="dropdown-item" href="#">&nbsp;Action</a><a class="dropdown-item" href="#">&nbsp;Another action</a>
</div> <div class="dropdown-divider"></div><a class="dropdown-item" href="#">&nbsp;Something else here</a>
</div> </div>
<div class="card-body"> </div>
<div class="chart-container" style="position: relative; height:40vh; text-align: center;"> </div>
<canvas id="speedGraph"></canvas> <div class="card-body">
</div> <div class="chart-container" style="position: relative; height:40vh; text-align: center;">
</div> <canvas id="speedGraph"></canvas>
</div> </div>
</div> </div>
<div class="col-lg-5 col-xl-4"> </div>
<div class="card shadow mb-4"> </div>
<div class="card-header d-flex justify-content-between align-items-center"> <div class="col-lg-5 col-xl-4">
<h6 class="text-primary fw-bold m-0">GPS</h6> <div class="card shadow mb-4">
<div class="dropdown no-arrow"><button class="btn btn-link btn-sm dropdown-toggle" aria-expanded="false" data-bs-toggle="dropdown" type="button"><i class="fas fa-ellipsis-v text-gray-400"></i></button> <div class="card-header d-flex justify-content-between align-items-center">
<div class="dropdown-menu shadow dropdown-menu-end animated--fade-in"> <h6 class="text-primary fw-bold m-0">GPS</h6>
<p class="text-center dropdown-header">dropdown header:</p><a class="dropdown-item" href="#">&nbsp;Action</a><a class="dropdown-item" href="#">&nbsp;Another action</a> <div class="dropdown no-arrow"><button class="btn btn-link btn-sm dropdown-toggle" aria-expanded="false" data-bs-toggle="dropdown" type="button"><i class="fas fa-ellipsis-v text-gray-400"></i></button>
<div class="dropdown-divider"></div><a class="dropdown-item" href="#">&nbsp;Something else here</a> <div class="dropdown-menu shadow dropdown-menu-end animated--fade-in">
</div> <p class="text-center dropdown-header">dropdown header:</p><a class="dropdown-item" href="#">&nbsp;Action</a><a class="dropdown-item" href="#">&nbsp;Another action</a>
</div> <div class="dropdown-divider"></div><a class="dropdown-item" href="#">&nbsp;Something else here</a>
</div> </div>
<div class="card-body"> </div>
<div id="map"></div> </div>
</div> <div class="card-body">
</div> <div id="map"></div>
<div class="card shadow mb-4"> </div>
<div class="card-header d-flex justify-content-between align-items-center"> </div>
<h6 class="text-primary fw-bold m-0">GPS Info</h6> <div class="card shadow mb-4">
<div class="dropdown no-arrow"><button class="btn btn-link btn-sm dropdown-toggle" aria-expanded="false" data-bs-toggle="dropdown" type="button"><i class="fas fa-ellipsis-v text-gray-400"></i></button> <div class="card-header d-flex justify-content-between align-items-center">
<div class="dropdown-menu shadow dropdown-menu-end animated--fade-in"> <h6 class="text-primary fw-bold m-0">GPS Info</h6>
<p class="text-center dropdown-header">dropdown header:</p><a class="dropdown-item" href="#">&nbsp;Action</a><a class="dropdown-item" href="#">&nbsp;Another action</a> <div class="dropdown no-arrow"><button class="btn btn-link btn-sm dropdown-toggle" aria-expanded="false" data-bs-toggle="dropdown" type="button"><i class="fas fa-ellipsis-v text-gray-400"></i></button>
<div class="dropdown-divider"></div><a class="dropdown-item" href="#">&nbsp;Something else here</a> <div class="dropdown-menu shadow dropdown-menu-end animated--fade-in">
</div> <p class="text-center dropdown-header">dropdown header:</p><a class="dropdown-item" href="#">&nbsp;Action</a><a class="dropdown-item" href="#">&nbsp;Another action</a>
</div> <div class="dropdown-divider"></div><a class="dropdown-item" href="#">&nbsp;Something else here</a>
</div> </div>
<div class="card-body"> </div>
<p>GPS X:</p> </div>
<p>GPS Y:</p> <div class="card-body">
</div> <p>GPS X: <span id="gpsLocationX"></span></p>
</div> <p>GPS Y: <span id="gpsLocationY"></span></p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<footer class="bg-white sticky-footer"> </div>
<div class="container my-auto"> </div>
<div class="text-center my-auto copyright"><span>Copyright © yaris vroom vroom de course 2023</span></div> <footer class="bg-white sticky-footer">
</div> <div class="container my-auto">
</footer> <div class="text-center my-auto copyright"><span>Copyright © yaris vroom vroom de course 2023</span></div>
</div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a> </div>
</div> </footer>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> </div><a class="border rounded d-inline scroll-to-top" href="#page-top"><i class="fas fa-angle-up"></i></a>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.js"></script> </div>
<script src="{{ url_for('static', filename='js/yaris.js') }}"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js') }}"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.js"></script>
<script src="{{ url_for('static', filename='js/bs-init.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/theme.js') }}"></script> <script src="{{ url_for('static', filename='js/yaris.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='bootstrap/js/bootstrap.min.js') }}"></script>
<script>var map = L.map('map').setView([48.505, -0.09], 13); <script src="{{ url_for('static', filename='js/bs-init.js') }}"></script>
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', { <script src="{{ url_for('static', filename='js/theme.js') }}"></script>
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' </body>
}).addTo(map);
L.marker([51.5, -0.09]).addTo(map)
.bindPopup('your car... soon(tm)')
.openPopup();
</script>
</body>
</html> </html>