|
|
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().Errorf("err %+v \n", v)
|
|
|
} else {
|
|
|
zap.S().Errorf("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(gerror.Wrap(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()
|
|
|
}
|