Fleet Manager: Error log access support (#169)

* Update README.md

* add error troubleshooting and delScreenRecords btn

* Revert "Update README.md"

This reverts commit 5d22fe815fd7d772bb73a6b673ddd93b1383b3be.

* complete coment at paths

* add button to delete screen record

* remove button to delete screen record

* index cleanup

* rename

* simpler

* same module

* no need auth on home

* ide

* name

* smaller text

* spacing

* Update README.md

* Update CHANGELOGS.md

* '\n on changelogs.md

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
This commit is contained in:
AlexandreSato 2023-06-08 11:19:24 -03:00 committed by GitHub
parent 0065709a25
commit 6fd591e4b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 64 additions and 8 deletions

View File

@ -6,7 +6,10 @@ sunnypilot - Version Latest (2023-06-xx)
* NEW❗: Nissan and Mazda upstream models support * NEW❗: Nissan and Mazda upstream models support
* NEW❗: Pre-Global Subaru upstream models support * NEW❗: Pre-Global Subaru upstream models support
* HKG: smartMDPS automatic detection (installed with applicable firmware) * HKG: smartMDPS automatic detection (installed with applicable firmware)
* Fleet Manager (native & screen recordings) via Browser support thanks to actuallylemoncurd, AlexandreSato, ntegan1, and royjr! * Fleet Manager via Browser support thanks to actuallylemoncurd, AlexandreSato, ntegan1, and royjr!
* Access your dashcam footage, screen recordings, and error logs when the car is turned off
* Connect to the device via Wi-Fi, mobile hotspot, or tethering on the comma device, then navigate to
http://ipAddress:5050 to access.
* Honda Clarity 2018-22 support thanks to mcallbosco, vanillagorillaa and wirelessnet2! * Honda Clarity 2018-22 support thanks to mcallbosco, vanillagorillaa and wirelessnet2!
* Ram: Steer to 0/7 MPH support thanks to vincentw56! * Ram: Steer to 0/7 MPH support thanks to vincentw56!
* Retain hotspot/tethering state across reboots thanks to rogerioaguas! * Retain hotspot/tethering state across reboots thanks to rogerioaguas!

View File

@ -1,5 +1,5 @@
# Fleet Manager # Fleet Manager
Fleet Manger on sunnypilot allows viewing dashcam footage and screen recordings by connecting to the comma device via the same network, with your mobile device or PC. Big thanks to [actuallylemoncurd](https://github.com/actuallylemoncurd), [AlexandreSato](https://github.com/alexandreSato), [ntegan1](https://github.com/ntegan1), and [royjr](https://github.com/royjr). Fleet Manger on sunnypilot allows viewing dashcam footage, screen recordings, and error logs by connecting to the comma device via the same network, with your mobile device or PC. Big thanks to [actuallylemoncurd](https://github.com/actuallylemoncurd), [AlexandreSato](https://github.com/alexandreSato), [ntegan1](https://github.com/ntegan1), and [royjr](https://github.com/royjr).
The network can be set up by Wi-Fi, mobile hotspot, or tethering on the comma device. Navigate to http://tici:5050/ OR http://ipAddress:5050 to access. The network can be set up by Wi-Fi, mobile hotspot, or tethering on the comma device. Navigate to http://tici:5050/ OR http://ipAddress:5050 to access.

View File

@ -2,8 +2,8 @@
import os import os
import random import random
import secrets import secrets
import system.fleetmanager.helpers as fleet
from flask import Flask, render_template, Response, request, send_from_directory, session, redirect, url_for from flask import Flask, render_template, Response, request, send_from_directory, session, redirect, url_for
import system.fleetmanager.helpers as fleet
from system.loggerd.config import ROOT as REALDATA from system.loggerd.config import ROOT as REALDATA
app = Flask(__name__) app = Flask(__name__)
@ -89,7 +89,7 @@ def footage():
@app.route("/screenrecords") @app.route("/screenrecords")
@fleet.login_required @fleet.login_required
def screenrecords(): def screenrecords():
rows = fleet.all_screenrecords() rows = fleet.list_files(fleet.SCREENRECORD_PATH)
if not rows: if not rows:
return render_template("error.html", error="no screenrecords found at:<br><br>" + fleet.SCREENRECORD_PATH) return render_template("error.html", error="no screenrecords found at:<br><br>" + fleet.SCREENRECORD_PATH)
return render_template("screenrecords.html", rows=rows, clip=rows[0]) return render_template("screenrecords.html", rows=rows, clip=rows[0])
@ -98,7 +98,7 @@ def screenrecords():
@app.route("/screenrecords/<clip>") @app.route("/screenrecords/<clip>")
@fleet.login_required @fleet.login_required
def screenrecord(clip): def screenrecord(clip):
return render_template("screenrecords.html", rows=fleet.all_screenrecords(), clip=clip) return render_template("screenrecords.html", rows=fleet.list_files(fleet.SCREENRECORD_PATH), clip=clip)
@app.route("/screenrecords/play/pipe/<file>") @app.route("/screenrecords/play/pipe/<file>")
@ -119,6 +119,18 @@ def about():
return render_template("about.html") return render_template("about.html")
@app.route("/error_logs")
def error_logs():
return render_template("error_logs.html", rows=fleet.list_files(fleet.ERROR_LOGS_PATH))
@app.route("/error_logs/<file_name>")
def open_error_log(file_name):
f = open(fleet.ERROR_LOGS_PATH + file_name)
error = f.read()
return render_template("error_log.html", file_name=file_name, file_content=error)
def main(): def main():
if not os.path.exists(fleet.PIN_PATH): if not os.path.exists(fleet.PIN_PATH):
os.makedirs(fleet.PIN_PATH) os.makedirs(fleet.PIN_PATH)

View File

@ -8,12 +8,15 @@ from system.loggerd.config import ROOT as REALDATA
from system.loggerd.uploader import listdir_by_creation from system.loggerd.uploader import listdir_by_creation
from tools.lib.route import SegmentName from tools.lib.route import SegmentName
# path to sunnypilot screen recordings
# path to sunnypilot screen recordings and error logs
if PC: if PC:
SCREENRECORD_PATH = os.path.join(str(Path.home()), ".comma", "media", "0", "videos", "") SCREENRECORD_PATH = os.path.join(str(Path.home()), ".comma", "media", "0", "videos", "")
ERROR_LOGS_PATH = os.path.join(str(Path.home()), ".comma", "community", "crashes", "")
PIN_PATH = os.path.join(str(Path.home()), ".comma", "otp", "") PIN_PATH = os.path.join(str(Path.home()), ".comma", "otp", "")
else: else:
SCREENRECORD_PATH = "/data/media/0/videos/" SCREENRECORD_PATH = "/data/media/0/videos/"
ERROR_LOGS_PATH = "/data/community/crashes/"
PIN_PATH = "/data/otp/" PIN_PATH = "/data/otp/"
@ -27,8 +30,8 @@ def login_required(f):
return decorated_route return decorated_route
def all_screenrecords(): def list_files(path):
return sorted(listdir_by_creation(SCREENRECORD_PATH), reverse=True) return sorted(listdir_by_creation(path), reverse=True)
def is_valid_segment(segment): def is_valid_segment(segment):

View File

@ -0,0 +1,16 @@
{% extends "layout.html" %}
{% block title %}
Error Log
{% endblock %}
{% block main %}
<br>
<h1>Error Log of<br>{{ file_name }}</h1>
<br>
{% endblock %}
{% block unformated %}
<pre style="font-size: x-small; margin: 20px;">{{ file_content }}</pre>
<br><br>
{% endblock %}

View File

@ -0,0 +1,14 @@
{% extends "layout.html" %}
{% block title %}
Error Logs
{% endblock %}
{% block main %}
<br>
<h1>Error Logs</h1>
<br>
{% for row in rows %}
<a href="error_logs/{{ row }}">{{ row }}</a><br>
{% endfor %}
{% endblock %}

View File

@ -11,4 +11,5 @@
{% for row in rows %} {% for row in rows %}
<a href="footage/{{ row }}">{{ row }}</a><br> <a href="footage/{{ row }}">{{ row }}</a><br>
{% endfor %} {% endfor %}
<br><br>
{% endblock %} {% endblock %}

View File

@ -10,4 +10,5 @@
<br> <br>
<a href='/footage'>View Dashcam Footage</a><br> <a href='/footage'>View Dashcam Footage</a><br>
<br><a href='/screenrecords'>View Screen Recordings</a><br> <br><a href='/screenrecords'>View Screen Recordings</a><br>
<br><a href='/error_logs'>Access Error Logs</a><br>
{% endblock %} {% endblock %}

View File

@ -25,6 +25,9 @@
<li class="nav-item active"> <li class="nav-item active">
<a href="/screenrecords" class="nav-link">&nbsp &nbsp &nbsp &nbsp Screen Recordings</a> <a href="/screenrecords" class="nav-link">&nbsp &nbsp &nbsp &nbsp Screen Recordings</a>
</li> </li>
<li class="nav-item active">
<a href="/error_logs" class="nav-link">&nbsp &nbsp &nbsp &nbsp Error Logs</a>
</li>
<li class="nav-item active"> <li class="nav-item active">
<a href="/about" class="nav-link">&nbsp &nbsp &nbsp &nbsp About</a> <a href="/about" class="nav-link">&nbsp &nbsp &nbsp &nbsp About</a>
</li> </li>
@ -33,5 +36,6 @@
</div> </div>
</nav> </nav>
<main class="container-fluid p-7 text-center"> {% block main %}{% endblock %} </main> <main class="container-fluid p-7 text-center"> {% block main %}{% endblock %} </main>
{% block unformated %}{% endblock %}
</body> </body>
</html> </html>

View File

@ -53,4 +53,5 @@
document.getElementById("currentview").textContent=video.src.split("/")[4]; document.getElementById("currentview").textContent=video.src.split("/")[4];
</script> </script>
{% endautoescape %} {% endautoescape %}
<br><br>
{% endblock %} {% endblock %}

View File

@ -27,4 +27,5 @@
{% for row in rows %} {% for row in rows %}
<a href="/screenrecords/{{ row }}">{{ row }}</a><br> <a href="/screenrecords/{{ row }}">{{ row }}</a><br>
{% endfor %} {% endfor %}
<br><br>
{% endblock %} {% endblock %}