Rice 1 month ago
parent cefe5ee26c
commit 241041d570

@ -0,0 +1,47 @@
@echo off
setlocal enabledelayedexpansion
REM 处理架构参数(第三个参数)
if "%3"=="" (
set "goarch=amd64"
set "releasePath=x86_64"
) else if "%3"=="arm" (
set "goarch=arm"
set "releasePath=arm"
) else if "%3"=="arm64" (
set "goarch=arm64"
set "releasePath=arm64"
) else if "%3"=="loong64" (
set "goarch=loong64"
set "releasePath=loong64"
) else (
echo 目标 %3 无法编译
exit /b 1
)
REM 处理操作系统参数(第二个参数)
if "%2"=="linux" (
echo 交叉编译目标为linux+%goarch%
set "CGO_ENABLED=0"
set "GOOS=linux"
set "GOARCH=%goarch%"
go build -o "%~n1-!releasePath!" %1
) else if "%2"=="windows" (
echo 交叉编译目标为windows+%goarch%
set "CGO_ENABLED=0"
set "GOOS=windows"
set "GOARCH=%goarch%"
go build -o "%~n1-!releasePath!.exe" %1
) else if "%2"=="darwin" (
echo 交叉编译目标为maxos+%goarch%
set "CGO_ENABLED=0"
set "GOOS=darwin"
set "GOARCH=%goarch%"
go build -o "%~n1-!releasePath!" %1
) else (
echo 参数不正确: %2
exit /b 1
)
echo 脚本执行结束...
endlocal

@ -0,0 +1,51 @@
case $3 in
"")
goarch="amd64"
releasePath="x86_64"
break
;;
"arm")
goarch="arm"
releasePath="arm"
break
;;
"arm64")
goarch="arm64"
releasePath="arm64"
break
;;
"loong64")
goarch="loong64"
releasePath="loong64"
break
;;
*)
echo '目标 ' $3 ' 无法编译'
exit
;;
esac
buildfile=$1
case $2 in
"linux"|"l") echo '交叉编译目标为linux+'$goarch
echo "CGO_ENABLED=0 GOOS=linux GOARCH="$goarch" go build "$1
CGO_ENABLED=0 GOOS=linux GOARCH=$goarch go build -o ./"${buildfile%%.*}-"$releasePath $1
break
;;
"windows"|"w") echo '交叉编译目标为windows+'$goarch
echo "CGO_ENABLED=0 GOOS=windows GOARCH="$goarch" go build "$1
CGO_ENABLED=0 GOOS=windows GOARCH=$goarch go build -o ././"${buildfile%%.*}-"$releasePath".exe" $1
break
;;
"darwin") echo '交叉编译目标为maxos+'$goarch
echo "CGO_ENABLED=0 GOOS=darwin GOARCH="$goarch" go build "$1
CGO_ENABLED=0 GOOS=darwin GOARCH=$goarch go build -o ./"${buildfile%%.*}-"$releasePath $1
break
;;
*) echo '参数不正确:'$goarch
break
;;
esac
echo '脚本执行结束...'

@ -0,0 +1,55 @@
{
"server": {
"port": "8089",
"static": "./wwwroot"
},
"logger": {
"path": "logs",
"file": "{Y-m-d}.log",
"prefix": "",
"level": "debug",
"timeFormat": "2006-01-02 15:04:05",
"ctxKeys": [],
"header": true,
"stdout": true,
"rotateSize": 0,
"rotateExpire": 0,
"rotateBackupLimit": 0,
"rotateBackupExpire": 0,
"rotateBackupCompress": 0,
"rotateCheckInterval": "1h",
"stdoutColorDisabled": false,
"writerColorEnable": false
},
"tty": {
"serialPortAddress": "/dev/ttyS2",
"baudRate": "9600"
},
"deviceInfo": {
"deviceId": "TGK",
"version": "1.0.2",
"meterAddr": "0x04"
},
"MessageInterval": 5,
"Firefox": {
"DebPkgPath": "./firefox",
"DebPkgName": "firefox-deb.tar.gz",
"InstallShellPath": "./firefox/firefox_install.sh"
},
"zap": {
"level": "debug",
"prefix": "",
"format": "console",
"director": "logs",
"encode-level": "CapitalLevelEncoder",
"stacktrace-key": "stacktrace",
"show-line": true,
"console-in-log": true,
"log-in-console": true,
"retention-day": 30,
"max-size": "10mb",
"compress": true,
"compress-level": 9,
"check-interval": "30m"
}
}

