Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f087478736 | ||
|
|
646bdd32b5 | ||
|
|
ada68ed6ac | ||
|
|
286649e9c3 | ||
|
|
792c170fd6 | ||
|
|
c4c10972a1 | ||
|
|
bdf6bb477b | ||
|
|
4bc184fcdf | ||
|
|
5e8e3cf603 | ||
|
|
651c798d3a | ||
|
|
e9f204d6bd | ||
|
|
9aa32584e6 | ||
|
|
698adee415 |
@@ -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()
|
||||||
|
|
||||||
@@ -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]
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
class Car:
|
|
||||||
def __init__(self):
|
|
||||||
self.model = None
|
|
||||||
@@ -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")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
##
|
||||||
|
## MangoDB server connection details
|
||||||
|
##
|
||||||
|
|
||||||
|
mangosrv_user = ""
|
||||||
|
mangosrv_pass = ""
|
||||||
|
mangosrv_db = ""
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class Account:
|
||||||
|
def __init__(self):
|
||||||
|
self.name = "quoije"
|
||||||
|
self.pp_image = None
|
||||||
|
self.car = None
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class Car:
|
||||||
|
def __init__(self):
|
||||||
|
self.model = "Yaris 2013"
|
||||||
|
self.obd = None
|
||||||
@@ -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)
|
||||||
@@ -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()
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
from flask_socketio import SocketIO
|
||||||
|
from threading import Thread
|
||||||
|
from modules import app_obd
|
||||||
|
import time, threading
|
||||||
|
|
||||||
|
socketio = SocketIO()
|
||||||
|
uptime_lock = threading.Lock()
|
||||||
|
|
||||||
|
@socketio.on('connect')
|
||||||
|
def connect_event():
|
||||||
|
print('Client connected')
|
||||||
|
print('Getting OBD status...')
|
||||||
|
app_obd.obd_connection()
|
||||||
|
uptime()
|
||||||
|
|
||||||
|
def uptime():
|
||||||
|
thread = Thread(target=loop_uptime)
|
||||||
|
thread.daemon = True
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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")
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
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()
|
||||||
|
|
||||||
|
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():
|
||||||
|
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', "-")
|
||||||
|
|
||||||
|
# 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()
|
||||||
|
|
||||||
|
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(10)
|
||||||
|
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
|
||||||
@@ -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])
|
||||||
|
After Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,5 @@
|
|||||||
|
# yaris-obd #
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
python3 app.py
|
||||||
@@ -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
|
|
||||||
|
Before Width: | Height: | Size: 692 KiB After Width: | Height: | Size: 696 KiB |
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 142 KiB |
|
Before Width: | Height: | Size: 829 KiB After Width: | Height: | Size: 834 KiB |
@@ -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);
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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: '© <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;
|
|
||||||
});
|
});
|
||||||
@@ -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&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 </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 </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>
|
||||||
@@ -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&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&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 </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 </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 </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>
|
||||||
@@ -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&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&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 </span></a></li>
|
<li class="nav-item"><a class="nav-link" href="/dash"><i class="fas fa-table"></i><span>Dashcam </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 </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> Profile</a><a class="dropdown-item" href="#"><i class="fas fa-cogs fa-sm fa-fw me-2 text-gray-400"></i> Settings</a><a class="dropdown-item" href="#"><i class="fas fa-list fa-sm fa-fw me-2 text-gray-400"></i> 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> 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> Profile</a><a class="dropdown-item" href="#"><i class="fas fa-cogs fa-sm fa-fw me-2 text-gray-400"></i> Settings</a><a class="dropdown-item" href="#"><i class="fas fa-list fa-sm fa-fw me-2 text-gray-400"></i> 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> 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> 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> 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="#"> Action</a><a class="dropdown-item" href="#"> 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="#"> 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="#"> Action</a><a class="dropdown-item" href="#"> Another action</a>
|
||||||
</div>
|
<div class="dropdown-divider"></div><a class="dropdown-item" href="#"> 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="#"> Action</a><a class="dropdown-item" href="#"> 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="#"> 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="#"> Action</a><a class="dropdown-item" href="#"> Another action</a>
|
||||||
</div>
|
<div class="dropdown-divider"></div><a class="dropdown-item" href="#"> 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="#"> Action</a><a class="dropdown-item" href="#"> 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="#"> 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="#"> Action</a><a class="dropdown-item" href="#"> Another action</a>
|
||||||
</div>
|
<div class="dropdown-divider"></div><a class="dropdown-item" href="#"> 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: '© <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>
|
||||||