From 13b19e3889239038c1acbb2c32fac73ad28253d1 Mon Sep 17 00:00:00 2001 From: KOSHIKAWA Kenichi Date: Sat, 15 Mar 2025 05:29:58 +0900 Subject: [PATCH 1/3] Improve update-nanokvm script --- kvmapp/system/update-nanokvm.py | 59 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/kvmapp/system/update-nanokvm.py b/kvmapp/system/update-nanokvm.py index 1260748..af0e490 100755 --- a/kvmapp/system/update-nanokvm.py +++ b/kvmapp/system/update-nanokvm.py @@ -2,41 +2,38 @@ import os import shutil import time import zipfile - +import pathlib import requests -temporary = "/root/.kvm-cache/" +temporary: str = "/root/.kvm-cache/" -def mkdir(): - is_exists = os.path.exists(temporary) - if is_exists: +def mkdir() -> None: + if pathlib.Path(temporary).exists(): shutil.rmtree(temporary) - os.mkdir(temporary) - print(f"create temporary directory {temporary}") + pathlib.Path(temporary).mkdir() + print(f"Created temporary directory {temporary}") -def read(file): - with open(file, "r") as f: - content = f.read() - return content.replace("\n", "") +def read(file: str) -> str: + return pathlib.Path(file).read_text().replace("\n", "") -def download_firmware(): - print("download firmware...") +def download_firmware() -> None: + print("Downloading firmware...") now = int(time.time()) url = f"https://cdn.sipeed.com/nanokvm/latest.zip?n={now}" - print(f"download from {url}") + print(f"Downloading firmware from {url}") response = requests.get(url) if response.status_code != 200: - raise Exception(f"download firmware failed, status: {response.status_code}") + raise Exception(f"Failed to download firmware, status: {response.status_code}") content_type = response.headers.get("content-type") if content_type != "application/zip": - raise Exception(f"download firmware failed, content_type: {content_type}") + raise Exception(f"Failed to download firmware, content_type: {content_type}") zip_file = f"{temporary}/latest.zip" with open(zip_file, "wb") as f: @@ -46,7 +43,7 @@ def download_firmware(): with zipfile.ZipFile(zip_file, "r") as f: f.extractall(temporary) - print("download firmware done") + print("Completed downloading firmware.") def download_lib(): @@ -75,20 +72,20 @@ def download_lib(): print("download lib done") -def update(): - backup_dir = "/root/old" - firmware_dir = "/kvmapp" +def update() -> None: + backup_dir = pathlib.Path("/root/old") + firmware_dir = pathlib.Path("/kvmapp") - if os.path.exists(backup_dir): - shutil.rmtree(backup_dir) + if backup_dir.exists(): + shutil.rmtree(backup_dir) - if os.path.exists(firmware_dir): - shutil.move(firmware_dir, backup_dir) + if firmware_dir.exists(): + firmware_dir.rename(backup_dir) - shutil.move(f"{temporary}/latest", firmware_dir) + pathlib.Path(f"{temporary}/latest").rename(firmware_dir) -def change_permissions(): +def change_permissions() -> None: for root, dirs, files in os.walk("/kvmapp"): os.chmod(root, 0o755) @@ -99,12 +96,12 @@ def change_permissions(): print("change permissions done") -def main(): +def main() -> None: try: - print("stop service...") + print("Stopping nanokvm service...") os.system("/etc/init.d/S95nanokvm stop") - print("start update......") + print("Staring update...") mkdir() download_firmware() @@ -113,7 +110,7 @@ def main(): change_permissions() version = read("/kvmapp/version") - print(f"update to {version} success.") + print(f"Successfully updated to version: {version}") print("restart service\nthe nanokvm will reboot") except Exception as e: print(f"update failed\n{e}") @@ -123,4 +120,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From bcaa8896eeeecd557ecc55e4503be5a09f3f29f8 Mon Sep 17 00:00:00 2001 From: mekaris <193354516+mekaris@users.noreply.github.com> Date: Sat, 15 Mar 2025 00:14:39 +0100 Subject: [PATCH 2/3] Add more serial features --- web/src/i18n/locales/en.ts | 10 +++ web/src/i18n/locales/pl.ts | 10 +++ .../desktop/menu/terminal/serial-port.tsx | 75 ++++++++++++++++++- web/src/pages/terminal/index.tsx | 6 +- 4 files changed, 97 insertions(+), 4 deletions(-) diff --git a/web/src/i18n/locales/en.ts b/web/src/i18n/locales/en.ts index 614d6ca..70600cd 100644 --- a/web/src/i18n/locales/en.ts +++ b/web/src/i18n/locales/en.ts @@ -133,6 +133,16 @@ const en = { serialPort: 'Serial Port', serialPortPlaceholder: 'Please enter the serial port', baudrate: 'Baud rate', + parity: 'Parity', + parityNone: 'None', + parityEven: 'Even', + parityOdd: 'Odd', + flowControl: 'Flow control', + flowControlNone: 'None', + flowControlSoft: 'Soft', + flowControlHard: 'Hard', + dataBits: 'Data bits', + stopBits: 'Stop bits', confirm: 'Ok' }, wol: { diff --git a/web/src/i18n/locales/pl.ts b/web/src/i18n/locales/pl.ts index 1f510ac..0674fc1 100644 --- a/web/src/i18n/locales/pl.ts +++ b/web/src/i18n/locales/pl.ts @@ -122,6 +122,16 @@ const pl = { serialPort: 'Port szeregowy', serialPortPlaceholder: 'Wprowadź port szeregowy', baudrate: 'Szybkość transmisji', + parity: 'Kontrola parzystości', + parityNone: 'Brak kontroli', + parityEven: 'Parzystość', + parityOdd: 'Nieparzystość', + flowControl: 'Kontrola przepływu', + flowControlNone: 'Brak kontroli', + flowControlSoft: 'Miękka', + flowControlHard: 'Twarda', + dataBits: 'Bity danych', + stopBits: 'Bity stopu', confirm: 'Ok' }, wol: { diff --git a/web/src/pages/desktop/menu/terminal/serial-port.tsx b/web/src/pages/desktop/menu/terminal/serial-port.tsx index 5f1d6dc..09a9aa4 100644 --- a/web/src/pages/desktop/menu/terminal/serial-port.tsx +++ b/web/src/pages/desktop/menu/terminal/serial-port.tsx @@ -1,5 +1,5 @@ import { ChangeEvent, useState } from 'react'; -import { Button, Input, InputNumber, Modal, Radio, RadioChangeEvent } from 'antd'; +import { Button, Input, InputNumber, Modal, Radio, RadioChangeEvent, Select } from 'antd'; import { useSetAtom } from 'jotai'; import { SquareTerminalIcon } from 'lucide-react'; import { useTranslation } from 'react-i18next'; @@ -13,6 +13,10 @@ export const SerialPort = () => { const [isModalOpen, setIsModalOpen] = useState(false); const [port, setPort] = useState(''); const [baudrate, setBaudrate] = useState(115200); + const [parity, setParity] = useState('none'); + const [flowControl, setFlowControl] = useState('none'); + const [dataBits, setDataBits] = useState(8); + const [stopBits, setStopBits] = useState(1); function openModal() { setIsKeyboardEnable(false); @@ -45,7 +49,7 @@ export const SerialPort = () => { } setIsModalOpen(false); - window.open(`/#terminal?port=${port}&baud=${baudrate}`, '_blank'); + window.open(`/#terminal?port=${port}&baud=${baudrate}&parity=${parity}&flowControl=${flowControl}&dataBits=${dataBits}&stopBits=${stopBits}`, '_blank'); } return ( @@ -92,6 +96,71 @@ export const SerialPort = () => { /> +
+
{t('terminal.parity')}
+
+ +
+
+ + +
+
{t('terminal.dataBits')}
+
+ +
+
+