@ -0,0 +1,296 @@
package main
import (
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/towgo/towgo/lib/jsonrpc"
"github.com/towgo/towgo/lib/system"
"github.com/towgo/towgo/lib/www"
"go.uber.org/zap"
"tgk-touch/internal/core"
g "tgk-touch/internal/global"
"tgk-touch/internal/initialize"
licenseterminal "tgk-touch/internal/module/license_terminal"
"tgk-touch/internal/module/maincontrollerClient"
"log"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
"time"
"github.com/towgo/towgo/errors/tcode"
"github.com/towgo/towgo/towgo"
)
var (
productNumber string = "LampServer"
)
func main() {
log.SetFlags(log.Lshortfile | log.LstdFlags)
defer func() {
if exception := recover(); exception != nil {
if v, ok := exception.(error); ok && gerror.HasStack(v) {
zap.S().Error("err %+v \n", v)
} else {
zap.S().Error("recover exception %+v\n", gerror.NewCodef(tcode.CodeInternalPanic, "%+v", exception))
}
}
}()
appInit()
start()
}
func appInit() {
initialize.Init()
initLicense()
}
func initLicense() {
licenseterminal.SetProductNumber(productNumber)
licenseterminal.AutoFristActive()
licenseterminal.RegExpirationCall(productNumber, func() {
log.Println("产品:" + productNumber + "许可证到期")
list := []string{
"/account/login",
"/license/activecode/get",
"/license/activecode/online/request",
"/license/getActiveCredential",
"/license/active",
"/license/list",
"/license/accesscode/get",
}
jsonrpc.MethodLockAll(list...)
})
licenseterminal.RegReNewCall(productNumber, func() {
log.Println("产品:" + productNumber + "许可证续存")
jsonrpc.MethodUnlockAll()
})
}
func start() {
var err error
var serialPortAddress string = g.Config().Tty.SerialPortAddress
if serialPortAddress == "" {
panic(gerror.Wrap(err, "串口地址未配置 tty.serialPortAddress"))
}
var baudRateint int = g.Config().Tty.BaudRate
if baudRateint == 0 {
zap.S().Info("波特率未配置 tty.baudRate , 使用 默认 9600")
baudRateint = 9600
}
towgo.SetFunc("/getMessageInterval", getMessageInterval)
err = maincontrollerClient.UseSerialPort(serialPortAddress, baudRateint)
if err != nil {
panic(err)
}
webServer := www.WebServer{}
webServer.Wwwroot = system.GetPathOfProgram() + "wwwroot"
webServer.Index = []string{"index.html"}
g.HttpServerMux().HandleFunc("/",
webServer.WebServerHandller,
)
g.HttpServerMux().HandleFunc("/jsonrpc/websocket",
towgo.DefaultWebSocketServer.WebsocketServiceHandller.ServeHTTP,
)
g.HttpServerMux().HandleFunc("/jsonrpc",
towgo.HttpHandller)
towgo.DefaultExec = func(rpcConn towgo.JsonRpcConnection) {
if exception := recover(); exception != nil {
var msg string
if v, ok := exception.(error); ok && gerror.HasStack(v) {
g.Log().Error("towgo jsonrpc exception \n", v)
msg = v.Error()
} else {
g.Log().Error("towgo jsonrpc recover exception \n", gerror.NewCodef(tcode.CodeInternalPanic, "%+v", exception))
msg = v.Error()
}
rpcConn.WriteError(500, rpcConn.GetRpcRequest().Method+":"+msg)
}
}
install()
go runClient(g.Config().Server.Port)
core.RunServer()
}
func getMessageInterval(rpcConn towgo.JsonRpcConnection) {
rpcConn.WriteResult(g.Config().MessageInterval)
}
func install() {
// 1. 检查并安装Firefox
if !isFirefoxInstalled() {
fmt.Println("Firefox未安装正在安装...")
if err := installFirefox(); err != nil {
fmt.Printf("安装Firefox失败: %v\n", err)
os.Exit(1)
}
fmt.Println("Firefox安装成功")
} else {
fmt.Println("Firefox已安装")
}
// 2. 设置当前应用开机自启动
appPath, err := os.Executable()
if err != nil {
fmt.Printf("读取应用路径失败: %v\n", err)
os.Exit(1)
}
if !isAutoStartEnabled(appPath) {
fmt.Println("正在设置开机自启动...")
if err := enableAutoStart(appPath); err != nil {
fmt.Printf("设置开机自启动失败: %v\n", err)
os.Exit(1)
}
fmt.Println("开机自启动设置成功")
} else {
fmt.Println("已设置开机自启动")
}
}
func runClient(port int) {
// 配置显示器和Xauthority路径
display := ":0"
currentUser, err := user.Current()
if err != nil {
fmt.Printf("读取当前用户失败: %v\n", err)
os.Exit(1)
}
xauthPath := filepath.Join(currentUser.HomeDir, ".Xauthority")
for {
// 设置环境变量
os.Setenv("DISPLAY", display)
os.Setenv("XAUTHORITY", xauthPath)
// 关键:这组参数 = 完全关闭密码管理器 + 禁止保存/填充/弹窗
args := []string{
/*"--kiosk",
"--noerrdialogs",
"--no-first-run",
"--new-instance",
// 👇 下面这 3 个就是禁密码弹窗的核心
"--disable-features=PasswordManager",
"--pref=signon.rememberSignons=false",
"--pref=signon.autofillForms=false",*/
"http://127.0.0.1:" + fmt.Sprintf("%d", port),
}
// 启动Firefox
cmd := exec.Command("firefox", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
g.Log().Error(err.Error())
time.Sleep(5 * time.Second) // 等待后重试
continue
}
}
}
// 检查Firefox是否安装
func isFirefoxInstalled() bool {
cmd := exec.Command("which", "firefox")
return cmd.Run() == nil
}
// 安装Firefox
func installFirefox() error {
var p struct {
DebPkgPath string `json:"DebPkgPath"`
DebPkgName string `json:"DebPkgName"`
InstallShellPath string `json:"InstallShellPath"`
}
p.DebPkgPath = g.Config().Firefox.DebPkgPath
p.DebPkgName = g.Config().Firefox.DebPkgName
p.InstallShellPath = g.Config().Firefox.InstallShellPath
command := exec.Command("sudo", "sh", "-c", fmt.Sprintf(`
echo "=== 当前工作目录 ==="
pwd
echo ""
echo "=== 卸载旧版 Firefox ==="
dpkg -P firefox || echo "警告:卸载旧版 Firefox 失败(可能未安装)"
echo ""
echo "=== 清理残留文件 ==="
rm -rf /opt/firefox* 2>/dev/null
echo ""
echo "=== 开始安装 Firefox ==="
echo "1. 复制安装包到 /opt 目录..."
cp -v %s%s/%s /opt/firefox-deb.tar.gz || { echo "错误:复制安装包失败"; exit 1; }
echo ""
echo "2. 解压安装包..."
cd /opt && tar -xzvf firefox-deb.tar.gz || { echo "错误:解压失败"; exit 1; }
echo ""
echo "3. 安装依赖和主程序..."
cd /opt/firefox-deb && sudo dpkg -i *.deb || { echo "错误:安装 deb 包失败"; }
echo ""
echo "4. 验证安装..."
firefox --version || { echo "错误Firefox 未正确安装"; exit 1; }
echo ""
echo "=== Firefox 安装完成 ==="
`, system.GetPathOfProgram(), p.DebPkgPath, p.DebPkgName))
// 将命令的 stdout/stderr 直接绑定到当前终端
command.Stdout = os.Stdout
command.Stderr = os.Stderr
return command.Run()
}
func isAutoStartEnabled(appPath string) bool {
desktopFile := fmt.Sprintf("/etc/systemd/system/%s.service", strings.TrimSuffix(filepath.Base(appPath), filepath.Ext(appPath)))
_, err := os.Stat(desktopFile)
return !os.IsNotExist(err)
}
func enableAutoStart(appPath string) error {
appName := strings.TrimSuffix(filepath.Base(appPath), filepath.Ext(appPath))
serviceFile := fmt.Sprintf("/etc/systemd/system/%s.service", appName)
// 创建systemd服务文件内容
content := fmt.Sprintf(`[Unit]
Description=%s Background Service
After=network.target
[Service]
Type=simple
ExecStart=%s
Restart=on-failure
RestartSec=10
User=root
WorkingDirectory=%s
[Install]
WantedBy=multi-user.target
`,
appName,
appPath,
filepath.Dir(appPath))
// 写入服务文件
cmd := exec.Command("sudo", "bash", "-c",
fmt.Sprintf("echo '%s' > %s", content, serviceFile))
if err := cmd.Run(); err != nil {
return err
}
// 重新加载systemd配置
cmd = exec.Command("sudo", "systemctl", "daemon-reload")
if err := cmd.Run(); err != nil {
return err
}
// 启用服务
cmd = exec.Command("sudo", "systemctl", "enable", appName+".service")
return cmd.Run()
}
Loading…
Cancel
Save