From ae02bdb99389c3cb43fff3e3656166d3efd5948e Mon Sep 17 00:00:00 2001 From: mofeng <3285338098@qq.com> Date: Thu, 14 Dec 2023 18:46:17 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install.sh | 47 +++++++++--- patch/hw.py | 143 +++++++++++++++++++++++++++++++++++++ patch/meson8b-onecloud.dtb | Bin 21082 -> 0 bytes 3 files changed, 181 insertions(+), 9 deletions(-) create mode 100644 patch/hw.py delete mode 100644 patch/meson8b-onecloud.dtb diff --git a/install.sh b/install.sh index 90c01fb1..b7688efe 100755 --- a/install.sh +++ b/install.sh @@ -33,26 +33,55 @@ if [ -f "./installed.txt" ]; then rm /etc/kvmd/nginx/ssl/server.crt rm /etc/kvmd/nginx/ssl/server.key else + #此为危险操作,会覆盖MBR分区,请在没有自行分区前执行,否则会丢失分区数据系统无法启动! + gzip -dc ./patch/Boot_SkipUSBBurning.gz | dd of=/dev/mmcblk1 && echo "One-KVM V0.4" >> installed.txt && echo "覆盖引导成功!" echo kvmd ALL=\(ALL\) NOPASSWD: /usr/bin/long_press_gpio420,/usr/bin/short_press_gpio420 >> /etc/sudoers fi -#此为危险操作,会覆盖MBR分区,请在没有自行分区前执行,否则会丢失分区数据系统无法启动! -gzip -dc ./patch/Boot_SkipUSBBurning.gz | dd of=/dev/mmcblk1 && echo "One-KVM V0.4" >> installed.txt && echo "覆盖引导成功!" -bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh) --source mirrors.tuna.tsinghua.edu.cn --updata-software false --web-protocol http && echo "换源成功!" -echo "正在安装依赖软件nginx tesseract-ocr tesseract-ocr-eng janus libevent-dev libgpiod-dev tesseract-ocr-chi-sim......" -apt install -y nginx tesseract-ocr tesseract-ocr-eng janus libevent-dev libgpiod-dev tesseract-ocr-chi-sim >> ./log.txt -echo "正在安装PiKVM......" -dpkg -i ./fruity-pikvm_0.2_armhf.deb && echo "PiKVM安装成功!" && systemctl enable kvmd-vnc + +if [-f "./installed.txt"]; then + echo "您似乎已经安装One-KVM,是否覆盖安装激活(Y/N)?" + read USERYN + case $USERYN in + N | n) + echo "跳过安装fruity-pikvm_0.2_armhf.deb!" + exit + ;; + *) + echo "正在安装PiKVM......" + dpkg -i ./fruity-pikvm_0.2_armhf.deb >> ./log.txt && systemctl enable kvmd-vnc && echo "PiKVM安装成功!" + ;; + esac +else + bash <(curl -sSL https://gitee.com/SuperManito/LinuxMirrors/raw/main/ChangeMirrors.sh) --source mirrors.tuna.tsinghua.edu.cn --updata-software false --web-protocol http && echo "换源成功!" + echo "正在安装依赖软件nginx tesseract-ocr tesseract-ocr-eng janus libevent-dev libgpiod-dev tesseract-ocr-chi-sim......" + apt install -y nginx tesseract-ocr tesseract-ocr-eng janus libevent-dev libgpiod-dev tesseract-ocr-chi-sim >> ./log.txt + echo "正在安装PiKVM......" + dpkg -i ./fruity-pikvm_0.2_armhf.deb >> ./log.txt && systemctl enable kvmd-vnc && echo "PiKVM安装成功!" +fi + + + cd $CURRENTWD cp ./patch/chinese.patch /usr/share/kvmd/web/ && cd /usr/share/kvmd/web/ && patch -s -p0 < chinese.patch cd $CURRENTWD cp ./patch/3.198msd.patch /usr/local/lib/python3.10/kvmd-packages/ && cd /usr/local/lib/python3.10/kvmd-packages/ && patch -s -p0 < 3.198msd.patch +cp -f ./patch/hw.py /usr/local/lib/python3.10/kvmd-packages/kvmd/apps/kvmd/info/ && chmod +x /usr/local/lib/python3.10/kvmd-packages/kvmd/apps/kvmd/info/hw.py echo "补丁应用成功!" cd $CURRENTWD && cp -f ./patch/long_press_gpio420 /usr/bin && cp -f ./patch/short_press_gpio420 /usr/bin && echo "GPIO-420脚本移动成功!" chmod +x /usr/bin/long_press_gpio420 && chmod +x /usr/bin/short_press_gpio420 cp -f ./config/main.yaml /etc/kvmd/ && cp -f ./config/override.yaml /etc/kvmd/ && echo "配置文件修改成功!" -kvmd -m >> ./log.txt -echo "机器已执行重启命令,请手动给玩客云重新上电(拔插电源),然后就可以开始使用One-KVM了!" + +if [-f "./installed.txt"]; then + kvmd -m >> ./log.txt + echo "机器已执行重启命令,稍作等待就可以开始使用One-KVM了!" +else + kvmd -m >> ./log.txt + echo "机器已执行重启命令,请手动给玩客云重新上电(拔插电源),然后就可以开始使用One-KVM了!" +fi + +ipaddr=`ip addr | grep "scope global" | awk '{print $2}' |awk -F/ '{print $1}'` +echo -e "内网访问地址为:\nhttp://$ipaddr\nhttps://$ipaddr" reboot \ No newline at end of file diff --git a/patch/hw.py b/patch/hw.py new file mode 100644 index 00000000..83f5c6c2 --- /dev/null +++ b/patch/hw.py @@ -0,0 +1,143 @@ +# ========================================================================== # +# # +# KVMD - The main PiKVM daemon. # +# # +# Copyright (C) 2018-2022 Maxim Devaev # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +# ========================================================================== # + + +import os +import asyncio + +from typing import Callable +from typing import AsyncGenerator +from typing import TypeVar + +from ....logging import get_logger + +from .... import env +from .... import tools +from .... import aiofs +from .... import aioproc + +from .base import BaseInfoSubmanager + + +# ===== +_RetvalT = TypeVar("_RetvalT") + + +# ===== +class HwInfoSubmanager(BaseInfoSubmanager): + def __init__( + self, + vcgencmd_cmd: list[str], + state_poll: float, + ) -> None: + + self.__vcgencmd_cmd = vcgencmd_cmd + self.__state_poll = state_poll + + self.__dt_cache: dict[str, str] = {} + + async def get_state(self) -> dict: + (model, cpu_temp, throttling) = await asyncio.gather( + self.__read_dt_file("model"), + self.__get_cpu_temp(), + self.__get_throttling(), + ) + return { + "platform": { + "type": "rpi", + "base": model, + "serial": "0000000000000000", + }, + "health": { + "temp": { + "cpu": cpu_temp, + }, + "throttling": throttling, + }, + } + + async def poll_state(self) -> AsyncGenerator[dict, None]: + prev_state: dict = {} + while True: + state = await self.get_state() + if state != prev_state: + yield state + prev_state = state + await asyncio.sleep(self.__state_poll) + + # ===== + + async def __read_dt_file(self, name: str) -> (str | None): + if name not in self.__dt_cache: + path = os.path.join(f"{env.PROCFS_PREFIX}/proc/device-tree", name) + try: + self.__dt_cache[name] = (await aiofs.read(path)).strip(" \t\r\n\0") + except Exception as err: + get_logger(0).error("Can't read DT %s from %s: %s", name, path, err) + return None + return self.__dt_cache[name] + + async def __get_cpu_temp(self) -> (float | None): + temp_path = f"{env.SYSFS_PREFIX}/sys/class/thermal/thermal_zone0/temp" + try: + return int((await aiofs.read(temp_path)).strip()) / 1000 + except Exception as err: + get_logger(0).error("Can't read CPU temp from %s: %s", temp_path, err) + return None + + async def __get_throttling(self) -> (dict | None): + # https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=147781&start=50#p972790 + flags = await self.__parse_vcgencmd( + arg="get_throttled", + parser=(lambda text: int(text.split("=")[-1].strip(), 16)), + ) + if flags is not None: + return { + "raw_flags": flags, + "parsed_flags": { + "undervoltage": { + "now": bool(flags & (1 << 0)), + "past": bool(flags & (1 << 16)), + }, + "freq_capped": { + "now": bool(flags & (1 << 1)), + "past": bool(flags & (1 << 17)), + }, + "throttled": { + "now": bool(flags & (1 << 2)), + "past": bool(flags & (1 << 18)), + }, + }, + } + return None + + async def __parse_vcgencmd(self, arg: str, parser: Callable[[str], _RetvalT]) -> (_RetvalT | None): + cmd = [*self.__vcgencmd_cmd, arg] + try: + text = (await aioproc.read_process(cmd, err_to_null=True))[1] + except Exception: + get_logger(0).exception("Error while executing: %s", tools.cmdfmt(cmd)) + return None + try: + return parser(text) + except Exception as err: + get_logger(0).error("Can't parse [ %s ] output: %r: %s", tools.cmdfmt(cmd), text, tools.efmt(err)) + return None diff --git a/patch/meson8b-onecloud.dtb b/patch/meson8b-onecloud.dtb deleted file mode 100644 index 6567cc5243c2624e6ae3b23b0e65eec6d5592e38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21082 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