Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/canflash/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
uploads/
metadata.json
3 changes: 3 additions & 0 deletions scripts/canflash/flash_logic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import subprocess
from datetime import datetime
from constants import ECU_CONFIG, UPLOAD_DIR
from metadata import load_metadata, save_metadata


def save_uploaded_file(ecu: str, file_name: str, file_content: bytes) -> str:
Expand All @@ -12,6 +13,8 @@ def save_uploaded_file(ecu: str, file_name: str, file_content: bytes) -> str:
os.makedirs(full_path, exist_ok=True)
file_path = os.path.join(full_path, file_name)

save_metadata(file_name, "", timestamp, ecu.lower(), ecu_dir)

with open(file_path, "wb") as f:
f.write(file_content)

Expand Down
144 changes: 141 additions & 3 deletions scripts/canflash/main.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
from nicegui import ui
from nicegui.events import UploadEventArguments
from flash_logic import save_uploaded_file, flash_file
from constants import ECU_CONFIG
from metadata import load_metadata, save_metadata
from constants import ECU_CONFIG, UPLOAD_DIR
import os
import json

class home_page:
def __init__(self):
self.build_ui()

def build_ui(self):
ui.colors(primary="#AA1F26")
ui.label('Welcome to CAN Flash!')
ui.label('Select to flash a new binary file')
ui.button('Upload a new binary file', on_click=lambda e: ui.navigate.to('/upload_new_bin'))
ui.label('Select to flash an existing binary file or update its notes')
ui.button('Flash an existing binary file', on_click=lambda e: ui.navigate.to('/upload_old_bin'))

# Upload new binary file and flash
class CanFlashApp:
def __init__(self):
self.starting_ecu = "Select ECU"
Expand Down Expand Up @@ -35,7 +49,6 @@ def handle_flash(self):
else:
ui.notify(str(exception), type="negative")


def build_ui(self):
ui.colors(primary="#AA1F26")
ui.markdown("Welcome to CAN Flash! Select an ECU and upload a file to flash. See [docs](https://macformula.github.io/racecar/) for more information.")
Expand All @@ -58,11 +71,136 @@ def build_ui(self):
self.flash_button = ui.button("Flash", on_click=self.handle_flash)
self.flash_button.disable()


# Flash an existing binary file or update notes
# Upload new binary file and flash
class CanFlashUploadExisting(CanFlashApp):
def __init__(self):
self.starting_ecu = "Select ECU"
self.selected_ecu = self.starting_ecu
self.bin_file = "Select Binary File"
self.selected_bin_file = self.bin_file
self.uploaded_file_path = None
self.build_ui()

def save_notes(self, notes: str, file_name: str):
try:
metadata = load_metadata()
except FileNotFoundError:
metadata = {}

if file_name in metadata:
# Update or add the notes for this file
metadata[file_name]["notes"] = notes

with open("metadata.json", 'w') as f:
json.dump(metadata, f, indent=2)

ui.notify(f"Notes updated for {file_name}", position="center")
else:
ui.notify(f"File {file_name} not found in metadata", type="negative")

def on_file_selection(self):
# Don't do anything if no file is selected
if self.selected_bin_file == self.bin_file:
return

# Load metadata for the selected file
metadata = load_metadata()
file_metadata = metadata.get(self.selected_bin_file, {})

if not file_metadata:
ui.notify("Could not find file metadata", type="negative")
return

# Construct the full file path
upload_name = file_metadata.get("upload name", "")
file_name = file_metadata.get("file name", "")
self.uploaded_file_path = os.path.join(UPLOAD_DIR, upload_name, file_name)

# Set the ECU from metadata
stored_ecu = file_metadata.get("ecu", "").lower()
# Match it to the ECU_CONFIG keys (which are title case)
for ecu_key in ECU_CONFIG.keys():
if ecu_key.lower() == stored_ecu:
self.selected_ecu = ecu_key
break

# Enable buttons
if hasattr(self, "flash_button"):
self.flash_button.enable()
if hasattr(self, "save_notes_button"):
self.save_notes_button.enable()

# Load existing notes into textbox
if hasattr(self, "textbox"):
self.textbox.value = file_metadata.get("notes", "")



def build_ui(self):
ui.colors(primary="#AA1F26")
ui.markdown("Welcome to CAN Flash! Select an ECU and upload a file to flash. See [docs](https://macformula.github.io/racecar/) for more information.")

# ECU Selection
self.ecu_select = ui.select([self.starting_ecu] + list(ECU_CONFIG.keys()))
self.ecu_select.bind_value(self, "selected_ecu")

# Binary File Selection
self.file_dropdown = ui.select([self.selected_bin_file] + list(load_metadata().keys()),
on_change=self.on_file_selection)
self.file_dropdown.bind_value(self, "selected_bin_file")

# Flash Button
ui.markdown("")
ui.markdown("Flash Binary File")
self.flash_button = ui.button("Flash", on_click=self.handle_flash)
self.flash_button.disable()

# Update Notes

ui.markdown("")
ui.markdown("Update Notes for previously Uploaded Files")

self.textbox = ui.input(label='Enter Metadata Notes')

self.save_notes_button = ui.button('Submit', on_click=lambda:
self.save_notes(self.textbox.value, self.selected_bin_file))
self.save_notes_button.disable()

# Delete Binary File

#FIXME
'''ui.markdown("")
ui.markdown("Delete Binary File")
self.delete_button = ui.button("Delete Binary File", on_click=lambda: delete_metadata("uploads"))
self.delete_button.disable()'''


@ui.page("/")
def main_page():
home_page()


@ui.page("/upload_new_bin")
def upload_new_bin():
CanFlashApp()


#Navigation
ui.markdown("")
ui.markdown("Navigation")
ui.button('Home', on_click=lambda e: ui.navigate.to('/'))
ui.button('Flash an existing binary file or update notes', on_click=lambda e: ui.navigate.to('/upload_old_bin'))

@ui.page("/upload_old_bin")
def reupload_existing_bin():
CanFlashUploadExisting()

#Navigation
ui.markdown("")
ui.markdown("Navigation")
ui.button('Home', on_click=lambda e: ui.navigate.to('/'))
ui.button('Upload a new binary file', on_click=lambda e: ui.navigate.to('/upload_new_bin'))

if __name__ in {"__main__", "__mp_main__"}:
ui.run(
Expand Down
27 changes: 27 additions & 0 deletions scripts/canflash/metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
import subprocess
import json

METADATA_FILE = "metadata.json"

def load_metadata():
if os.path.exists(METADATA_FILE):
with open(METADATA_FILE, "r") as f:
return json.load(f)
return {}

def save_metadata(file_name: str, notes: str, timestamp: str, ecu: str, upload_name: str):

metadata = load_metadata()

metadata[upload_name] = {
"file name": file_name,
"upload name": upload_name,
"ecu": ecu,
"notes": notes,
"uploaded_at": timestamp,
}


with open(METADATA_FILE, "w") as f:
json.dump(metadata, f, indent=2)