From e3608e02c6665e0a77471c8aae5a7aa197e8a729 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 16 Nov 2023 13:00:27 +0800 Subject: [PATCH 001/138] dev: add alias to modbus return --- driver/modbus_rtu_driver.go | 4 ++++ driver/modbus_tcp_driver.go | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/driver/modbus_rtu_driver.go b/driver/modbus_rtu_driver.go index b0d52744f..09565d08a 100644 --- a/driver/modbus_rtu_driver.go +++ b/driver/modbus_rtu_driver.go @@ -78,6 +78,7 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { SlaverId: r.SlaverId, Address: r.Address, Quantity: r.Quantity, + Alias: r.Alias, Value: covertEmptyHex(results), } dataMap[r.Tag] = value @@ -94,6 +95,7 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { SlaverId: r.SlaverId, Address: r.Address, Quantity: r.Quantity, + Alias: r.Alias, Value: covertEmptyHex(results), } dataMap[r.Tag] = value @@ -111,6 +113,7 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { SlaverId: r.SlaverId, Address: r.Address, Quantity: r.Quantity, + Alias: r.Alias, Value: covertEmptyHex(results), } dataMap[r.Tag] = value @@ -127,6 +130,7 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { SlaverId: r.SlaverId, Address: r.Address, Quantity: r.Quantity, + Alias: r.Alias, Value: covertEmptyHex(results), } dataMap[r.Tag] = value diff --git a/driver/modbus_tcp_driver.go b/driver/modbus_tcp_driver.go index 20d2aedc9..e9eb498ac 100644 --- a/driver/modbus_tcp_driver.go +++ b/driver/modbus_tcp_driver.go @@ -78,6 +78,7 @@ func (d *modBusTCPDriver) Read(cmd []byte, data []byte) (int, error) { SlaverId: r.SlaverId, Address: r.Address, Quantity: r.Quantity, + Alias: r.Alias, Value: covertEmptyHex(results), } dataMap[r.Tag] = value @@ -93,6 +94,7 @@ func (d *modBusTCPDriver) Read(cmd []byte, data []byte) (int, error) { Function: r.Function, SlaverId: r.SlaverId, Address: r.Address, + Alias: r.Alias, Quantity: r.Quantity, Value: covertEmptyHex(results), } @@ -110,6 +112,7 @@ func (d *modBusTCPDriver) Read(cmd []byte, data []byte) (int, error) { Function: r.Function, SlaverId: r.SlaverId, Address: r.Address, + Alias: r.Alias, Quantity: r.Quantity, Value: covertEmptyHex(results), } @@ -126,6 +129,7 @@ func (d *modBusTCPDriver) Read(cmd []byte, data []byte) (int, error) { Function: r.Function, SlaverId: r.SlaverId, Address: r.Address, + Alias: r.Alias, Quantity: r.Quantity, Value: covertEmptyHex(results), } From 951b67a84eea47eb9f2621ba9e1062d52d07eaf0 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 16 Nov 2023 13:00:51 +0800 Subject: [PATCH 002/138] dev: optimize tdengine and tcp target --- common/target_config.go | 12 ++++------ target/tdengine_target.go | 15 ++---------- target/ttcp_target.go | 48 +++++++++++++++++---------------------- 3 files changed, 28 insertions(+), 47 deletions(-) diff --git a/common/target_config.go b/common/target_config.go index c2d54ea3e..7287a9d99 100644 --- a/common/target_config.go +++ b/common/target_config.go @@ -17,13 +17,11 @@ type MongoConfig struct { // db_name: 可选参数,指定本次所执行的 SQL 语句的默认数据库库名 // curl -u root:taosdata -d 'show databases;' 106.15.225.172:6041/rest/sql type TDEngineConfig struct { - Fqdn string `json:"fqdn" validate:"required" title:"地址"` // 服务地址 - Port int `json:"port" validate:"required" title:"端口"` // 服务端口 - Username string `json:"username" validate:"required" title:"用户"` // 用户 - Password string `json:"password" validate:"required" title:"密码"` // 密码 - DbName string `json:"dbName" validate:"required" title:"数据库名"` // 数据库名 - CreateDbSql string `json:"createDbSql" validate:"required" title:"建库SQL"` // 建库SQL - CreateTableSql string `json:"createTableSql" validate:"required" title:"建表SQL"` // 建表SQL + Fqdn string `json:"fqdn" validate:"required" title:"地址"` // 服务地址 + Port int `json:"port" validate:"required" title:"端口"` // 服务端口 + Username string `json:"username" validate:"required" title:"用户"` // 用户 + Password string `json:"password" validate:"required" title:"密码"` // 密码 + DbName string `json:"dbName" validate:"required" title:"数据库名"` // 数据库名 } /* diff --git a/target/tdengine_target.go b/target/tdengine_target.go index ce9fde2b5..262565eb8 100644 --- a/target/tdengine_target.go +++ b/target/tdengine_target.go @@ -93,19 +93,8 @@ func (td *tdEngineTarget) Start(cctx typex.CCTX) error { td.Ctx = cctx.Ctx td.CancelCTX = cctx.CancelCTX // - - if err := execQuery(td.client, td.mainConfig.Username, - td.mainConfig.Password, td.mainConfig.CreateDbSql, td.url()); err != nil { - return err - } - if err := execQuery(td.client, td.mainConfig.Username, - td.mainConfig.Password, td.mainConfig.CreateTableSql, td.url()); err != nil { - return err - } else { - td.status = typex.SOURCE_UP - return nil - } - + td.status = typex.SOURCE_UP + return nil } // 数据模型, 用来描述该资源支持的数据, 对应的是云平台的物模型 diff --git a/target/ttcp_target.go b/target/ttcp_target.go index 3d089b30d..c09ce2f81 100644 --- a/target/ttcp_target.go +++ b/target/ttcp_target.go @@ -21,20 +21,18 @@ import ( "net" "time" - "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) -type _TcpCommonConfig struct { +type _TcpMainConfig struct { DataMode string `json:"dataMode" validate:"required"` // RAW_STRING ; HEX_STRING AllowPing *bool `json:"allowPing" validate:"required"` // 是否开启ping PingPacket string `json:"pingPacket" validate:"required"` // Ping 包内容, 必填16字符以内 -} -type _TcpMainConfig struct { - CommonConfig _TcpCommonConfig `json:"commonConfig" validate:"required"` - HostConfig common.HostConfig `json:"hostConfig" validate:"required"` + Host string `json:"host" validate:"required" title:"服务地址"` + Port int `json:"port" validate:"required" title:"服务端口"` + Timeout int `json:"timeout,omitempty" title:"连接超时"` } type TTcpTarget struct { typex.XStatus @@ -52,19 +50,15 @@ func NewTTcpTarget(e typex.RuleX) typex.XTarget { ht := new(TTcpTarget) ht.RuleEngine = e ht.mainConfig = _TcpMainConfig{ - CommonConfig: _TcpCommonConfig{ - DataMode: "RAW_STRING", - AllowPing: func() *bool { - b := true - return &b - }(), - PingPacket: "HR0001", // 默认每隔5秒发送PING包 - }, - HostConfig: common.HostConfig{ - Host: "127.0.0.1", - Port: 2585, - Timeout: 3000, - }, + DataMode: "RAW_STRING", + AllowPing: func() *bool { + b := true + return &b + }(), + PingPacket: "HR0001", // 默认每隔5秒发送PING包 + Host: "127.0.0.1", + Port: 2585, + Timeout: 3000, } ht.status = typex.SOURCE_DOWN return ht @@ -82,7 +76,7 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { ht.Ctx = cctx.Ctx ht.CancelCTX = cctx.CancelCTX var err error - host := fmt.Sprintf("%s:%d", ht.mainConfig.HostConfig.Host, ht.mainConfig.HostConfig.Port) + host := fmt.Sprintf("%s:%d", ht.mainConfig.Host, ht.mainConfig.Port) serverAddr, err := net.ResolveTCPAddr("tcp", host) if err != nil { return err @@ -94,7 +88,7 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { if err != nil { return err } - if *ht.mainConfig.CommonConfig.AllowPing { + if *ht.mainConfig.AllowPing { go func(ht *TTcpTarget) { for { select { @@ -107,10 +101,10 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { } } ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.Timeout) * time.Millisecond)), ) - _, err1 := ht.client.Write([]byte(ht.mainConfig.CommonConfig.PingPacket)) + _, err1 := ht.client.Write([]byte(ht.mainConfig.PingPacket)) ht.client.SetReadDeadline(time.Time{}) if err1 != nil { glogger.GLogger.Error("TTcpTarget Ping Error:", err1) @@ -139,9 +133,9 @@ func (ht *TTcpTarget) To(data interface{}) (interface{}, error) { if ht.client != nil { switch s := data.(type) { case string: - if ht.mainConfig.CommonConfig.DataMode == "RAW_STRING" { + if ht.mainConfig.DataMode == "RAW_STRING" { ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.Timeout) * time.Millisecond)), ) _, err0 := ht.client.Write([]byte(s)) @@ -150,13 +144,13 @@ func (ht *TTcpTarget) To(data interface{}) (interface{}, error) { return 0, err0 } } - if ht.mainConfig.CommonConfig.DataMode == "HEX_STRING" { + if ht.mainConfig.DataMode == "HEX_STRING" { dByte, err1 := hex.DecodeString(s) if err1 != nil { return 0, err1 } ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.Timeout) * time.Millisecond)), ) _, err0 := ht.client.Write(dByte) From 03e8565e816a3adaf06685dcb1c893e59f4919f0 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 16 Nov 2023 17:22:03 +0800 Subject: [PATCH 003/138] dev: optimize install script --- release_pkg.sh | 2 +- script/readme-daemon.md | 26 ++++ script/{readme.md => readme-systemctl.md} | 0 script/rulex_install.bat | 25 ++++ script/rulex_uninstall.bat | 23 ++++ script/rulexd.sh | 159 ---------------------- 6 files changed, 75 insertions(+), 160 deletions(-) create mode 100644 script/readme-daemon.md rename script/{readme.md => readme-systemctl.md} (100%) create mode 100644 script/rulex_install.bat create mode 100644 script/rulex_uninstall.bat delete mode 100644 script/rulexd.sh diff --git a/release_pkg.sh b/release_pkg.sh index 3a885353a..a9203342f 100755 --- a/release_pkg.sh +++ b/release_pkg.sh @@ -19,7 +19,7 @@ create_pkg() { chmod +x ./${APP} calculate_and_save_md5 ./${APP} else - files_to_include="$files_to_include_exe" + files_to_include="$files_to_include_exe ./script/*.bat" mv ./${APP}-$target.exe ./${APP}.exe calculate_and_save_md5 ./${APP}.exe fi diff --git a/script/readme-daemon.md b/script/readme-daemon.md new file mode 100644 index 000000000..91e6afdd8 --- /dev/null +++ b/script/readme-daemon.md @@ -0,0 +1,26 @@ + +# 通用Linux +这个脚本是针对无systemctl支持的系统使用。 + +- 安装服务:`bash ./rulex_daemon.sh install` +- 启动服务:`bash ./rulex_daemon.sh start` +- 停止服务:`bash ./rulex_daemon.sh stop` +- 重启服务:`bash ./rulex_daemon.sh restart` +- 禁用服务:`bash ./rulex_daemon.sh disable` +- 启用服务:`bash ./rulex_daemon.sh enable` +- 卸载服务:`bash ./rulex_daemon.sh uninstall` \ No newline at end of file diff --git a/script/readme.md b/script/readme-systemctl.md similarity index 100% rename from script/readme.md rename to script/readme-systemctl.md diff --git a/script/rulex_install.bat b/script/rulex_install.bat new file mode 100644 index 000000000..f1dce5257 --- /dev/null +++ b/script/rulex_install.bat @@ -0,0 +1,25 @@ +rem Copyright (C) 2023 wwhai +rem +rem This program is free software: you can redistribute it and/or modify +rem it under the terms of the GNU Affero General Public License as +rem published by the Free Software Foundation, either version 3 of the +rem License, or (at your option) any later version. +rem +rem This program is distributed in the hope that it will be useful, +rem but WITHOUT ANY WARRANTY; without even the implied warranty of +rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +rem GNU Affero General Public License for more details. +rem +rem You should have received a copy of the GNU Affero General Public License +rem along with this program. If not, see . + +@echo off + +set SERVICE_NAME=RulexService +set BINARY_PATH=%CD%\rulex.exe +set CONFIG_PATH=%CD%\rulex.ini + +sc create %SERVICE_NAME% binPath= "%BINARY_PATH% run -config %CONFIG_PATH%" start= auto DisplayName= RulexService + +echo Service created successfully. + diff --git a/script/rulex_uninstall.bat b/script/rulex_uninstall.bat new file mode 100644 index 000000000..8005723b5 --- /dev/null +++ b/script/rulex_uninstall.bat @@ -0,0 +1,23 @@ +rem Copyright (C) 2023 wwhai +rem +rem This program is free software: you can redistribute it and/or modify +rem it under the terms of the GNU Affero General Public License as +rem published by the Free Software Foundation, either version 3 of the +rem License, or (at your option) any later version. +rem +rem This program is distributed in the hope that it will be useful, +rem but WITHOUT ANY WARRANTY; without even the implied warranty of +rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +rem GNU Affero General Public License for more details. +rem +rem You should have received a copy of the GNU Affero General Public License +rem along with this program. If not, see . + +@echo off + +set SERVICE_NAME=RulexService + +sc stop %SERVICE_NAME% +sc delete %SERVICE_NAME% + +echo Service deleted successfully. diff --git a/script/rulexd.sh b/script/rulexd.sh deleted file mode 100644 index 7d363712c..000000000 --- a/script/rulexd.sh +++ /dev/null @@ -1,159 +0,0 @@ -#!/bin/bash -RESET='\033[0m' -RED='\033[31m' -BLUE='\033[34m' -YELLOW='\033[33m' - -# 打印红色文本 -echo_red() { - echo -e "${RED}$1${RESET}" -} - -# 打印蓝色文本 -echo_blue() { - echo -e "${BLUE}$1${RESET}" -} - -# 打印黄色文本 -echo_yellow() { - echo -e "${YELLOW}$1${RESET}" -} -install(){ - # check_deps - local source_dir="$PWD" - local service_file="/etc/systemd/system/rulex.service" - local executable="/usr/local/rulex" - local working_directory="/usr/local/" - local config_file="/usr/local/rulex.ini" - local db_file="/usr/local/rulex.db" -cat > "$service_file" << EOL -[Unit] -Description=Rulex Daemon -After=network.target - -[Service] -Environment="ARCHSUPPORT=EEKITH3" -WorkingDirectory=$working_directory -ExecStart=$executable run -config=$config_file -db=$db_file -Restart=always -User=root -Group=root -StartLimitInterval=0 -RestartSec=5 -[Install] -WantedBy=multi-user.target -EOL - chmod +x $source_dir/rulex - cp "$source_dir/rulex" "$executable" - cp "$source_dir/rulex.ini" "$config_file" - systemctl daemon-reload - systemctl enable rulex - systemctl start rulex - if [ $? -eq 0 ]; then - echo "[√] Rulex service has been created and extracted." - else - echo "[x] Failed to create the Rulex service or extract files." - fi - exit 0 -} - -start(){ - systemctl daemon-reload - systemctl start rulex - echo "[√] RULEX started as a daemon." - exit 0 -} -status(){ - systemctl status rulex -} -restart(){ - systemctl stop rulex - start -} - -stop(){ - systemctl stop rulex - echo "[√] Service Rulex has been stopped." -} -remove_files(){ - if ls $1 1> /dev/null 2>&1; then - rm $1 - echo "[!] $1 files removed." - else - echo "[#] $1 files not found. No need to remove." - fi -} -uninstall(){ - local working_directory="/usr/local" - systemctl stop rulex - systemctl disable rulex - remove_files /etc/systemd/system/rulex.service - remove_files $working_directory/rulex - remove_files $working_directory/rulex.ini - remove_files $working_directory/rulex.db - remove_files $working_directory/*.txt - remove_files $working_directory/*.txt.gz - systemctl daemon-reload - systemctl reset-failed - echo "[√] Rulex has been uninstalled." -} - -check_deps() { - # Check if ffmpeg is installed - echo_yellow "[·] Check necessary software" - if command -v ffmpeg >/dev/null 2>&1; then - echo "[=] ffmpeg is installed" - else - echo "!!! ffmpeg is not installed, Please install ffmpeg, you can go to install document: https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu" - exit 1 - fi - # Check if ttyd is installed - if command -v ttyd >/dev/null 2>&1; then - echo "[=] ttyd is installed" - else - echo "!!! ttyd is not installed, Please install ttyd, you can go to install document: https://github.com/tsl0922/ttyd" - exit 1 - fi - echo_yellow "[√] All necessary software is installed" -} -# create a default user -create_user(){ - response=$(curl -X POST -H "Content-Type: application/json" -d '{ - "role": "admin", - "username": "admin", - "password": "admin", - "description": "system admin" - }' http://127.0.0.1:2580/api/v1/users -w "%{http_code}") - - if [ "$response" = "201" ]; then - echo "[√] User created" - else - echo "[x] User creation failed" - fi - -} -# -# -# -main(){ - case "$1" in - "install" | "start" | "restart" | "stop" | "uninstall" | "create_user" | "status") - $1 - ;; - *) - echo "[x] Invalid command: $1" - echo "[?] Usage: $0 " - exit 1 - ;; - esac - exit 0 -} -#=========================================== -# main -#=========================================== -if [ "$(id -u)" != "0" ]; then - echo "[x] This script must be run as root" - exit 1 -else - main $1 -fi \ No newline at end of file From 764e228588e62b710ba8ae6fdd3960f4d9e77336 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 16 Nov 2023 17:24:18 +0800 Subject: [PATCH 004/138] dev: update doc --- script/readme-daemon.md | 91 +++++++++++++++++++++++++++----------- script/readme-systemctl.md | 34 ++++++-------- 2 files changed, 79 insertions(+), 46 deletions(-) diff --git a/script/readme-daemon.md b/script/readme-daemon.md index 91e6afdd8..346f8d4ad 100644 --- a/script/readme-daemon.md +++ b/script/readme-daemon.md @@ -1,26 +1,67 @@ - -# 通用Linux -这个脚本是针对无systemctl支持的系统使用。 - -- 安装服务:`bash ./rulex_daemon.sh install` -- 启动服务:`bash ./rulex_daemon.sh start` -- 停止服务:`bash ./rulex_daemon.sh stop` -- 重启服务:`bash ./rulex_daemon.sh restart` -- 禁用服务:`bash ./rulex_daemon.sh disable` -- 启用服务:`bash ./rulex_daemon.sh enable` -- 卸载服务:`bash ./rulex_daemon.sh uninstall` \ No newline at end of file +下面的脚本一定要在root权限下执行,或者使用sudo。 +- 安装 + ```sh + ./rulex_daemon.sh install + ``` +- 启动 + ```sh + ./rulex_daemon.sh start + ``` +- 状态 + ```sh + ./rulex_daemon.sh status + ``` +- 停止 + ```sh + ./rulex_daemon.sh stop + ``` +- 卸载 + ```sh + ./rulex_daemon.sh uninstall + ``` +## 操作演示 +```sh +rer@revb-h3:~/Desktop/rulex$ unzip rulex-arm32linux-v0.6.2.zip -d rulex +Archive: rulex-arm32linux-v0.6.2.zip + inflating: rulex/rulex + inflating: rulex/LICENSE + inflating: rulex/rulex.ini + inflating: rulex/rulex_daemon.sh +rer@revb-h3:~/Desktop/rulex$ ll +total 16540 +drwxrwxrwx 3 rer rer 4096 Sep 4 21:00 ./ +drwxrwxrwx 3 rer rer 4096 May 19 2022 ../ +drwxrwxr-x 2 rer rer 4096 Sep 4 21:00 rulex/ +-rw-rw-r-- 1 rer rer 16921343 Sep 4 21:00 rulex-arm32linux-v0.6.2.zip +rer@revb-h3:~/Desktop/rulex$ cd rulex/ +rer@revb-h3:~/Desktop/rulex/rulex$ ll +total 45848 +drwxrwxr-x 2 rer rer 4096 Sep 4 21:00 ./ +drwxrwxrwx 3 rer rer 4096 Sep 4 21:00 ../ +-rwxrwxrwx 1 rer rer 34523 Sep 4 20:51 LICENSE* +-rwxrwxrwx 1 rer rer 46891964 Sep 4 20:52 rulex* +-rwxrwxrwx 1 rer rer 2104 Sep 4 20:51 rulex_daemon.sh* +-rwxrwxrwx 1 rer rer 2605 Sep 4 20:51 rulex.ini* +rer@revb-h3:~/Desktop/rulex/rulex$ ./rulex_daemon.sh install +This script must be run as root +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh install +Created symlink /etc/systemd/system/multi-user.target.wants/rulex.service → /etc/systemd/system/rulex.service. +Rulex service has been created and extracted. +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh start +RULEX started as a daemon. +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh restart +RULEX started as a daemon. +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh stop +Service Rulex has been stopped. +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh uninstall +Removed /etc/systemd/system/multi-user.target.wants/rulex.service. +Rulex has been uninstalled. +``` \ No newline at end of file diff --git a/script/readme-systemctl.md b/script/readme-systemctl.md index bc87965ae..6de19dc67 100644 --- a/script/readme-systemctl.md +++ b/script/readme-systemctl.md @@ -9,40 +9,32 @@ unzip rulex-arm32linux-v0.6.2.zip -d rulex 下面的脚本一定要在root权限下执行,或者使用sudo。 - 安装 ```sh - ./rulexd.sh install + ./rulex_systemctl.sh install ``` - 启动 ```sh - ./rulexd.sh start + ./rulex_systemctl.sh start ``` - 状态 ```sh - ./rulexd.sh status + ./rulex_systemctl.sh status ``` - 停止 ```sh - ./rulexd.sh stop + ./rulex_systemctl.sh stop ``` - 卸载 ```sh - ./rulexd.sh uninstall + ./rulex_systemctl.sh uninstall ``` ## 操作演示 ```sh rer@revb-h3:~/Desktop/rulex$ unzip rulex-arm32linux-v0.6.2.zip -d rulex -Archive: rulex-arm32linux-v0.6.2.zip - End-of-central-directory signature not found. Either this file is not - a zipfile, or it constitutes one disk of a multi-part archive. In the - latter case the central directory and zipfile comment will be found on - the last disk(s) of this archive. -unzip: cannot find zipfile directory in one of rulex-arm32linux-v0.6.2.zip or - rulex-arm32linux-v0.6.2.zip.zip, and cannot find rulex-arm32linux-v0.6.2.zip.ZIP, period. -rer@revb-h3:~/Desktop/rulex$ unzip rulex-arm32linux-v0.6.2.zip -d rulex Archive: rulex-arm32linux-v0.6.2.zip inflating: rulex/rulex inflating: rulex/LICENSE inflating: rulex/rulex.ini - inflating: rulex/rulexd.sh + inflating: rulex/rulex_systemctl.sh rer@revb-h3:~/Desktop/rulex$ ll total 16540 drwxrwxrwx 3 rer rer 4096 Sep 4 21:00 ./ @@ -56,20 +48,20 @@ drwxrwxr-x 2 rer rer 4096 Sep 4 21:00 ./ drwxrwxrwx 3 rer rer 4096 Sep 4 21:00 ../ -rwxrwxrwx 1 rer rer 34523 Sep 4 20:51 LICENSE* -rwxrwxrwx 1 rer rer 46891964 Sep 4 20:52 rulex* --rwxrwxrwx 1 rer rer 2104 Sep 4 20:51 rulexd.sh* +-rwxrwxrwx 1 rer rer 2104 Sep 4 20:51 rulex_systemctl.sh* -rwxrwxrwx 1 rer rer 2605 Sep 4 20:51 rulex.ini* -rer@revb-h3:~/Desktop/rulex/rulex$ ./rulexd.sh install +rer@revb-h3:~/Desktop/rulex/rulex$ ./rulex_systemctl.sh install This script must be run as root -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulexd.sh install +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh install Created symlink /etc/systemd/system/multi-user.target.wants/rulex.service → /etc/systemd/system/rulex.service. Rulex service has been created and extracted. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulexd.sh start +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh start RULEX started as a daemon. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulexd.sh restart +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh restart RULEX started as a daemon. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulexd.sh stop +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh stop Service Rulex has been stopped. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulexd.sh uninstall +rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh uninstall Removed /etc/systemd/system/multi-user.target.wants/rulex.service. Rulex has been uninstalled. ``` \ No newline at end of file From 3cd0894be84459269a3e698a0673d9695a70f1cd Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 16 Nov 2023 17:26:27 +0800 Subject: [PATCH 005/138] dev: add new system sctipt --- script/rulex-daemon.sh | 118 +++++++++++++++++++++++++++++++ script/rulex-systemctl.sh | 141 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 script/rulex-daemon.sh create mode 100644 script/rulex-systemctl.sh diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh new file mode 100644 index 000000000..a6dc91dcc --- /dev/null +++ b/script/rulex-daemon.sh @@ -0,0 +1,118 @@ +#!/bin/sh /etc/rc.common +# rulex_daemon - Rulex daemon script for Linux + +START=99 +USE_PROCD=1 + +# Check if the service is disabled +[ -e /etc/config/rulex_daemon ] && . /etc/config/rulex_daemon + +working_directory="./" + +# Function to copy files to /usr/local +install_files() { + cp "$working_directory"/rulex /usr/local/ + cp "$working_directory"/rulex.ini /usr/local/ +} + +# Function to uninstall the service +uninstall_files() { + rm -f /usr/local/rulex + rm -f /usr/local/rulex.ini + rm -f /usr/local/rulex.db + rm -f /usr/local/*.txt + rm -rf /usr/local/upload/ + rm -f /usr/local/*.txt.gz +} + +start_service() { + if [ "$DISABLED" -eq 0 ]; then + procd_open_instance + procd_set_param command /usr/local/rulex run -config /usr/local/rulex.ini + procd_set_param respawn + procd_set_param timeout 5 # 5 seconds timeout + procd_close_instance + else + echo "Service is disabled. To enable, run: /etc/init.d/rulex_daemon enable" + fi +} + +stop_service() { + procd_close_instance +} + +# Function to disable the service +disable_service() { + [ -e /etc/config/rulex_daemon ] && echo 'DISABLED=1' > /etc/config/rulex_daemon + /etc/init.d/rulex_daemon stop + /etc/init.d/rulex_daemon disable +} + +# Function to enable the service +enable_service() { + [ -e /etc/config/rulex_daemon ] && rm /etc/config/rulex_daemon + /etc/init.d/rulex_daemon enable +} + +# Function to uninstall the service +uninstall_service() { + uninstall_files + /etc/init.d/rulex_daemon stop + /etc/init.d/rulex_daemon disable + rm /etc/init.d/rulex_daemon + rm /etc/config/rulex_daemon + echo "Rulex uninstallation complete." +} + +# Function to check service status +status_service() { + if procd_status rulex_daemon > /dev/null; then + echo "Rulex is running." + else + echo "Rulex is not running." + fi +} + +service_triggers() { + procd_add_reload_trigger "rulex" +} + +reload_service() { + procd_send_signal rulex HUP +} + +shutdown_service() { + procd_close_instance +} + +service_error() { + procd_close_instance + echo "Error starting rulex_daemon" >&2 +} + +run() { + case "$1" in + install) + install_files + ;; + start) + start_service + ;; + restart) + reload_service + ;; + stop) + stop_service + ;; + uninstall) + uninstall_service + ;; + status) + status_service + ;; + *) + echo "Usage: $0 {install|start|restart|stop|uninstall|status}" + exit 1 + ;; + esac +} diff --git a/script/rulex-systemctl.sh b/script/rulex-systemctl.sh new file mode 100644 index 000000000..126a21453 --- /dev/null +++ b/script/rulex-systemctl.sh @@ -0,0 +1,141 @@ +#!/bin/bash +RESET='\033[0m' +RED='\033[31m' +BLUE='\033[34m' +YELLOW='\033[33m' + +# 打印红色文本 +echo_red() { + echo -e "${RED}$1${RESET}" +} + +# 打印蓝色文本 +echo_blue() { + echo -e "${BLUE}$1${RESET}" +} + +# 打印黄色文本 +echo_yellow() { + echo -e "${YELLOW}$1${RESET}" +} +install(){ + local source_dir="$PWD" + local service_file="/etc/systemd/system/rulex.service" + local executable="/usr/local/rulex" + local working_directory="/usr/local/" + local config_file="/usr/local/rulex.ini" + local db_file="/usr/local/rulex.db" +cat > "$service_file" << EOL +[Unit] +Description=Rulex Daemon +After=network.target + +[Service] +Environment="ARCHSUPPORT=EEKITH3" +WorkingDirectory=$working_directory +ExecStart=$executable run -config=$config_file -db=$db_file +Restart=always +User=root +Group=root +StartLimitInterval=0 +RestartSec=5 +[Install] +WantedBy=multi-user.target +EOL + chmod +x $source_dir/rulex + cp "$source_dir/rulex" "$executable" + cp "$source_dir/rulex.ini" "$config_file" + systemctl daemon-reload + systemctl enable rulex + systemctl start rulex + if [ $? -eq 0 ]; then + echo "[√] Rulex service has been created and extracted." + else + echo "[x] Failed to create the Rulex service or extract files." + fi + exit 0 +} + +start(){ + systemctl daemon-reload + systemctl start rulex + echo "[√] RULEX started as a daemon." + exit 0 +} +status(){ + systemctl status rulex +} +restart(){ + systemctl stop rulex + start +} + +stop(){ + systemctl stop rulex + echo "[√] Service Rulex has been stopped." +} +remove_files(){ + if ls $1 1> /dev/null 2>&1; then + rm $1 + echo "[!] $1 files removed." + else + echo "[#] $1 files not found. No need to remove." + fi +} +uninstall(){ + local working_directory="/usr/local" + systemctl stop rulex + systemctl disable rulex + remove_files /etc/systemd/system/rulex.service + remove_files $working_directory/rulex + remove_files $working_directory/rulex.ini + remove_files $working_directory/rulex.db + remove_files $working_directory/*.txt + remove_files $working_directory/upload/ + remove_files $working_directory/*.txt.gz + systemctl daemon-reload + systemctl reset-failed + echo "[√] Rulex has been uninstalled." +} + +# create a default user +create_user(){ + response=$(curl -X POST -H "Content-Type: application/json" -d '{ + "role": "admin", + "username": "admin", + "password": "admin", + "description": "system admin" + }' http://127.0.0.1:2580/api/v1/users -w "%{http_code}") + + if [ "$response" = "201" ]; then + echo "[√] User created" + else + echo "[x] User creation failed" + fi + +} +# +# +# +main(){ + case "$1" in + "install" | "start" | "restart" | "stop" | "uninstall" | "create_user" | "status") + $1 + ;; + *) + echo "[x] Invalid command: $1" + echo "[?] Usage: $0 " + exit 1 + ;; + esac + exit 0 +} +#=========================================== +# main +#=========================================== +if [ "$(id -u)" != "0" ]; then + echo "[x] This script must be run as root" + exit 1 +else + main $1 +fi \ No newline at end of file From 4394f750d052c1a8d1b755a84fdbacd7a41383d6 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 17 Nov 2023 15:45:55 +0800 Subject: [PATCH 006/138] dev: update user api --- plugin/http_server/apis/rule_api.go | 33 +++++---------------------- plugin/http_server/apis/user_api.go | 32 ++++++++++++++++++++++++++ plugin/http_server/http_api_server.go | 3 ++- plugin/http_server/service/dao.go | 12 ++++------ 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/plugin/http_server/apis/rule_api.go b/plugin/http_server/apis/rule_api.go index 6023fe969..85c369010 100644 --- a/plugin/http_server/apis/rule_api.go +++ b/plugin/http_server/apis/rule_api.go @@ -55,32 +55,10 @@ func RuleDetail(c *gin.Context, ruleEngine typex.RuleX) { // Get all rules func Rules(c *gin.Context, ruleEngine typex.RuleX) { - uuid, _ := c.GetQuery("uuid") - if uuid == "" { - DataList := []ruleVo{} - allRules, _ := service.GetAllMRule() - for _, rule := range allRules { - DataList = append(DataList, ruleVo{ - UUID: rule.UUID, - Name: rule.Name, - Type: rule.Type, - Status: 1, - Description: rule.Description, - FromSource: rule.FromSource, - FromDevice: rule.FromDevice, - Success: rule.Success, - Failed: rule.Failed, - Actions: rule.Actions, - }) - } - c.JSON(common.HTTP_OK, common.OkWithData(DataList)) - } else { - rule, err := service.GetMRuleWithUUID(uuid) - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - c.JSON(common.HTTP_OK, common.OkWithData(ruleVo{ + DataList := []ruleVo{} + allRules, _ := service.GetAllMRule() + for _, rule := range allRules { + DataList = append(DataList, ruleVo{ UUID: rule.UUID, Name: rule.Name, Type: rule.Type, @@ -91,8 +69,9 @@ func Rules(c *gin.Context, ruleEngine typex.RuleX) { Success: rule.Success, Failed: rule.Failed, Actions: rule.Actions, - })) + }) } + c.JSON(common.HTTP_OK, common.OkWithData(DataList)) } // Create rule diff --git a/plugin/http_server/apis/user_api.go b/plugin/http_server/apis/user_api.go index 7c7603f57..7c396f76b 100644 --- a/plugin/http_server/apis/user_api.go +++ b/plugin/http_server/apis/user_api.go @@ -85,6 +85,38 @@ func CreateUser(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error("user already exists:"+form.Username)) } +// UpdateUser +func UpdateUser(c *gin.Context, ruleEngine typex.RuleX) { + type Form struct { + Username string `json:"username" binding:"required"` + Password string `json:"password" binding:"required"` + Description string `json:"description"` + } + form := Form{} + if err := c.ShouldBindJSON(&form); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + if !isLengthBetween8And16(form.Username) { + c.JSON(common.HTTP_OK, common.Error("Username Length must Between 8 ~ 16")) + return + } + if !isLengthBetween8And16(form.Password) { + c.JSON(common.HTTP_OK, common.Error("Password Length must Between 8 ~ 16")) + return + } + + if err := service.UpdateMUser(&model.MUser{ + Username: form.Username, + Password: md5Hash(form.Password), + Description: form.Description, + }); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) +} + /* * * Md5 计算 diff --git a/plugin/http_server/http_api_server.go b/plugin/http_server/http_api_server.go index 8bc9f2fa8..90eb43a7a 100644 --- a/plugin/http_server/http_api_server.go +++ b/plugin/http_server/http_api_server.go @@ -251,8 +251,9 @@ func (hs *ApiServerPlugin) LoadRoute() { // userApi := server.RouteGroup(server.ContextUrl("/users")) { - userApi.GET(("/"), server.AddRoute(apis.Users)) + // userApi.GET(("/"), server.AddRoute(apis.Users)) userApi.POST(("/"), server.AddRoute(apis.CreateUser)) + userApi.PUT(("/update"), server.AddRoute(apis.UpdateUser)) userApi.GET(("/detail"), server.AddRoute(apis.UserDetail)) userApi.POST(("/logout"), server.AddRoute(apis.LogOut)) diff --git a/plugin/http_server/service/dao.go b/plugin/http_server/service/dao.go index 2e8ab299e..6408fe0c3 100644 --- a/plugin/http_server/service/dao.go +++ b/plugin/http_server/service/dao.go @@ -147,14 +147,10 @@ func InitMUser(o *model.MUser) error { return interdb.DB().Table("m_users").FirstOrCreate(o).Error } -func UpdateMUser(uuid string, o *model.MUser) error { - m := model.MUser{} - if err := interdb.DB().Where("uuid=?", uuid).First(&m).Error; err != nil { - return err - } else { - interdb.DB().Model(m).Updates(*o) - return nil - } +func UpdateMUser(o *model.MUser) error { + interdb.DB().Model(o).Where("username=?", o.Username).Updates(*o) + return nil + } // ----------------------------------------------------------------------------------- From eef288513cb2b8d8f37f377cff75a0aaf133bd43 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 17 Nov 2023 16:40:40 +0800 Subject: [PATCH 007/138] dev: rename some paths --- plugin/cs104_server/cs_104_server.go | 4 +- plugin/demo_plugin/demo_plugin.go | 4 +- plugin/devguide.md | 4 +- .../generic_watchdog_linux.go | 4 +- .../generic_watchdog_windows.go | 4 +- plugin/http_server/apis/inend_api.go | 61 +++------- plugin/http_server/apis/rule_api.go | 76 +++++------- plugin/http_server/http_api_server.go | 114 ++++++------------ plugin/icmp_sender/icmp_sender.go | 4 +- plugin/modbus_scanner/modbus_scanner.go | 4 +- plugin/modbuscrc_tools/modbuscrc_tools.go | 4 +- plugin/mqtt_server/mqtt_server.go | 8 +- plugin/net_discover/net_boardcast.go | 4 +- plugin/sensor_server/sensor_server.go | 4 +- plugin/ttyd_terminal/ttyd_terminal.go | 4 +- plugin/usb_monitor/usb_mnitor_windows.go | 4 +- plugin/usb_monitor/usb_monitor_linux.go | 4 +- 17 files changed, 118 insertions(+), 193 deletions(-) diff --git a/plugin/cs104_server/cs_104_server.go b/plugin/cs104_server/cs_104_server.go index e834f3466..d71e35271 100644 --- a/plugin/cs104_server/cs_104_server.go +++ b/plugin/cs104_server/cs_104_server.go @@ -96,8 +96,8 @@ func (cs *cs104Server) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/demo_plugin/demo_plugin.go b/plugin/demo_plugin/demo_plugin.go index 015c5a645..cd23dd78e 100644 --- a/plugin/demo_plugin/demo_plugin.go +++ b/plugin/demo_plugin/demo_plugin.go @@ -33,8 +33,8 @@ func (hh *DemoPlugin) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/devguide.md b/plugin/devguide.md index 0cf1a3a86..d31832aa4 100644 --- a/plugin/devguide.md +++ b/plugin/devguide.md @@ -81,8 +81,8 @@ func (hh *DemoPlugin) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/generic_watchdog/generic_watchdog_linux.go b/plugin/generic_watchdog/generic_watchdog_linux.go index 90efa7be9..595f03192 100644 --- a/plugin/generic_watchdog/generic_watchdog_linux.go +++ b/plugin/generic_watchdog/generic_watchdog_linux.go @@ -112,8 +112,8 @@ func (hh *genericWatchDog) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/generic_watchdog/generic_watchdog_windows.go b/plugin/generic_watchdog/generic_watchdog_windows.go index a066a10e4..37add8a1a 100644 --- a/plugin/generic_watchdog/generic_watchdog_windows.go +++ b/plugin/generic_watchdog/generic_watchdog_windows.go @@ -57,8 +57,8 @@ func (hh *genericWatchDog) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/http_server/apis/inend_api.go b/plugin/http_server/apis/inend_api.go index ea02dc48d..55a403d53 100644 --- a/plugin/http_server/apis/inend_api.go +++ b/plugin/http_server/apis/inend_api.go @@ -38,52 +38,29 @@ func InEndDetail(c *gin.Context, ruleEngine typex.RuleX) { // Get all inends func InEnds(c *gin.Context, ruleEngine typex.RuleX) { - uuid, _ := c.GetQuery("uuid") - if uuid == "" { - inEnds := []typex.InEnd{} - for _, v := range service.AllMInEnd() { - var inEnd *typex.InEnd - if inEnd = ruleEngine.GetInEnd(v.UUID); inEnd == nil { - tmpInEnd := typex.InEnd{ - UUID: v.UUID, - Type: typex.InEndType(v.Type), - Name: v.Name, - Description: v.Description, - BindRules: map[string]typex.Rule{}, - Config: v.GetConfig(), - State: typex.SOURCE_STOP, - } - inEnds = append(inEnds, tmpInEnd) - } - if inEnd != nil { - inEnd.State = inEnd.Source.Status() - inEnds = append(inEnds, *inEnd) + + inEnds := []typex.InEnd{} + for _, v := range service.AllMInEnd() { + var inEnd *typex.InEnd + if inEnd = ruleEngine.GetInEnd(v.UUID); inEnd == nil { + tmpInEnd := typex.InEnd{ + UUID: v.UUID, + Type: typex.InEndType(v.Type), + Name: v.Name, + Description: v.Description, + BindRules: map[string]typex.Rule{}, + Config: v.GetConfig(), + State: typex.SOURCE_STOP, } + inEnds = append(inEnds, tmpInEnd) } - c.JSON(common.HTTP_OK, common.OkWithData(inEnds)) - return - } - Model, err := service.GetMInEndWithUUID(uuid) - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - inEnd := ruleEngine.GetInEnd(Model.UUID) - if inEnd == nil { - tmpInEnd := typex.InEnd{ - UUID: Model.UUID, - Type: typex.InEndType(Model.Type), - Name: Model.Name, - Description: Model.Description, - BindRules: map[string]typex.Rule{}, - Config: Model.GetConfig(), - State: typex.SOURCE_STOP, + if inEnd != nil { + inEnd.State = inEnd.Source.Status() + inEnds = append(inEnds, *inEnd) } - c.JSON(common.HTTP_OK, common.OkWithData(tmpInEnd)) - return } - inEnd.State = inEnd.Source.Status() - c.JSON(common.HTTP_OK, common.OkWithData(inEnd)) + c.JSON(common.HTTP_OK, common.OkWithData(inEnds)) + return } diff --git a/plugin/http_server/apis/rule_api.go b/plugin/http_server/apis/rule_api.go index 85c369010..843c33455 100644 --- a/plugin/http_server/apis/rule_api.go +++ b/plugin/http_server/apis/rule_api.go @@ -119,29 +119,17 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } - // - mRule := &model.MRule{ - Name: form.Name, - Type: form.Type, - UUID: utils.RuleUuid(), - Description: form.Description, - FromSource: form.FromSource, - FromDevice: form.FromDevice, - Success: form.Success, - Failed: form.Failed, - Actions: form.Actions, - } rule := typex.NewLuaRule( ruleEngine, - mRule.UUID, - mRule.Name, - mRule.Description, - mRule.FromSource, - mRule.FromDevice, - mRule.Success, - mRule.Actions, - mRule.Failed) + utils.RuleUuid(), + form.Name, + form.Description, + form.FromSource, + form.FromDevice, + form.Success, + form.Actions, + form.Failed) ruleEngine.RemoveRule(rule.UUID) if err := ruleEngine.LoadRule(rule); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) @@ -154,18 +142,7 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) return } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range InEnd.BindRules { - ruleMap[rule] = rule - } - // 追加新的ID - ruleMap[inId] = mRule.UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } + BindRules := []string{rule.UUID} InEnd.BindRules = BindRules if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ BindRules: BindRules, @@ -174,6 +151,18 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { return } // SaveDB + // + mRule := &model.MRule{ + Name: form.Name, + Type: form.Type, + UUID: rule.UUID, + Description: form.Description, + FromSource: form.FromSource, + FromDevice: form.FromDevice, + Success: form.Success, + Failed: form.Failed, + Actions: form.Actions, + } if err := service.InsertMRule(mRule); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return @@ -193,18 +182,8 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) return } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range Device.BindRules { - ruleMap[rule] = rule - } - // 追加新的ID - ruleMap[devId] = mRule.UUID // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } + BindRules := []string{rule.UUID} Device.BindRules = BindRules if err := service.UpdateDevice(Device.UUID, &model.MDevice{ BindRules: BindRules, @@ -213,6 +192,17 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { return } // SaveDB + mRule := &model.MRule{ + Name: form.Name, + Type: form.Type, + UUID: rule.UUID, + Description: form.Description, + FromSource: form.FromSource, + FromDevice: form.FromDevice, + Success: form.Success, + Failed: form.Failed, + Actions: form.Actions, + } if err := service.InsertMRule(mRule); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return diff --git a/plugin/http_server/http_api_server.go b/plugin/http_server/http_api_server.go index 90eb43a7a..b8fd43958 100644 --- a/plugin/http_server/http_api_server.go +++ b/plugin/http_server/http_api_server.go @@ -222,25 +222,12 @@ func (hs *ApiServerPlugin) LoadRoute() { systemApi.GET(("/ping"), server.AddRoute(apis.Ping)) systemApi.POST(("/logout"), server.AddRoute(apis.LogOut)) } - // - // Get all inends - // - server.DefaultApiServer.Route().GET(server.ContextUrl("inends"), server.AddRoute(apis.InEnds)) - server.DefaultApiServer.Route().GET(server.ContextUrl("inends/detail"), server.AddRoute(apis.InEndDetail)) + // // // server.DefaultApiServer.Route().GET(server.ContextUrl("drivers"), server.AddRoute(apis.Drivers)) - // - // Get all outends - // - server.DefaultApiServer.Route().GET(server.ContextUrl("outends"), server.AddRoute(apis.OutEnds)) - server.DefaultApiServer.Route().GET(server.ContextUrl("outends/detail"), server.AddRoute(apis.OutEndDetail)) - // - // Get all rules - // - server.DefaultApiServer.Route().GET(server.ContextUrl("rules"), server.AddRoute(apis.Rules)) - server.DefaultApiServer.Route().GET(server.ContextUrl("rules/detail"), server.AddRoute(apis.RuleDetail)) + // // Get statistics data // @@ -268,49 +255,38 @@ func (hs *ApiServerPlugin) LoadRoute() { // server.DefaultApiServer.Route().GET(server.ContextUrl("info"), server.AddRoute(apis.Info)) // - // Create InEnd - // - server.DefaultApiServer.Route().POST(server.ContextUrl("inends"), server.AddRoute(apis.CreateInend)) - // - // Update Inend - // - server.DefaultApiServer.Route().PUT(server.ContextUrl("inends"), server.AddRoute(apis.UpdateInend)) - // - // 配置表 - // - server.DefaultApiServer.Route().GET(server.ContextUrl("inends/config"), server.AddRoute(apis.GetInEndConfig)) - // - // 数据模型表 - // - server.DefaultApiServer.Route().GET(server.ContextUrl("inends/models"), server.AddRoute(apis.GetInEndModels)) - // - // Create OutEnd - // - server.DefaultApiServer.Route().POST(server.ContextUrl("outends"), server.AddRoute(apis.CreateOutEnd)) - // - // Update OutEnd - // - server.DefaultApiServer.Route().PUT(server.ContextUrl("outends"), server.AddRoute(apis.UpdateOutEnd)) + InEndApi := server.RouteGroup(server.ContextUrl("/inends")) + + { + InEndApi.GET(("/detail"), server.AddRoute(apis.InEndDetail)) + InEndApi.GET(("/list"), server.AddRoute(apis.InEnds)) + InEndApi.POST(("/create"), server.AddRoute(apis.CreateInend)) + InEndApi.DELETE(("/delete"), server.AddRoute(apis.DeleteInEnd)) + InEndApi.PUT(("/update"), server.AddRoute(apis.UpdateInend)) + } + rulesApi := server.RouteGroup(server.ContextUrl("/rules")) { - rulesApi.POST(("/"), server.AddRoute(apis.CreateRule)) - rulesApi.PUT(("/"), server.AddRoute(apis.UpdateRule)) - rulesApi.DELETE(("/"), server.AddRoute(apis.DeleteRule)) + rulesApi.POST(("/create"), server.AddRoute(apis.CreateRule)) + rulesApi.PUT(("/update"), server.AddRoute(apis.UpdateRule)) + rulesApi.DELETE(("/delete"), server.AddRoute(apis.DeleteRule)) + rulesApi.GET(("/list"), server.AddRoute(apis.Rules)) + rulesApi.GET(("/detail"), server.AddRoute(apis.RuleDetail)) + // rulesApi.POST(("/testIn"), server.AddRoute(apis.TestSourceCallback)) rulesApi.POST(("/testOut"), server.AddRoute(apis.TestOutEndCallback)) rulesApi.POST(("/testDevice"), server.AddRoute(apis.TestDeviceCallback)) rulesApi.GET(("/byInend"), server.AddRoute(apis.ListByInend)) rulesApi.GET(("/byDevice"), server.AddRoute(apis.ListByDevice)) } - - // - // Delete inend by UUID - // - server.DefaultApiServer.Route().DELETE(server.ContextUrl("inends"), server.AddRoute(apis.DeleteInEnd)) - // - // Delete outEnd by UUID - // - server.DefaultApiServer.Route().DELETE(server.ContextUrl("outends"), server.AddRoute(apis.DeleteOutEnd)) + OutEndApi := server.RouteGroup(server.ContextUrl("/outends")) + { + OutEndApi.GET(("/detail"), server.AddRoute(apis.OutEndDetail)) + OutEndApi.GET(("/list"), server.AddRoute(apis.OutEnds)) + OutEndApi.POST(("/create"), server.AddRoute(apis.CreateOutEnd)) + OutEndApi.DELETE(("/delete"), server.AddRoute(apis.DeleteOutEnd)) + OutEndApi.PUT(("/update"), server.AddRoute(apis.UpdateOutEnd)) + } // // 验证 lua 语法 @@ -339,9 +315,9 @@ func (hs *ApiServerPlugin) LoadRoute() { // deviceApi := server.RouteGroup(server.ContextUrl("/devices")) { - deviceApi.POST(("/"), server.AddRoute(apis.CreateDevice)) - deviceApi.PUT(("/"), server.AddRoute(apis.UpdateDevice)) - deviceApi.DELETE(("/"), server.AddRoute(apis.DeleteDevice)) + deviceApi.POST(("/create"), server.AddRoute(apis.CreateDevice)) + deviceApi.PUT(("/update"), server.AddRoute(apis.UpdateDevice)) + deviceApi.DELETE(("/delete"), server.AddRoute(apis.DeleteDevice)) deviceApi.GET(("/detail"), server.AddRoute(apis.DeviceDetail)) deviceApi.POST(("/modbus/sheetImport"), server.AddRoute(apis.ModbusSheetImport)) deviceApi.PUT(("/modbus/point"), server.AddRoute(apis.UpdateModbusPoint)) @@ -356,23 +332,15 @@ func (hs *ApiServerPlugin) LoadRoute() { // ---------------------------------------------------------------------------------------------- appApi := server.RouteGroup(server.ContextUrl("/app")) { - appApi.GET(("/"), server.AddRoute(apis.Apps)) - appApi.POST(("/"), server.AddRoute(apis.CreateApp)) - appApi.PUT(("/"), server.AddRoute(apis.UpdateApp)) - appApi.DELETE(("/"), server.AddRoute(apis.RemoveApp)) + appApi.GET(("/list"), server.AddRoute(apis.Apps)) + appApi.POST(("/create"), server.AddRoute(apis.CreateApp)) + appApi.PUT(("/update"), server.AddRoute(apis.UpdateApp)) + appApi.DELETE(("/delete"), server.AddRoute(apis.RemoveApp)) appApi.PUT(("/start"), server.AddRoute(apis.StartApp)) appApi.PUT(("/stop"), server.AddRoute(apis.StopApp)) appApi.GET(("/detail"), server.AddRoute(apis.AppDetail)) } // ---------------------------------------------------------------------------------------------- - // AI BASE - // ---------------------------------------------------------------------------------------------- - aiApi := server.RouteGroup(server.ContextUrl("/aibase")) - { - aiApi.GET(("/"), server.AddRoute(apis.AiBase)) - aiApi.DELETE(("/"), server.AddRoute(apis.DeleteAiBase)) - } - // ---------------------------------------------------------------------------------------------- // Plugin // ---------------------------------------------------------------------------------------------- pluginsApi := server.RouteGroup(server.ContextUrl("/plugins")) @@ -396,19 +364,9 @@ func (hs *ApiServerPlugin) LoadRoute() { groupApi.GET("/detail", server.AddRoute(apis.GroupDetail)) groupApi.POST("/bind", server.AddRoute(apis.BindResource)) groupApi.PUT("/unbind", server.AddRoute(apis.UnBindResource)) - groupApi.DELETE("/", server.AddRoute(apis.DeleteGroup)) + groupApi.DELETE("/delete", server.AddRoute(apis.DeleteGroup)) } - // - // 协议应用管理 - // - protoAppApi := server.RouteGroup(server.ContextUrl("/protoapp")) - { - protoAppApi.POST("/create", server.AddRoute(apis.CreateProtocolApp)) - protoAppApi.DELETE("/delete", server.AddRoute(apis.DeleteProtocolApp)) - protoAppApi.PUT("/update", server.AddRoute(apis.UpdateProtocolApp)) - protoAppApi.GET("/list", server.AddRoute(apis.ListProtocolApp)) - } // // 大屏应用管理 // @@ -522,8 +480,8 @@ func (hs *ApiServerPlugin) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v1.0.0", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/icmp_sender/icmp_sender.go b/plugin/icmp_sender/icmp_sender.go index a2b4a62d3..b1321513d 100644 --- a/plugin/icmp_sender/icmp_sender.go +++ b/plugin/icmp_sender/icmp_sender.go @@ -40,8 +40,8 @@ func (hh *ICMPSender) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v1.0.0", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/modbus_scanner/modbus_scanner.go b/plugin/modbus_scanner/modbus_scanner.go index 96077d6f6..86f44631c 100644 --- a/plugin/modbus_scanner/modbus_scanner.go +++ b/plugin/modbus_scanner/modbus_scanner.go @@ -60,8 +60,8 @@ func (hh *modbusScanner) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/modbuscrc_tools/modbuscrc_tools.go b/plugin/modbuscrc_tools/modbuscrc_tools.go index b319fb36f..a30a8b02c 100644 --- a/plugin/modbuscrc_tools/modbuscrc_tools.go +++ b/plugin/modbuscrc_tools/modbuscrc_tools.go @@ -48,8 +48,8 @@ func (hh *modbusCRCCalculator) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/mqtt_server/mqtt_server.go b/plugin/mqtt_server/mqtt_server.go index 491a86895..e22ff5bdc 100644 --- a/plugin/mqtt_server/mqtt_server.go +++ b/plugin/mqtt_server/mqtt_server.go @@ -89,10 +89,10 @@ func (s *MqttServer) PluginMetaInfo() typex.XPluginMetaInfo { UUID: s.uuid, Name: "Light Weight MqttServer", Version: "v2.0.0", - Homepage: "https://github.com/lion-brave", - HelpLink: "https://github.com/lion-brave", - Author: "liyong", - Email: "liyong@gmail.com", + Homepage: "https://hootrhino.github.io", + HelpLink: "https://hootrhino.github.io", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/net_discover/net_boardcast.go b/plugin/net_discover/net_boardcast.go index 579ef893f..2ff07cf44 100644 --- a/plugin/net_discover/net_boardcast.go +++ b/plugin/net_discover/net_boardcast.go @@ -176,8 +176,8 @@ func (hh *NetDiscover) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/sensor_server/sensor_server.go b/plugin/sensor_server/sensor_server.go index 00bb68f20..43883b600 100644 --- a/plugin/sensor_server/sensor_server.go +++ b/plugin/sensor_server/sensor_server.go @@ -48,8 +48,8 @@ func (hh *SensorServer) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/ttyd_terminal/ttyd_terminal.go b/plugin/ttyd_terminal/ttyd_terminal.go index f18f30701..5b2dbedc6 100644 --- a/plugin/ttyd_terminal/ttyd_terminal.go +++ b/plugin/ttyd_terminal/ttyd_terminal.go @@ -86,8 +86,8 @@ func (hh *WebTTYPlugin) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://github.com/tsl0922/ttyd", HelpLink: "https://github.com/tsl0922/ttyd", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/usb_monitor/usb_mnitor_windows.go b/plugin/usb_monitor/usb_mnitor_windows.go index 43cadfea9..592fc7120 100644 --- a/plugin/usb_monitor/usb_mnitor_windows.go +++ b/plugin/usb_monitor/usb_mnitor_windows.go @@ -42,8 +42,8 @@ func (usbm *usbMonitor) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://github.com/hootrhino/rulex.git", HelpLink: "https://github.com/hootrhino/rulex.git", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } diff --git a/plugin/usb_monitor/usb_monitor_linux.go b/plugin/usb_monitor/usb_monitor_linux.go index 16b28d658..a6f6b0db8 100644 --- a/plugin/usb_monitor/usb_monitor_linux.go +++ b/plugin/usb_monitor/usb_monitor_linux.go @@ -164,8 +164,8 @@ func (usbm *usbMonitor) PluginMetaInfo() typex.XPluginMetaInfo { Version: "v0.0.1", Homepage: "https://hootrhino.github.io", HelpLink: "https://hootrhino.github.io", - Author: "wwhai", - Email: "cnwwhai@gmail.com", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", License: "MIT", } } From 73bab72bef6f7806552de8a520bda8699fb68520 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 17 Nov 2023 21:23:35 +0800 Subject: [PATCH 008/138] dev: regular some name; add license validate --- conf/licence.key | 1 + conf/licence.lic | 1 + conf/rulex.ini | 16 + engine/load_plugin.go | 13 - engine/runner.go | 22 +- plugin/cs104_server/cs_104_server.go | 2 +- plugin/demo_plugin/demo_plugin.go | 2 +- plugin/devguide.md | 2 +- .../generic_watchdog_linux.go | 2 +- .../generic_watchdog_windows.go | 2 +- plugin/http_server/http_api_server.go | 12 +- plugin/http_server/model/model.go | 13 - plugin/icmp_sender/icmp_sender.go | 2 +- plugin/license_manager/cert_codec.go | 50 --- plugin/license_manager/license_loader.go | 303 ------------------ plugin/license_manager/license_manager.go | 174 ++++------ plugin/license_manager/license_manager.md | 74 +---- plugin/license_manager/misc.go | 89 +++++ plugin/modbus_scanner/modbus_scanner.go | 2 +- plugin/modbuscrc_tools/modbuscrc_tools.go | 2 +- plugin/mqtt_server/mqtt_server.go | 2 +- plugin/net_discover/net_boardcast.go | 2 +- plugin/sensor_server/sensor_server.go | 2 +- plugin/telemetry/telemetry.go | 2 +- plugin/ttyd_terminal/ttyd_terminal.go | 2 +- plugin/usb_monitor/usb_mnitor_windows.go | 2 +- plugin/usb_monitor/usb_monitor_linux.go | 2 +- test/conf/licence.key | 1 + test/conf/licence.lic | 1 + test/conf/rulex.ini | 15 +- 30 files changed, 220 insertions(+), 595 deletions(-) create mode 100644 conf/licence.key create mode 100644 conf/licence.lic delete mode 100644 plugin/license_manager/cert_codec.go delete mode 100644 plugin/license_manager/license_loader.go create mode 100644 plugin/license_manager/misc.go create mode 100644 test/conf/licence.key create mode 100644 test/conf/licence.lic diff --git a/conf/licence.key b/conf/licence.key new file mode 100644 index 000000000..bb51973d3 --- /dev/null +++ b/conf/licence.key @@ -0,0 +1 @@ +914674f13f92175feceac1cd70d566cc \ No newline at end of file diff --git a/conf/licence.lic b/conf/licence.lic new file mode 100644 index 000000000..57d389d42 --- /dev/null +++ b/conf/licence.lic @@ -0,0 +1 @@ +6HQVH6rUebN8D0J2KjEHHoza-P-xtVhEFh7pmB-P4Wc5RJ70lf4G8__kWtWC9SJS \ No newline at end of file diff --git a/conf/rulex.ini b/conf/rulex.ini index c7f737879..72cd22f7c 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -186,3 +186,19 @@ enable = false # Enable # enable = false +# +# Soft Watchdog +# +[plugin.license_manager] +# +# Enable +# +enable = true +# +# Enable +# +licence_path = ./conf/licence.lic +# +# Enable +# +key_path = ./conf/licence.key \ No newline at end of file diff --git a/engine/load_plugin.go b/engine/load_plugin.go index 2b6a95b78..71cbb4cab 100644 --- a/engine/load_plugin.go +++ b/engine/load_plugin.go @@ -29,19 +29,6 @@ import ( // └──────┘ └──────┘ └──────┘ func (e *RuleEngine) LoadPlugin(sectionK string, p typex.XPlugin) error { section := utils.GetINISection(core.INIPath, sectionK) - /*key, err1 := section.GetKey("enable") - if err1 != nil { - return err1 - } - enable, err2 := key.Bool() - if err2 != nil { - return err2 - } - if !enable { - glogger.GLogger.Infof("Plugin is not enable:%s", p.PluginMetaInfo().Name) - return nil - }*/ - if err := p.Init(section); err != nil { return err } diff --git a/engine/runner.go b/engine/runner.go index a825777d7..e3fd2d7f8 100644 --- a/engine/runner.go +++ b/engine/runner.go @@ -16,8 +16,6 @@ package engine import ( - "github.com/hootrhino/rulex/component/cron_task" - "github.com/hootrhino/rulex/plugin/http_server/service" "os" "os/signal" "strings" @@ -36,6 +34,7 @@ import ( "github.com/hootrhino/rulex/glogger" httpserver "github.com/hootrhino/rulex/plugin/http_server" icmpsender "github.com/hootrhino/rulex/plugin/icmp_sender" + license_manager "github.com/hootrhino/rulex/plugin/license_manager" "github.com/hootrhino/rulex/typex" ) @@ -64,22 +63,21 @@ func RunRulex(iniPath string) { signal.Notify(c, syscall.SIGINT, syscall.SIGABRT, syscall.SIGTERM) engine := InitRuleEngine(mainConfig) engine.Start() - - // Load Plugin - loadPlugin(engine) // Load Http api Server httpServer := httpserver.NewHttpApiServer(engine) if err := engine.LoadPlugin("plugin.http_server", httpServer); err != nil { glogger.GLogger.Error(err) return } - // load Cron Task - for _, task := range service.AllEnabledCronTask() { - if err := cron_task.GetCronManager().AddTask(task); err != nil { - glogger.GLogger.Error(err) - continue - } + license_manager := license_manager.NewLicenseManager(engine) + if err := engine.LoadPlugin("plugin.license_manager", license_manager); err != nil { + glogger.GLogger.Error(err) + return } + + // Load Plugin + loadPlugin(engine) + s := <-c glogger.GLogger.Warn("RULEX Receive Stop Signal: ", s) engine.Stop() @@ -94,7 +92,7 @@ func loadPlugin(engine typex.RuleX) { name := strings.TrimPrefix(section.Name(), "plugin.") enable, err := section.GetKey("enable") if err != nil { - glogger.GLogger.Fatal(err) + continue } if !enable.MustBool(false) { glogger.GLogger.Warnf("Plugin is disable:%s", name) diff --git a/plugin/cs104_server/cs_104_server.go b/plugin/cs104_server/cs_104_server.go index d71e35271..130e10178 100644 --- a/plugin/cs104_server/cs_104_server.go +++ b/plugin/cs104_server/cs_104_server.go @@ -98,7 +98,7 @@ func (cs *cs104Server) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/demo_plugin/demo_plugin.go b/plugin/demo_plugin/demo_plugin.go index cd23dd78e..97b188b79 100644 --- a/plugin/demo_plugin/demo_plugin.go +++ b/plugin/demo_plugin/demo_plugin.go @@ -35,7 +35,7 @@ func (hh *DemoPlugin) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/devguide.md b/plugin/devguide.md index d31832aa4..73260458e 100644 --- a/plugin/devguide.md +++ b/plugin/devguide.md @@ -83,7 +83,7 @@ func (hh *DemoPlugin) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/generic_watchdog/generic_watchdog_linux.go b/plugin/generic_watchdog/generic_watchdog_linux.go index 595f03192..409db1930 100644 --- a/plugin/generic_watchdog/generic_watchdog_linux.go +++ b/plugin/generic_watchdog/generic_watchdog_linux.go @@ -114,7 +114,7 @@ func (hh *genericWatchDog) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/generic_watchdog/generic_watchdog_windows.go b/plugin/generic_watchdog/generic_watchdog_windows.go index 37add8a1a..47a7ca85a 100644 --- a/plugin/generic_watchdog/generic_watchdog_windows.go +++ b/plugin/generic_watchdog/generic_watchdog_windows.go @@ -59,7 +59,7 @@ func (hh *genericWatchDog) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/http_server/http_api_server.go b/plugin/http_server/http_api_server.go index b8fd43958..93fb402ae 100644 --- a/plugin/http_server/http_api_server.go +++ b/plugin/http_server/http_api_server.go @@ -3,6 +3,7 @@ package httpserver import ( "encoding/json" + "github.com/hootrhino/rulex/component/cron_task" "github.com/hootrhino/rulex/component/hwportmanager" "github.com/hootrhino/rulex/component/appstack" @@ -134,6 +135,14 @@ func initRulex(engine typex.RuleX) { } } } + // + // load Cron Task + for _, task := range service.AllEnabledCronTask() { + if err := cron_task.GetCronManager().AddTask(task); err != nil { + glogger.GLogger.Error(err) + continue + } + } } @@ -192,7 +201,6 @@ func (hs *ApiServerPlugin) Init(config *ini.Section) error { &model.MVisual{}, &model.MGenericGroup{}, &model.MGenericGroupRelation{}, - &model.MProtocolApp{}, &model.MNetworkConfig{}, &model.MWifiConfig{}, &model.MDataSchema{}, @@ -482,7 +490,7 @@ func (hs *ApiServerPlugin) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/http_server/model/model.go b/plugin/http_server/model/model.go index ca8f9290b..608e3ecc0 100644 --- a/plugin/http_server/model/model.go +++ b/plugin/http_server/model/model.go @@ -223,19 +223,6 @@ type MGenericGroupRelation struct { Rid string `gorm:"not null"` // 被绑定方 } -/* -* -* 应用商店里面的各类协议脚本 -* - */ -type MProtocolApp struct { - RulexModel - UUID string `gorm:"not null"` // 名称 - Name string `gorm:"not null"` // 名称 - Type string `gorm:"not null"` // 类型: IN OUT DEVICE APP - Content string `gorm:"not null"` // 协议包的内容 -} - /* * * 系统配置参数, 直接以String保存,完了以后再加工成Dto结构体 diff --git a/plugin/icmp_sender/icmp_sender.go b/plugin/icmp_sender/icmp_sender.go index b1321513d..5a8628450 100644 --- a/plugin/icmp_sender/icmp_sender.go +++ b/plugin/icmp_sender/icmp_sender.go @@ -42,7 +42,7 @@ func (hh *ICMPSender) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/license_manager/cert_codec.go b/plugin/license_manager/cert_codec.go deleted file mode 100644 index 727b9b513..000000000 --- a/plugin/license_manager/cert_codec.go +++ /dev/null @@ -1,50 +0,0 @@ -package licensemanager - -import ( - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "fmt" - "reflect" - "unsafe" -) - -func decodeCert(data []byte) (*Certificate, error) { - // 解析证书 - block, _ := pem.Decode(data) - if block == nil { - return nil, fmt.Errorf("illegal certificate") - } - xcert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return nil, err - } - - key, ok := xcert.PublicKey.(*rsa.PublicKey) - if !ok { - return nil, ErrUnsupportedPublicKey - } - - var cert = &Certificate{ - Raw: b2s(data), - Issuer: xcert.Issuer, - Subject: xcert.Subject, - NotBefore: xcert.NotBefore, - NotAfter: xcert.NotAfter, - PublicKey: key, - } - return cert, nil -} - -func b2s(b []byte) string { - return *(*string)(unsafe.Pointer(&b)) -} - -func s2b(s string) (b []byte) { - var sh = (*reflect.StringHeader)(unsafe.Pointer(&s)) - var bh = (*reflect.SliceHeader)(unsafe.Pointer(&b)) - bh.Len = sh.Len - bh.Cap = sh.Len - bh.Data = sh.Data - return -} diff --git a/plugin/license_manager/license_loader.go b/plugin/license_manager/license_loader.go deleted file mode 100644 index 5f6a3b3c5..000000000 --- a/plugin/license_manager/license_loader.go +++ /dev/null @@ -1,303 +0,0 @@ -package licensemanager - -import ( - "bytes" - "crypto/md5" - "crypto/rand" - "crypto/rsa" - "encoding/base64" - "encoding/hex" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "net" - "net/http" - "os" - "runtime" - "time" - - "github.com/hootrhino/rulex/glogger" -) - -const defaultCertPath = "./rulex.pem" - -func loadAndVerifyCert(conf LicenseConfig) (*Certificate, error) { - path := conf.LocalAddr - if len(path) == 0 { - path = defaultCertPath - } - // 加载证书 - cert, isLocal, err := loadCert(path, conf.RemoteAddr, conf.NetName) - if err != nil { - return nil, err - } - - if !isLocal { - // 第一次拉到证书,联网校验 - if err := onlineVerifyCert(conf.RemoteAddr, conf.NetName, cert.PublicKey); err != nil { - return nil, err - } - // 校验成功,证书写入到本地 - writeToFile(path, cert.Raw) - } else { - // 本地已有证书,离线校验即可 - if err := offlineVerifyCert(cert, conf.NetName); err != nil { - // 验证失败,移除证书 - os.Remove(path) - return nil, err - } - } - return cert, nil -} - -func writeToFile(path string, s string) { - file, err := os.Create(path) - if err != nil { - glogger.GLogger.Error("license_manager:writeToFile", err.Error()) - // fmt.Println("license_manager:writeToFile", err. common.Error()) - return - } - defer file.Close() - file.Write(s2b(s)) - file.Sync() -} - -func loadCert(local, remote, netName string) (*Certificate, bool, error) { - cert, err := loadLocalCert(local) - if err == nil { - return cert, true, nil - } - - cert, err1 := pullRemoteCert(remote, netName) - if err1 == nil { - // 写入到本地 - return cert, false, nil - } - - return nil, false, fmt.Errorf("load cert from local '%s': %s, load cert from remote '%s': %s", - local, err.Error(), remote, err1.Error()) -} - -func loadLocalCert(path string) (*Certificate, error) { - // 没有配置路径,使用默认路径 - if len(path) == 0 { - path = defaultCertPath - } - file, err := os.Open(path) - if err != nil { - return nil, err - } - defer file.Close() - - // 读证书文件 - data, err := ioutil.ReadAll(file) - if err != nil { - return nil, err - } - - cert, err := decodeCert(data) - - return cert, err -} - -// DeviceInfo 硬件信息 -type DeviceInfo struct { - MAC string `json:"mac"` // 硬件mac地址 - OS string `json:"os"` - Arch string `json:"arch"` -} - -type CertificateResponse struct { - Ret int `json:"ret"` - Msg string `json:"msg"` - Data string `json:"data"` -} - -// pullRemoteCert 请求远程主机生成证书并下发 -/* -POST http://remote.site/xxx/cert -request: -{ - "mac": "xxx", - "os": "linux", - "arch": "arm" -} -response: -{ - "ret":0, - "msg": "", - "data": "-----BEGIN CERTIFICATE----" -} -*/ -func pullRemoteCert(url, netName string) (*Certificate, error) { - if len(url) == 0 { - return nil, errors.New("empty url") - } - hw := deviceInfo(netName) - if len(hw.MAC) == 0 { - return nil, ErrUnknownHardwareAddr - } - - // 构建请求 - infoBytes, _ := json.Marshal(&hw) - body := bytes.NewReader(infoBytes) - req, err := http.NewRequest(http.MethodPost, url, body) - if err != nil { - return nil, err - } - // 请求证书 - var cert *Certificate - err = retryRequest(req, func(resp *http.Response) error { - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } - var cr CertificateResponse - if err := json.Unmarshal(data, &cr); err != nil { - return err - } - - if cr.Ret != 0 { - return fmt.Errorf("ret: %d, msg: %s", cr.Ret, cr.Msg) - } - - // 解析证书 - cert, err = decodeCert(s2b(cr.Data)) - return err - }) - - return cert, err -} - -type VerifyCertRequest struct { - MAC string `json:"mac"` - Data string `json:"data"` -} - -type VerifyCertResponse struct { - Ret int `json:"ret"` // 返回值 - Msg string `json:"msg"` // -} - -/* -GET http://remote.site/xxx/cert -request: - - { - "mac": "xxx", // 硬件地址,标识机器 - "data" "xxx" // 加密后的数据 - } - -response: -*/ - -var ( - ErrUnsupportedPublicKey = errors.New("unsupported public key type") - ErrUnknownHardwareAddr = errors.New("unknown hardware addr") - ErrMismatchedCertificate = errors.New("mismatched certificate") -) - -func onlineVerifyCert(url, netName string, key *rsa.PublicKey) error { - hw := deviceInfo(netName) - if len(hw.MAC) == 0 { - return ErrUnknownHardwareAddr - } - - // 加密数据 - src := []byte(hw.MAC) - dst, err := rsa.EncryptPKCS1v15(rand.Reader, key, src) - if err != nil { - return err - } - - // 构建请求 - rc := VerifyCertRequest{ - MAC: string(src), - Data: base64.StdEncoding.EncodeToString(dst), - } - - bts, _ := json.Marshal(&rc) - body := bytes.NewReader(bts) - req, err := http.NewRequest(http.MethodGet, url, body) - if err != nil { - return err - } - - // 请求验证 - err = retryRequest(req, func(resp *http.Response) error { - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - return err - } - - var vc VerifyCertResponse - if err := json.Unmarshal(data, &vc); err != nil { - return err - } - - // 检查响应 - if vc.Ret != 0 { - return fmt.Errorf("ret: %d, msg: %s", vc.Ret, vc.Msg) - } - return nil - }) - - return err -} - -// retryRequest 重试请求,第1次超时1.5s,每次重试增加0.75s -func retryRequest(req *http.Request, fn func(*http.Response) error) error { - var err error - for i := 0; i < 3; i++ { - client := http.Client{ - Timeout: time.Duration(1500+i*750) * time.Millisecond, - } - // 发起请求 - var resp *http.Response - resp, err = client.Do(req) - if err != nil { - continue - } - // 处理响应 - if err = fn(resp); err != nil { - continue - } - - return nil - } - - return err -} - -func offlineVerifyCert(cert *Certificate, netName string) error { - var mac string - inte, err := net.InterfaceByName(netName) - if err == nil && inte.HardwareAddr != nil { - mac = inte.HardwareAddr.String() - md5Byts := md5.Sum(s2b(mac)) - mac = hex.EncodeToString(md5Byts[:]) - } - if len(mac) == 0 { - return fmt.Errorf("unknown netName: %s", netName) - } - - if mac != cert.Subject.CommonName { - return ErrMismatchedCertificate - } - return nil -} - -func deviceInfo(name string) DeviceInfo { - info := DeviceInfo{ - OS: runtime.GOOS, - Arch: runtime.GOARCH, - } - - inte, err := net.InterfaceByName(name) - if err == nil && inte.HardwareAddr != nil { - info.MAC = inte.HardwareAddr.String() - } - - return info -} diff --git a/plugin/license_manager/license_manager.go b/plugin/license_manager/license_manager.go index bfb12c35f..f437b0498 100644 --- a/plugin/license_manager/license_manager.go +++ b/plugin/license_manager/license_manager.go @@ -6,89 +6,79 @@ package licensemanager */ import ( - "crypto/rsa" - "crypto/x509/pkix" - "sync/atomic" - "time" + "fmt" + "os" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" "gopkg.in/ini.v1" ) // LicenseManager 证书管理 type LicenseManager struct { - uuid string - cert atomic.Value // 证书信息(*Certificate) - conf LicenseConfig + uuid string + CpuId string + EthMac string + AdminUsername string + AdminPassword string } -func NewLicenseManager() *LicenseManager { +// admin := { +// Username: "open-rhino", +// Password: "open-hoot", +// } +// +// // 出厂的第一台设备 +// +// device := { +// CpuId: "o:p:e:n:r:h:i:n:o", +// EthMac: "o:p:e:n:h:o:o:t", +// } +func NewLicenseManager(r typex.RuleX) *LicenseManager { return &LicenseManager{ - uuid: "LicenseManager", + uuid: "LicenseManager", + AdminUsername: "rhino", + AdminPassword: "hoot", + CpuId: "o:p:e:n:r:h:i:n:o", + EthMac: "o:p:e:n:h:o:o:t", } } -// LicenseConfig 证书配置 -type LicenseConfig struct { - LocalAddr string `ini:"local_addr"` // 本地存放证书的路径 - RemoteAddr string `ini:"remote_addr"` // 远程拉取证书的路径 - NetName string `ini:"net_name"` // 网络名('eth0') -} - -// Certificate 证书信息 -type Certificate struct { - Raw string `json:"raw"` - Issuer pkix.Name `json:"issuer"` // 授权方 - Subject pkix.Name `json:"subject"` // 证书授权信息 - NotAfter time.Time - NotBefore time.Time - PublicKey *rsa.PublicKey `json:"key"` // 加密公钥 -} - // Init 初始化LicenseManager func (l *LicenseManager) Init(section *ini.Section) error { - // 解析配置 - _ = utils.InIMapToStruct(section, &l.conf) - - // 先尝试加载证书 - l.reload(false) - - // 加载失败,设置定时器1小时再检查 - if l.cert.Load() == nil { - time.AfterFunc(time.Hour, func() { l.reload(true) }) + licence_path, err1 := section.GetKey("licence_path") + if err1 != nil { + glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") } - - return nil -} - -func (l *LicenseManager) reload(quit bool) *Certificate { - // 已有证书,直接返回 - cert, _ := l.cert.Load().(*Certificate) - if cert != nil { - return cert + licence_key, err2 := section.GetKey("key_path") + if err2 != nil { + glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") } - - // 尝试加载证书 - cert, err := loadAndVerifyCert(l.conf) - if err == nil { - if !l.cert.CompareAndSwap(nil, cert) { - cert, _ = l.cert.Load().(*Certificate) - } - return cert + lic, err1 := os.ReadFile(licence_path.String()) + if err1 != nil { + glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") } - - // 日志输出 - glogger.GLogger.Error("license_manager:", err.Error()) - // fmt.Println("license_manager:", err. common.Error()) - - // 加载失败并退出 - if quit { - glogger.GLogger.Fatal("need a valid certificate") - // panic("need a valid certificate") + licence := string(lic) + glogger.GLogger.Info("licence public key:", licence) + key, err2 := os.ReadFile(licence_key.String()) + if err2 != nil { + glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") } + private := string(key) + localMacSum := SumMd5(fmt.Sprintf("%s,%s", l.CpuId, l.EthMac)) + localAdminSum := SumMd5(fmt.Sprintf("%s,%s", l.AdminUsername, l.AdminPassword)) + adminSalt, err3 := DecryptAES(private, licence) + if err3 != nil { + glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") + } + if localAdminSum != private { + glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") + } + if adminSalt != localMacSum { + glogger.GLogger.Fatal("Load License Failed, May be Your License IS Invalid.") + } + glogger.GLogger.Info("Load License Success:", licence) return nil } @@ -96,6 +86,9 @@ func (l *LicenseManager) reload(quit bool) *Certificate { func (dm *LicenseManager) Start(typex.RuleX) error { return nil } +func (dm *LicenseManager) Service(arg typex.ServiceArg) typex.ServiceResult { + return typex.ServiceResult{} +} // Stop 未实现 func (dm *LicenseManager) Stop() error { @@ -107,57 +100,10 @@ func (hh *LicenseManager) PluginMetaInfo() typex.XPluginMetaInfo { UUID: hh.uuid, Name: "LicenseManager", Version: "v0.0.1", - Homepage: "https://github.com/dropliu/rulex", - HelpLink: "https://github.com/dropliu/rulex", - Author: "dropliu", - Email: "13594448678@163.com", - License: "MIT", - } -} - -/* - * - * 服务调用接口 - * - */ -func (l *LicenseManager) Service(arg typex.ServiceArg) typex.ServiceResult { - switch arg.Name { - case "info": - var info CertificateInfo - if cert, _ := l.cert.Load().(*Certificate); cert != nil { - info = Certificate2Info(cert) - } - return typex.ServiceResult{Out: info} - case "verify": - var info CertificateInfo - if cert := l.reload(false); cert != nil { - info = Certificate2Info(cert) - } - return typex.ServiceResult{Out: info} - default: - } - - return typex.ServiceResult{} -} - -type CertificateInfo struct { - Authorized bool `json:"authorized"` // 是否已授权?(当为false时,其它字段为空) - Content string `json:"content"` // 证书原始内容 - StartDate string `json:"start_date"` // 开始日期 - EndDate string `json:"end_date"` // 结束日期 - Valid bool `json:"valid"` // 证书是否有效? - Issuer string `json:"issuer"` - Subject string `json:"subject"` -} - -func Certificate2Info(cert *Certificate) CertificateInfo { - return CertificateInfo{ - Authorized: true, - Content: cert.Raw, - StartDate: cert.NotBefore.Format(time.DateOnly), - EndDate: cert.NotAfter.Format(time.DateOnly), - Valid: time.Since(cert.NotAfter) < 0, - Issuer: cert.Issuer.CommonName, - Subject: cert.Subject.CommonName, + Homepage: "https://hootrhino.github.io", + HelpLink: "https://hootrhino.github.io", + Author: "HootRhinoTeam", + Email: "HootRhinoTeam@hootrhino.com", + License: "AGPL", } } diff --git a/plugin/license_manager/license_manager.md b/plugin/license_manager/license_manager.md index 59265d8eb..064d479c4 100644 --- a/plugin/license_manager/license_manager.md +++ b/plugin/license_manager/license_manager.md @@ -1,72 +1,2 @@ -# license manager: 固件证书管理器 -固件证书管理器,用来防止盗版或者破解。 -## 原理 -该插件会向一个服务器发送一个 HTTP 请求,该请求包含了: -1. 本地计算机 MAC 地址 -1. 本地软件版本号 -1. 本地操作系统 -1. 本地硬件架构 -2. 或者其他更多 - -最终会将上述信息用某种算法加密后上传到服务器,服务器验证后返回一个加密数字证书,该证书存放在本地路径下。每次开机启动的时候验证证书即可。 - -注册伪代码: -``` -license_text = request_server("*********") -if check(license_text){ - save(license_text) -} -``` - -启动认证伪代码: -``` -license_text = load_file("/path/app.lic") -if check(license_text){ - start() -}else{ - stop(error-message) -} -``` - -## 配置 -```ini -[plugin.license_manager] -local_addr = "./rulex/cert.pem" -remote_addr = "http://remote.site/cert/" -net_name = "eth0" -``` - -## 接口 -远程服务器承担了拉取、验证证书的作用,需要实现对应的接口 - -``` -创建证书 -POST remote.site/cert -request: -{ - "mac": "xxx", - "os": "linux", - "arch": "amd64", -} -response: -{ - "ret":0, - "msg": "", - "data": "-----BEGIN CERTIFICATE-----...-----END CERTIFICATE-----" -} -``` - -``` -验证证书 -GET remote.site/cert -request: -{ - "mac": "xxx", - "data": "xxx" // 使用证书加密mac后的数据,使用base64编码(二进制安全) -} -response: -{ - "ret": 0, - "msg": "xxx" -} -``` \ No newline at end of file +# 固件证书管理器 +固件证书管理器,用来防止盗版或者破解。开源版不限制使用,商业版有单独的证书管理器。 diff --git a/plugin/license_manager/misc.go b/plugin/license_manager/misc.go new file mode 100644 index 000000000..642d68307 --- /dev/null +++ b/plugin/license_manager/misc.go @@ -0,0 +1,89 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package licensemanager + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/md5" + "crypto/rand" + "encoding/base64" + "errors" + "fmt" + "io" +) + +// encryptAES 加密字符串 +func EncryptAES(key, text string) (string, error) { + block, err := aes.NewCipher([]byte(key)) + if err != nil { + return "", err + } + + // 为加密创建一个密码分组模式 + cipherText := make([]byte, aes.BlockSize+len(text)) + iv := cipherText[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return "", err + } + + stream := cipher.NewCFBEncrypter(block, iv) + stream.XORKeyStream(cipherText[aes.BlockSize:], []byte(text)) + + return base64.URLEncoding.EncodeToString(cipherText), nil +} + +// decryptAES 解密字符串 +func DecryptAES(key, cipherText string) (string, error) { + block, err := aes.NewCipher([]byte(key)) + if err != nil { + return "", err + } + + // 使用密文的前 16 个字节作为 IV + cipherTextBytes, err := base64.URLEncoding.DecodeString(cipherText) + if err != nil { + return "", err + } + + if len(cipherTextBytes) < aes.BlockSize { + return "", errors.New("cipherText is too short") + } + + iv := cipherTextBytes[:aes.BlockSize] + cipherTextBytes = cipherTextBytes[aes.BlockSize:] + + // 创建一个密码分组模式 + stream := cipher.NewCFBDecrypter(block, iv) + + // 解密 + stream.XORKeyStream(cipherTextBytes, cipherTextBytes) + + return string(cipherTextBytes), nil +} + +/* +* +* MD5 +* + */ +func SumMd5(inputString string) string { + hasher := md5.New() + io.WriteString(hasher, inputString) + hashBytes := hasher.Sum(nil) + md5String := fmt.Sprintf("%x", hashBytes) + return md5String +} diff --git a/plugin/modbus_scanner/modbus_scanner.go b/plugin/modbus_scanner/modbus_scanner.go index 86f44631c..99b197e50 100644 --- a/plugin/modbus_scanner/modbus_scanner.go +++ b/plugin/modbus_scanner/modbus_scanner.go @@ -62,6 +62,6 @@ func (hh *modbusScanner) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/modbuscrc_tools/modbuscrc_tools.go b/plugin/modbuscrc_tools/modbuscrc_tools.go index a30a8b02c..d97b2acf2 100644 --- a/plugin/modbuscrc_tools/modbuscrc_tools.go +++ b/plugin/modbuscrc_tools/modbuscrc_tools.go @@ -50,6 +50,6 @@ func (hh *modbusCRCCalculator) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/mqtt_server/mqtt_server.go b/plugin/mqtt_server/mqtt_server.go index e22ff5bdc..390fab576 100644 --- a/plugin/mqtt_server/mqtt_server.go +++ b/plugin/mqtt_server/mqtt_server.go @@ -93,7 +93,7 @@ func (s *MqttServer) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/net_discover/net_boardcast.go b/plugin/net_discover/net_boardcast.go index 2ff07cf44..5343cfdbb 100644 --- a/plugin/net_discover/net_boardcast.go +++ b/plugin/net_discover/net_boardcast.go @@ -178,7 +178,7 @@ func (hh *NetDiscover) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/sensor_server/sensor_server.go b/plugin/sensor_server/sensor_server.go index 43883b600..6892a775d 100644 --- a/plugin/sensor_server/sensor_server.go +++ b/plugin/sensor_server/sensor_server.go @@ -50,7 +50,7 @@ func (hh *SensorServer) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/telemetry/telemetry.go b/plugin/telemetry/telemetry.go index 02f4f8ef2..ce5dc39a7 100644 --- a/plugin/telemetry/telemetry.go +++ b/plugin/telemetry/telemetry.go @@ -93,6 +93,6 @@ func (p *Telemetry) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://github.com/dropliu/rulex", Author: "dropliu", Email: "13594448678@163.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/ttyd_terminal/ttyd_terminal.go b/plugin/ttyd_terminal/ttyd_terminal.go index 5b2dbedc6..ae0a082f1 100644 --- a/plugin/ttyd_terminal/ttyd_terminal.go +++ b/plugin/ttyd_terminal/ttyd_terminal.go @@ -88,6 +88,6 @@ func (hh *WebTTYPlugin) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://github.com/tsl0922/ttyd", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/usb_monitor/usb_mnitor_windows.go b/plugin/usb_monitor/usb_mnitor_windows.go index 592fc7120..349d30fc7 100644 --- a/plugin/usb_monitor/usb_mnitor_windows.go +++ b/plugin/usb_monitor/usb_mnitor_windows.go @@ -44,7 +44,7 @@ func (usbm *usbMonitor) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://github.com/hootrhino/rulex.git", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/plugin/usb_monitor/usb_monitor_linux.go b/plugin/usb_monitor/usb_monitor_linux.go index a6f6b0db8..047fdd9cb 100644 --- a/plugin/usb_monitor/usb_monitor_linux.go +++ b/plugin/usb_monitor/usb_monitor_linux.go @@ -166,7 +166,7 @@ func (usbm *usbMonitor) PluginMetaInfo() typex.XPluginMetaInfo { HelpLink: "https://hootrhino.github.io", Author: "HootRhinoTeam", Email: "HootRhinoTeam@hootrhino.com", - License: "MIT", + License: "AGPL", } } diff --git a/test/conf/licence.key b/test/conf/licence.key new file mode 100644 index 000000000..bb51973d3 --- /dev/null +++ b/test/conf/licence.key @@ -0,0 +1 @@ +914674f13f92175feceac1cd70d566cc \ No newline at end of file diff --git a/test/conf/licence.lic b/test/conf/licence.lic new file mode 100644 index 000000000..eb662e1e1 --- /dev/null +++ b/test/conf/licence.lic @@ -0,0 +1 @@ +P2UO_dEbw5sCsXBYAF6hGgUIdTEyBi9K7x6Wai1UpymdycrtVV2Fqtwt1ssydG1U \ No newline at end of file diff --git a/test/conf/rulex.ini b/test/conf/rulex.ini index c867ab55b..91ac68dff 100644 --- a/test/conf/rulex.ini +++ b/test/conf/rulex.ini @@ -193,4 +193,17 @@ enable = true # # Enable # -enable = true \ No newline at end of file +enable = true +[plugin.license_manager] +# +# Enable +# +enable = true +# +# Enable +# +licence_path = ./conf/licence.lic +# +# Enable +# +key_path = ./conf/licence.key \ No newline at end of file From 0a5c55dd4520bfa4a2edd052842889faac91f7ae Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 17 Nov 2023 21:48:34 +0800 Subject: [PATCH 009/138] dev: optimize license manager --- conf/{licence.key => license.key} | 0 conf/{licence.lic => license.lic} | 0 conf/rulex.ini | 4 ++-- plugin/http_server/server/www/index.html | 25 ++++++++++------------- plugin/license_manager/license_manager.go | 16 +++++++-------- release_pkg.sh | 2 +- script/rulex-daemon.sh | 1 + script/rulex-systemctl.sh | 2 ++ test/conf/licence.lic | 1 - test/conf/{licence.key => license.key} | 0 test/conf/license.lic | 1 + test/conf/rulex.ini | 4 ++-- 12 files changed, 27 insertions(+), 29 deletions(-) rename conf/{licence.key => license.key} (100%) rename conf/{licence.lic => license.lic} (100%) delete mode 100644 test/conf/licence.lic rename test/conf/{licence.key => license.key} (100%) create mode 100644 test/conf/license.lic diff --git a/conf/licence.key b/conf/license.key similarity index 100% rename from conf/licence.key rename to conf/license.key diff --git a/conf/licence.lic b/conf/license.lic similarity index 100% rename from conf/licence.lic rename to conf/license.lic diff --git a/conf/rulex.ini b/conf/rulex.ini index 72cd22f7c..e34c5a047 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -197,8 +197,8 @@ enable = true # # Enable # -licence_path = ./conf/licence.lic +license_path = ./license.lic # # Enable # -key_path = ./conf/licence.key \ No newline at end of file +key_path = ./license.key \ No newline at end of file diff --git a/plugin/http_server/server/www/index.html b/plugin/http_server/server/www/index.html index 4903f8789..b5a6747e5 100644 --- a/plugin/http_server/server/www/index.html +++ b/plugin/http_server/server/www/index.html @@ -1,17 +1,14 @@ - - - - - - - - Rulex - - + + + + + +Rhino EEKit + + - -Hello,Rulex - +
+ - \ No newline at end of file + \ No newline at end of file diff --git a/plugin/license_manager/license_manager.go b/plugin/license_manager/license_manager.go index f437b0498..a5dc8367f 100644 --- a/plugin/license_manager/license_manager.go +++ b/plugin/license_manager/license_manager.go @@ -46,31 +46,29 @@ func NewLicenseManager(r typex.RuleX) *LicenseManager { // Init 初始化LicenseManager func (l *LicenseManager) Init(section *ini.Section) error { - licence_path, err1 := section.GetKey("licence_path") + license_path, err1 := section.GetKey("license_path") if err1 != nil { glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") } - licence_key, err2 := section.GetKey("key_path") + license_key, err2 := section.GetKey("key_path") if err2 != nil { glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") } - lic, err1 := os.ReadFile(licence_path.String()) + lic, err1 := os.ReadFile(license_path.String()) if err1 != nil { glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") } - licence := string(lic) - glogger.GLogger.Info("licence public key:", licence) - key, err2 := os.ReadFile(licence_key.String()) + license := string(lic) + key, err2 := os.ReadFile(license_key.String()) if err2 != nil { glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") } private := string(key) localMacSum := SumMd5(fmt.Sprintf("%s,%s", l.CpuId, l.EthMac)) localAdminSum := SumMd5(fmt.Sprintf("%s,%s", l.AdminUsername, l.AdminPassword)) - adminSalt, err3 := DecryptAES(private, licence) + adminSalt, err3 := DecryptAES(private, license) if err3 != nil { glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") - } if localAdminSum != private { glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") @@ -78,7 +76,7 @@ func (l *LicenseManager) Init(section *ini.Section) error { if adminSalt != localMacSum { glogger.GLogger.Fatal("Load License Failed, May be Your License IS Invalid.") } - glogger.GLogger.Info("Load License Success:", licence) + glogger.GLogger.Info("Load License Success:", license) return nil } diff --git a/release_pkg.sh b/release_pkg.sh index a9203342f..ade84ad52 100755 --- a/release_pkg.sh +++ b/release_pkg.sh @@ -9,7 +9,7 @@ create_pkg() { local version="$(git describe --tags $(git rev-list --tags --max-count=1))" local release_dir="_release" local pkg_name="${APP}-$target-$version.zip" - local common_files="./LICENSE ./conf/${APP}.ini ./md5.sum" + local common_files="./conf/license.* ./LICENSE ./conf/${APP}.ini ./md5.sum" local files_to_include="./${APP} $common_files" local files_to_include_exe="./${APP}.exe $common_files" diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index a6dc91dcc..11eadea36 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -21,6 +21,7 @@ uninstall_files() { rm -f /usr/local/rulex.ini rm -f /usr/local/rulex.db rm -f /usr/local/*.txt + rm -f /usr/local/license.* rm -rf /usr/local/upload/ rm -f /usr/local/*.txt.gz } diff --git a/script/rulex-systemctl.sh b/script/rulex-systemctl.sh index 126a21453..86f5f6cc5 100644 --- a/script/rulex-systemctl.sh +++ b/script/rulex-systemctl.sh @@ -45,6 +45,7 @@ EOL chmod +x $source_dir/rulex cp "$source_dir/rulex" "$executable" cp "$source_dir/rulex.ini" "$config_file" + cp "$source_dir/license.*" /usr/local/ systemctl daemon-reload systemctl enable rulex systemctl start rulex @@ -92,6 +93,7 @@ uninstall(){ remove_files $working_directory/rulex.db remove_files $working_directory/*.txt remove_files $working_directory/upload/ + remove_files $working_directory/license.* remove_files $working_directory/*.txt.gz systemctl daemon-reload systemctl reset-failed diff --git a/test/conf/licence.lic b/test/conf/licence.lic deleted file mode 100644 index eb662e1e1..000000000 --- a/test/conf/licence.lic +++ /dev/null @@ -1 +0,0 @@ -P2UO_dEbw5sCsXBYAF6hGgUIdTEyBi9K7x6Wai1UpymdycrtVV2Fqtwt1ssydG1U \ No newline at end of file diff --git a/test/conf/licence.key b/test/conf/license.key similarity index 100% rename from test/conf/licence.key rename to test/conf/license.key diff --git a/test/conf/license.lic b/test/conf/license.lic new file mode 100644 index 000000000..57d389d42 --- /dev/null +++ b/test/conf/license.lic @@ -0,0 +1 @@ +6HQVH6rUebN8D0J2KjEHHoza-P-xtVhEFh7pmB-P4Wc5RJ70lf4G8__kWtWC9SJS \ No newline at end of file diff --git a/test/conf/rulex.ini b/test/conf/rulex.ini index 91ac68dff..78b6b49f2 100644 --- a/test/conf/rulex.ini +++ b/test/conf/rulex.ini @@ -202,8 +202,8 @@ enable = true # # Enable # -licence_path = ./conf/licence.lic +license_path = ./license.lic # # Enable # -key_path = ./conf/licence.key \ No newline at end of file +key_path = ./license.key \ No newline at end of file From 68acd9561605238046a5560bec3c3400f12c5e0c Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 17 Nov 2023 21:55:02 +0800 Subject: [PATCH 010/138] dev: update index.html --- plugin/http_server/server/www/index.html | 26 ++++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/plugin/http_server/server/www/index.html b/plugin/http_server/server/www/index.html index b5a6747e5..5a04e3493 100644 --- a/plugin/http_server/server/www/index.html +++ b/plugin/http_server/server/www/index.html @@ -1,14 +1,18 @@ - - - - - -Rhino EEKit - - + + + + + + + + rulex + + + -
- + hello,rulex + - \ No newline at end of file + \ No newline at end of file From 6f8fef693f4c4965b7c1990fed45bcc8eb738f50 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 17 Nov 2023 22:25:00 +0800 Subject: [PATCH 011/138] dev: optimize Get Vendor Key --- .../apis/system_settings_windows.go | 4 +++ .../http_server/apis/vendor_security_api.go | 33 +++++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/plugin/http_server/apis/system_settings_windows.go b/plugin/http_server/apis/system_settings_windows.go index 648b42716..6a17778ea 100644 --- a/plugin/http_server/apis/system_settings_windows.go +++ b/plugin/http_server/apis/system_settings_windows.go @@ -1,5 +1,7 @@ package apis +import "github.com/hootrhino/rulex/plugin/http_server/server" + // Copyright (C) 2023 wwhai // // This program is free software: you can redistribute it and/or modify @@ -16,4 +18,6 @@ package apis // along with this program. If not, see . func LoadSystemSettingsAPI() { + settingsFirmware := server.RouteGroup(server.ContextUrl("/firmware")) + settingsFirmware.GET("/vendorKey", server.AddRoute(GetVendorKey)) } diff --git a/plugin/http_server/apis/vendor_security_api.go b/plugin/http_server/apis/vendor_security_api.go index 994c967d2..01478d8fe 100644 --- a/plugin/http_server/apis/vendor_security_api.go +++ b/plugin/http_server/apis/vendor_security_api.go @@ -16,9 +16,14 @@ package apis import ( + "os" + "strings" + "github.com/gin-gonic/gin" + "github.com/hootrhino/rulex/core" common "github.com/hootrhino/rulex/plugin/http_server/common" "github.com/hootrhino/rulex/typex" + "gopkg.in/ini.v1" ) /* @@ -28,11 +33,25 @@ import ( */ func GetVendorKey(c *gin.Context, ruleEngine typex.RuleX) { - testK := ` ------BEGIN OPENSSH PRIVATE KEY----- -b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW ------END OPENSSH PRIVATE KEY----- -` - c.JSON(common.HTTP_OK, common.OkWithData(testK)) - + cfg, _ := ini.ShadowLoad(core.INIPath) + sections := cfg.ChildSections("plugin") + license := "" + for _, section := range sections { + name := strings.TrimPrefix(section.Name(), "plugin.") + if name == "license_manager" { + license_path, err1 := section.GetKey("license_path") + if err1 != nil { + c.JSON(common.HTTP_OK, common.Error400(err1)) + return + } + readBytes, err2 := os.ReadFile(license_path.String()) + if err2 != nil { + c.JSON(common.HTTP_OK, common.Error400(err2)) + return + } + license += string(readBytes) + break + } + } + c.JSON(common.HTTP_OK, common.OkWithData(license)) } From fc2c7a358500308f2e10024a8236a0f98dccd95e Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 18 Nov 2023 13:42:53 +0800 Subject: [PATCH 012/138] dev: rename api: delete to del --- docs/docs.go | 2 +- docs/swagger.json | 2 +- plugin/http_server/http_api_server.go | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/docs.go b/docs/docs.go index f2c5cfc7b..4a3d48a67 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -57,7 +57,7 @@ const docTemplate = `{ } } }, - "/crontask/delete": { + "/crontask/del": { "delete": { "consumes": [ "application/json" diff --git a/docs/swagger.json b/docs/swagger.json index f6bcc66fc..32c10c07c 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -50,7 +50,7 @@ } } }, - "/crontask/delete": { + "/crontask/del": { "delete": { "consumes": [ "application/json" diff --git a/plugin/http_server/http_api_server.go b/plugin/http_server/http_api_server.go index 93fb402ae..fbedf58e4 100644 --- a/plugin/http_server/http_api_server.go +++ b/plugin/http_server/http_api_server.go @@ -269,7 +269,7 @@ func (hs *ApiServerPlugin) LoadRoute() { InEndApi.GET(("/detail"), server.AddRoute(apis.InEndDetail)) InEndApi.GET(("/list"), server.AddRoute(apis.InEnds)) InEndApi.POST(("/create"), server.AddRoute(apis.CreateInend)) - InEndApi.DELETE(("/delete"), server.AddRoute(apis.DeleteInEnd)) + InEndApi.DELETE(("/del"), server.AddRoute(apis.DeleteInEnd)) InEndApi.PUT(("/update"), server.AddRoute(apis.UpdateInend)) } @@ -277,7 +277,7 @@ func (hs *ApiServerPlugin) LoadRoute() { { rulesApi.POST(("/create"), server.AddRoute(apis.CreateRule)) rulesApi.PUT(("/update"), server.AddRoute(apis.UpdateRule)) - rulesApi.DELETE(("/delete"), server.AddRoute(apis.DeleteRule)) + rulesApi.DELETE(("/del"), server.AddRoute(apis.DeleteRule)) rulesApi.GET(("/list"), server.AddRoute(apis.Rules)) rulesApi.GET(("/detail"), server.AddRoute(apis.RuleDetail)) // @@ -292,7 +292,7 @@ func (hs *ApiServerPlugin) LoadRoute() { OutEndApi.GET(("/detail"), server.AddRoute(apis.OutEndDetail)) OutEndApi.GET(("/list"), server.AddRoute(apis.OutEnds)) OutEndApi.POST(("/create"), server.AddRoute(apis.CreateOutEnd)) - OutEndApi.DELETE(("/delete"), server.AddRoute(apis.DeleteOutEnd)) + OutEndApi.DELETE(("/del"), server.AddRoute(apis.DeleteOutEnd)) OutEndApi.PUT(("/update"), server.AddRoute(apis.UpdateOutEnd)) } @@ -325,7 +325,7 @@ func (hs *ApiServerPlugin) LoadRoute() { { deviceApi.POST(("/create"), server.AddRoute(apis.CreateDevice)) deviceApi.PUT(("/update"), server.AddRoute(apis.UpdateDevice)) - deviceApi.DELETE(("/delete"), server.AddRoute(apis.DeleteDevice)) + deviceApi.DELETE(("/del"), server.AddRoute(apis.DeleteDevice)) deviceApi.GET(("/detail"), server.AddRoute(apis.DeviceDetail)) deviceApi.POST(("/modbus/sheetImport"), server.AddRoute(apis.ModbusSheetImport)) deviceApi.PUT(("/modbus/point"), server.AddRoute(apis.UpdateModbusPoint)) @@ -343,7 +343,7 @@ func (hs *ApiServerPlugin) LoadRoute() { appApi.GET(("/list"), server.AddRoute(apis.Apps)) appApi.POST(("/create"), server.AddRoute(apis.CreateApp)) appApi.PUT(("/update"), server.AddRoute(apis.UpdateApp)) - appApi.DELETE(("/delete"), server.AddRoute(apis.RemoveApp)) + appApi.DELETE(("/del"), server.AddRoute(apis.RemoveApp)) appApi.PUT(("/start"), server.AddRoute(apis.StartApp)) appApi.PUT(("/stop"), server.AddRoute(apis.StopApp)) appApi.GET(("/detail"), server.AddRoute(apis.AppDetail)) @@ -372,7 +372,7 @@ func (hs *ApiServerPlugin) LoadRoute() { groupApi.GET("/detail", server.AddRoute(apis.GroupDetail)) groupApi.POST("/bind", server.AddRoute(apis.BindResource)) groupApi.PUT("/unbind", server.AddRoute(apis.UnBindResource)) - groupApi.DELETE("/delete", server.AddRoute(apis.DeleteGroup)) + groupApi.DELETE("/del", server.AddRoute(apis.DeleteGroup)) } // @@ -399,7 +399,7 @@ func (hs *ApiServerPlugin) LoadRoute() { schemaApi := server.RouteGroup(server.ContextUrl("/schema")) { schemaApi.POST("/create", server.AddRoute(apis.CreateDataSchema)) - schemaApi.DELETE("/delete", server.AddRoute(apis.DeleteDataSchema)) + schemaApi.DELETE("/del", server.AddRoute(apis.DeleteDataSchema)) schemaApi.PUT("/update", server.AddRoute(apis.UpdateDataSchema)) schemaApi.GET("/list", server.AddRoute(apis.ListDataSchema)) schemaApi.GET(("/detail"), server.AddRoute(apis.DataSchemaDetail)) @@ -453,7 +453,7 @@ func (hs *ApiServerPlugin) LoadRoute() { crontaskApi := server.DefaultApiServer.GetGroup(server.ContextUrl("/crontask")) { crontaskApi.POST("/create", server.AddRouteV2(apis.CreateCronTask)) - crontaskApi.DELETE("/delete", server.AddRouteV2(apis.DeleteCronTask)) + crontaskApi.DELETE("/del", server.AddRouteV2(apis.DeleteCronTask)) crontaskApi.PUT("/update", server.AddRouteV2(apis.UpdateCronTask)) crontaskApi.GET("/list", server.AddRouteV2(apis.ListCronTask)) crontaskApi.GET("/results/page", server.AddRouteV2(apis.PageCronTaskResult)) From 64a50794efefbfdba6028825bcd8c6646cd2d1a6 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 18 Nov 2023 13:53:24 +0800 Subject: [PATCH 013/138] dev: add more resource; update doc --- script/readme-daemon.md | 40 +--------------------------------- script/readme-systemctl.md | 44 +++----------------------------------- script/readme-windows.md | 22 +++++++++++++++++++ test/conf/licence.key | 1 + test/conf/licence.lic | 1 + 5 files changed, 28 insertions(+), 80 deletions(-) create mode 100644 script/readme-windows.md create mode 100644 test/conf/licence.key create mode 100644 test/conf/licence.lic diff --git a/script/readme-daemon.md b/script/readme-daemon.md index 346f8d4ad..21e6861a7 100644 --- a/script/readme-daemon.md +++ b/script/readme-daemon.md @@ -1,5 +1,5 @@ # Linux script -该脚本是RULEX的系统服务操作脚本,处理RULEX的安装、启动、停止、卸载等。 +该脚本是RULEX的`系统服务`操作脚本,处理RULEX的安装、启动、停止、卸载等。 ## 基础使用 将安装包解压: ```sh @@ -27,41 +27,3 @@ unzip rulex-arm32linux-v0.6.2.zip -d rulex ```sh ./rulex_daemon.sh uninstall ``` -## 操作演示 -```sh -rer@revb-h3:~/Desktop/rulex$ unzip rulex-arm32linux-v0.6.2.zip -d rulex -Archive: rulex-arm32linux-v0.6.2.zip - inflating: rulex/rulex - inflating: rulex/LICENSE - inflating: rulex/rulex.ini - inflating: rulex/rulex_daemon.sh -rer@revb-h3:~/Desktop/rulex$ ll -total 16540 -drwxrwxrwx 3 rer rer 4096 Sep 4 21:00 ./ -drwxrwxrwx 3 rer rer 4096 May 19 2022 ../ -drwxrwxr-x 2 rer rer 4096 Sep 4 21:00 rulex/ --rw-rw-r-- 1 rer rer 16921343 Sep 4 21:00 rulex-arm32linux-v0.6.2.zip -rer@revb-h3:~/Desktop/rulex$ cd rulex/ -rer@revb-h3:~/Desktop/rulex/rulex$ ll -total 45848 -drwxrwxr-x 2 rer rer 4096 Sep 4 21:00 ./ -drwxrwxrwx 3 rer rer 4096 Sep 4 21:00 ../ --rwxrwxrwx 1 rer rer 34523 Sep 4 20:51 LICENSE* --rwxrwxrwx 1 rer rer 46891964 Sep 4 20:52 rulex* --rwxrwxrwx 1 rer rer 2104 Sep 4 20:51 rulex_daemon.sh* --rwxrwxrwx 1 rer rer 2605 Sep 4 20:51 rulex.ini* -rer@revb-h3:~/Desktop/rulex/rulex$ ./rulex_daemon.sh install -This script must be run as root -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh install -Created symlink /etc/systemd/system/multi-user.target.wants/rulex.service → /etc/systemd/system/rulex.service. -Rulex service has been created and extracted. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh start -RULEX started as a daemon. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh restart -RULEX started as a daemon. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh stop -Service Rulex has been stopped. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_daemon.sh uninstall -Removed /etc/systemd/system/multi-user.target.wants/rulex.service. -Rulex has been uninstalled. -``` \ No newline at end of file diff --git a/script/readme-systemctl.md b/script/readme-systemctl.md index 6de19dc67..468447ed2 100644 --- a/script/readme-systemctl.md +++ b/script/readme-systemctl.md @@ -1,5 +1,5 @@ -# Linux script -该脚本是RULEX的系统服务操作脚本,处理RULEX的安装、启动、停止、卸载等。 +# Linux systemctl +该脚本是RULEX的`systemctl`操作脚本,处理RULEX的安装、启动、停止、卸载等。 ## 基础使用 将安装包解压: ```sh @@ -26,42 +26,4 @@ unzip rulex-arm32linux-v0.6.2.zip -d rulex - 卸载 ```sh ./rulex_systemctl.sh uninstall - ``` -## 操作演示 -```sh -rer@revb-h3:~/Desktop/rulex$ unzip rulex-arm32linux-v0.6.2.zip -d rulex -Archive: rulex-arm32linux-v0.6.2.zip - inflating: rulex/rulex - inflating: rulex/LICENSE - inflating: rulex/rulex.ini - inflating: rulex/rulex_systemctl.sh -rer@revb-h3:~/Desktop/rulex$ ll -total 16540 -drwxrwxrwx 3 rer rer 4096 Sep 4 21:00 ./ -drwxrwxrwx 3 rer rer 4096 May 19 2022 ../ -drwxrwxr-x 2 rer rer 4096 Sep 4 21:00 rulex/ --rw-rw-r-- 1 rer rer 16921343 Sep 4 21:00 rulex-arm32linux-v0.6.2.zip -rer@revb-h3:~/Desktop/rulex$ cd rulex/ -rer@revb-h3:~/Desktop/rulex/rulex$ ll -total 45848 -drwxrwxr-x 2 rer rer 4096 Sep 4 21:00 ./ -drwxrwxrwx 3 rer rer 4096 Sep 4 21:00 ../ --rwxrwxrwx 1 rer rer 34523 Sep 4 20:51 LICENSE* --rwxrwxrwx 1 rer rer 46891964 Sep 4 20:52 rulex* --rwxrwxrwx 1 rer rer 2104 Sep 4 20:51 rulex_systemctl.sh* --rwxrwxrwx 1 rer rer 2605 Sep 4 20:51 rulex.ini* -rer@revb-h3:~/Desktop/rulex/rulex$ ./rulex_systemctl.sh install -This script must be run as root -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh install -Created symlink /etc/systemd/system/multi-user.target.wants/rulex.service → /etc/systemd/system/rulex.service. -Rulex service has been created and extracted. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh start -RULEX started as a daemon. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh restart -RULEX started as a daemon. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh stop -Service Rulex has been stopped. -rer@revb-h3:~/Desktop/rulex/rulex$ sudo ./rulex_systemctl.sh uninstall -Removed /etc/systemd/system/multi-user.target.wants/rulex.service. -Rulex has been uninstalled. -``` \ No newline at end of file + ``` \ No newline at end of file diff --git a/script/readme-windows.md b/script/readme-windows.md new file mode 100644 index 000000000..fd37107d3 --- /dev/null +++ b/script/readme-windows.md @@ -0,0 +1,22 @@ + + +# Windows 服务安装 +- 安装:rulex_install.bat +- 卸载:rulex_uninstall.bat + +> 只支持windows10+ \ No newline at end of file diff --git a/test/conf/licence.key b/test/conf/licence.key new file mode 100644 index 000000000..bb51973d3 --- /dev/null +++ b/test/conf/licence.key @@ -0,0 +1 @@ +914674f13f92175feceac1cd70d566cc \ No newline at end of file diff --git a/test/conf/licence.lic b/test/conf/licence.lic new file mode 100644 index 000000000..eb662e1e1 --- /dev/null +++ b/test/conf/licence.lic @@ -0,0 +1 @@ +P2UO_dEbw5sCsXBYAF6hGgUIdTEyBi9K7x6Wai1UpymdycrtVV2Fqtwt1ssydG1U \ No newline at end of file From de58c8e3e3c0b3a60dc2da580e2c3b84a0aa4813 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 18 Nov 2023 16:49:30 +0800 Subject: [PATCH 014/138] dev: optimize LicenseManager --- plugin/license_manager/license_manager.go | 39 ++++++++++++----------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/plugin/license_manager/license_manager.go b/plugin/license_manager/license_manager.go index a5dc8367f..858c14e07 100644 --- a/plugin/license_manager/license_manager.go +++ b/plugin/license_manager/license_manager.go @@ -23,17 +23,11 @@ type LicenseManager struct { AdminPassword string } -// admin := { -// Username: "open-rhino", -// Password: "open-hoot", -// } -// -// // 出厂的第一台设备 -// -// device := { -// CpuId: "o:p:e:n:r:h:i:n:o", -// EthMac: "o:p:e:n:h:o:o:t", -// } +/* +* +* 开源版本默认是给一个授权证书 +* + */ func NewLicenseManager(r typex.RuleX) *LicenseManager { return &LicenseManager{ uuid: "LicenseManager", @@ -44,37 +38,44 @@ func NewLicenseManager(r typex.RuleX) *LicenseManager { } } -// Init 初始化LicenseManager func (l *LicenseManager) Init(section *ini.Section) error { license_path, err1 := section.GetKey("license_path") + errMsg := "Load License Public Cipher Failed, May be Your License IS Invalid." if err1 != nil { - glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") + glogger.GLogger.Fatal() + os.Exit(0) } license_key, err2 := section.GetKey("key_path") if err2 != nil { - glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") + glogger.GLogger.Fatal(errMsg) + os.Exit(0) } lic, err1 := os.ReadFile(license_path.String()) if err1 != nil { - glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") + glogger.GLogger.Fatal(errMsg) + os.Exit(0) } license := string(lic) key, err2 := os.ReadFile(license_key.String()) if err2 != nil { - glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") + glogger.GLogger.Fatal(errMsg) + os.Exit(0) } private := string(key) localMacSum := SumMd5(fmt.Sprintf("%s,%s", l.CpuId, l.EthMac)) localAdminSum := SumMd5(fmt.Sprintf("%s,%s", l.AdminUsername, l.AdminPassword)) adminSalt, err3 := DecryptAES(private, license) if err3 != nil { - glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") + glogger.GLogger.Fatal(errMsg) + os.Exit(0) } if localAdminSum != private { - glogger.GLogger.Fatal("Load License Public Cipher Failed, May be Your License IS Invalid.") + glogger.GLogger.Fatal(errMsg) + os.Exit(0) } if adminSalt != localMacSum { - glogger.GLogger.Fatal("Load License Failed, May be Your License IS Invalid.") + glogger.GLogger.Fatal(errMsg) + os.Exit(0) } glogger.GLogger.Info("Load License Success:", license) return nil From 2362f29cda578c03cbbcb2743a5b037365c4c9ed Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 18 Nov 2023 18:03:49 +0800 Subject: [PATCH 015/138] doc: add tdengine target doc --- target/tdengine_target.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 target/tdengine_target.md diff --git a/target/tdengine_target.md b/target/tdengine_target.md new file mode 100644 index 000000000..cef04b0b6 --- /dev/null +++ b/target/tdengine_target.md @@ -0,0 +1,23 @@ +# Tdengine 支持 + +## 测试 +新建一个数据库,这里用Docker: +```sh +docker run -d --name tdengine -p 6041:6041 tdengine/tdengine +``` +新建测试库: +```sql +create database if not exists rhino +``` +新建测试表 +```sql +create table if not exists tb1 (ts timestamp, a int) +``` +插入数据 +```sql +use rhino; +insert into tb1 values(now, 0)(now+1s,1)(now+2s,2)(now+3s,3); +insert into tb1 values(now, 0)(now+1s,1)(now+2s,2)(now+3s,3); +insert into tb1 values(now, 0)(now+1s,1)(now+2s,2)(now+3s,3); +``` + From 587c5edf7ef1fa5466784fc4d36886e72896dab1 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 19 Nov 2023 19:12:23 +0800 Subject: [PATCH 016/138] dev: move api file --- {docs => component/cron_task/docs}/docs.go | 0 {docs => component/cron_task/docs}/swagger.json | 0 {docs => component/cron_task/docs}/swagger.yaml | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {docs => component/cron_task/docs}/docs.go (100%) rename {docs => component/cron_task/docs}/swagger.json (100%) rename {docs => component/cron_task/docs}/swagger.yaml (100%) diff --git a/docs/docs.go b/component/cron_task/docs/docs.go similarity index 100% rename from docs/docs.go rename to component/cron_task/docs/docs.go diff --git a/docs/swagger.json b/component/cron_task/docs/swagger.json similarity index 100% rename from docs/swagger.json rename to component/cron_task/docs/swagger.json diff --git a/docs/swagger.yaml b/component/cron_task/docs/swagger.yaml similarity index 100% rename from docs/swagger.yaml rename to component/cron_task/docs/swagger.yaml From 2c70ff08566fbc0b9ee72dd8ed6f20f2c3d2e144 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 19 Nov 2023 20:32:59 +0800 Subject: [PATCH 017/138] dev: add get eth0 addr func --- main.go | 41 +++++++++++++++++++++ ossupport/rhinoh3_ubuntu18xx_network_ctl.go | 22 +++++++++++ 2 files changed, 63 insertions(+) diff --git a/main.go b/main.go index c3f347b35..7f781292b 100644 --- a/main.go +++ b/main.go @@ -142,6 +142,47 @@ func main() { return nil }, }, + { + Name: "active", + Usage: "active -H host -U rhino -P hoot", + Hidden: true, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "H", + Usage: "active server ip", + }, + &cli.StringFlag{ + Name: "U", + Usage: "active admin username", + }, + &cli.StringFlag{ + Name: "P", + Usage: "active admin password", + }, + }, + Action: func(c *cli.Context) error { + host := c.String("H") + if host == "" { + return fmt.Errorf("[LICENCE ACTIVE]: missing host") + } + username := c.String("U") + if username == "" { + return fmt.Errorf("[LICENCE ACTIVE]: missing admin username") + } + password := c.String("P") + if password == "" { + return fmt.Errorf("[LICENCE ACTIVE]: missing admin password") + } + macAddr, err := ossupport.ReadIfaceMacAddr("eth0") + if err != nil { + return err + } + // commercial version will implement it + log.Printf("[LICENCE ACTIVE]: Admin(%s,%s), mac addr:[%s] try to request license from %s\n", + username, password, macAddr, host) + return nil + }, + }, // version { Name: "version", diff --git a/ossupport/rhinoh3_ubuntu18xx_network_ctl.go b/ossupport/rhinoh3_ubuntu18xx_network_ctl.go index 4b61684a4..7fc0a1164 100644 --- a/ossupport/rhinoh3_ubuntu18xx_network_ctl.go +++ b/ossupport/rhinoh3_ubuntu18xx_network_ctl.go @@ -3,6 +3,8 @@ package ossupport import ( "encoding/json" "fmt" + "os" + "path/filepath" "strings" ) @@ -68,3 +70,23 @@ func (iface *EtcNetworkConfig) GenEtcConfig() string { configText := strings.Join(configLines, "\n") return configText } + +/* +* +* 获取网卡的MAC地址 +* + */ +func ReadIfaceMacAddr(ifaceName string) (string, error) { + // 构建文件路径 + filePath := filepath.Join("/sys/class/net", ifaceName, "address") + + // 读取文件内容 + content, err := os.ReadFile(filePath) + if err != nil { + return "", err + } + if len(content) < 10 { + return "", fmt.Errorf("get mac address error:%s", ifaceName) + } + return string(content[:len(content)-1]), nil +} From cb00d53f57af5ce837aad48ddf97cfd577220a40 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 11:48:00 +0800 Subject: [PATCH 018/138] ci: remove unused ci; update doc --- .github/workflows/2_build_and_test.yml | 2 ++ ...ld-arm-32-v7.yml => 3_build-arm-32-v7.yml} | 0 .github/workflows/3_build-windows.yaml | 35 ------------------- README.md | 17 +++++++++ main.go | 1 + 5 files changed, 20 insertions(+), 35 deletions(-) rename .github/workflows/{4_build-arm-32-v7.yml => 3_build-arm-32-v7.yml} (100%) delete mode 100644 .github/workflows/3_build-windows.yaml diff --git a/.github/workflows/2_build_and_test.yml b/.github/workflows/2_build_and_test.yml index cd471f72e..3d71ab932 100644 --- a/.github/workflows/2_build_and_test.yml +++ b/.github/workflows/2_build_and_test.yml @@ -37,3 +37,5 @@ jobs: go test -timeout 30s -run ^Test_data_to_tdengine$ github.com/hootrhino/rulex/test -v -count=1 # go test -timeout 30s -run ^Test_DataToMongo$ github.com/hootrhino/rulex/test -v -count=1 + chmod +x ./release_pkg.sh + bash ./release_pkg.sh diff --git a/.github/workflows/4_build-arm-32-v7.yml b/.github/workflows/3_build-arm-32-v7.yml similarity index 100% rename from .github/workflows/4_build-arm-32-v7.yml rename to .github/workflows/3_build-arm-32-v7.yml diff --git a/.github/workflows/3_build-windows.yaml b/.github/workflows/3_build-windows.yaml deleted file mode 100644 index 7c8bee936..000000000 --- a/.github/workflows/3_build-windows.yaml +++ /dev/null @@ -1,35 +0,0 @@ -name: 3- Windows构建测试 -on: - push: - branches: [master] - pull_request: - branches: [master] - -jobs: - create_release: - name: Windows构建测试 - runs-on: windows-2022 - steps: - - name: Install Chocolate - shell: powershell - run: | - Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString("https://community.chocolatey.org/install.ps1")) - choco feature enable -n=allowGlobalConfirmation - - - name: Install Visualcpp-build-tools - shell: powershell - run: choco install visualcpp-build-tools -Y - - - name: Install golang - shell: powershell - run: | - choco upgrade chocolatey - choco install make -Y - choco install golang --version 1.20.1 -Y - - # - name: Build - # shell: powershell - # run: | - # go mod tidy - # go build - # go.exe test -timeout 30s -run ^TestFullyRun$ github.com/hootrhino/rulex/test -v -count=1 diff --git a/README.md b/README.md index 31315fa13..1cf605548 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,23 @@ ## 快速开始 +### 源码编译 +#### 环境安装 +下面是Ubuntu上搭建环境的指令: +```bash +sudo apt install jq cloc protobuf-compiler \ + gcc-mingw-w64-x86-64 \ + gcc-arm-linux-gnueabi \ + gcc-mips-linux-gnu \ + gcc-mingw-w64 \ + gcc-aarch64-linux-gnu -y +``` +> 推荐使用ubuntu开发。 + +#### 编译 +```sh +make +``` ### HelloWorld 下面展示一个最简单的设备数据转发案例: diff --git a/main.go b/main.go index 7f781292b..4ca2fd2ab 100644 --- a/main.go +++ b/main.go @@ -160,6 +160,7 @@ func main() { Usage: "active admin password", }, }, + Action: func(c *cli.Context) error { host := c.String("H") if host == "" { From 7cb4d2c63d8fa964250ff23f6141349ed048cdbb Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 13:46:18 +0800 Subject: [PATCH 019/138] fix: fix get unix port list failed --- ossupport/unix_dev_tree_ctrl.go | 49 +++++++++++++++++++ plugin/http_server/apis/system_api.go | 8 ++- .../service/hw_intrerface_service.go | 11 ++++- test/list_serial_port_test.go | 16 +++--- 4 files changed, 73 insertions(+), 11 deletions(-) create mode 100644 ossupport/unix_dev_tree_ctrl.go diff --git a/ossupport/unix_dev_tree_ctrl.go b/ossupport/unix_dev_tree_ctrl.go new file mode 100644 index 000000000..567683352 --- /dev/null +++ b/ossupport/unix_dev_tree_ctrl.go @@ -0,0 +1,49 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package ossupport + +import ( + "os" + "regexp" +) + +const devFolder = "/dev" +const regexFilter = "(ttyS|ttyHS|ttyUSB|ttyACM|ttyAMA|rfcomm|ttyO|ttymxc)[0-9]{1,3}" + +func GetPortsListUnix() ([]string, error) { + files, err := os.ReadDir(devFolder) + if err != nil { + return nil, err + } + ports := make([]string, 0, len(files)) + regex, err := regexp.Compile(regexFilter) + if err != nil { + return nil, err + } + for _, f := range files { + // Skip folders + if f.IsDir() { + continue + } + if !regex.MatchString(f.Name()) { + continue + } + portName := devFolder + "/" + f.Name() + ports = append(ports, portName) + } + + return ports, nil +} diff --git a/plugin/http_server/apis/system_api.go b/plugin/http_server/apis/system_api.go index 3d6c5412a..b6d426d82 100644 --- a/plugin/http_server/apis/system_api.go +++ b/plugin/http_server/apis/system_api.go @@ -3,6 +3,7 @@ package apis import ( "fmt" "net" + "runtime" // "runtime" "strconv" @@ -254,7 +255,12 @@ func DType(c *gin.Context, ruleEngine typex.RuleX) { * */ func GetUarts(c *gin.Context, ruleEngine typex.RuleX) { - ports, _ := serial.GetPortsList() + var ports []string + if runtime.GOOS == "windows" { + ports, _ = serial.GetPortsList() + } else { + ports, _ = ossupport.GetPortsListUnix() + } c.JSON(common.HTTP_OK, common.OkWithData(ports)) } diff --git a/plugin/http_server/service/hw_intrerface_service.go b/plugin/http_server/service/hw_intrerface_service.go index 03672f365..dc58dc908 100644 --- a/plugin/http_server/service/hw_intrerface_service.go +++ b/plugin/http_server/service/hw_intrerface_service.go @@ -17,8 +17,10 @@ package service import ( "encoding/json" + "runtime" "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/ossupport" "github.com/hootrhino/rulex/plugin/http_server/model" "go.bug.st/serial" ) @@ -129,10 +131,15 @@ func InitHwPortConfig() error { * */ func getOsPort() []string { - ports, _ := serial.GetPortsList() + var ports []string + if runtime.GOOS == "windows" { + ports, _ = serial.GetPortsList() + } else { + ports, _ = ossupport.GetPortsListUnix() + } List := []string{} for _, port := range ports { - // 明确知道有这么多端口,啰嗦代码是为了标记以免以后忘记 + // 明确知道有这么多端口是被占用的,啰嗦代码是为了标记以免以后忘记 if port == "COM0" { continue } diff --git a/test/list_serial_port_test.go b/test/list_serial_port_test.go index f383ad90c..e57b37ab7 100644 --- a/test/list_serial_port_test.go +++ b/test/list_serial_port_test.go @@ -1,9 +1,10 @@ package test import ( + "runtime" "testing" - "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/ossupport" "go.bug.st/serial" ) @@ -11,12 +12,11 @@ func Test_GetPortsList(t *testing.T) { t.Log(GetUartList()) } func GetUartList() []string { - r := []string{} - ports, err := serial.GetPortsList() - if err != nil { - glogger.GLogger.Error(err) - return r + var ports []string + if runtime.GOOS == "windows" { + ports, _ = serial.GetPortsList() + } else { + ports, _ = ossupport.GetPortsListUnix() } - r = append(r, ports...) - return r + return ports } From 92bd644f74b070116b60e1c5bf4202a1e3163ad9 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 15:45:28 +0800 Subject: [PATCH 020/138] dev: support user led --- bspsupport/eekit_adda_linux.go | 14 ++++++++++++- bspsupport/rhinopi_gpio_ctrl.go | 24 +++++++++++++++++----- component/appstack/appstack_lua_runtime.go | 3 +++ engine/rule_lua_runtime.go | 3 +++ release_pkg.sh | 2 +- rulexlib/eekith3_adda_lib.go | 24 ++++++++++++++++++++++ script/rulex-systemctl.sh | 13 +++++++++--- 7 files changed, 73 insertions(+), 10 deletions(-) diff --git a/bspsupport/eekit_adda_linux.go b/bspsupport/eekit_adda_linux.go index 03a5e6e01..65c867665 100644 --- a/bspsupport/eekit_adda_linux.go +++ b/bspsupport/eekit_adda_linux.go @@ -25,14 +25,18 @@ import ( DI1 -> PA8 DI2 -> PA9 DI3 -> PA10 + USER_GPIO -> PA20 */ const ( + // DO eekit_DO1 string = "6" eekit_DO2 string = "7" - + // DI eekit_DI1 string = "8" eekit_DI2 string = "9" eekit_DI3 string = "10" + // Use LED + eekit_USER_GPIO string = "20" ) const ( @@ -56,11 +60,13 @@ func _EEKIT_GPIOAllInit() int { gpio8 := "/sys/class/gpio/gpio8/value" gpio9 := "/sys/class/gpio/gpio9/value" gpio10 := "/sys/class/gpio/gpio10/value" + gpio20 := "/sys/class/gpio/gpio20/value" _, err1 := os.Stat(gpio6) _, err2 := os.Stat(gpio7) _, err3 := os.Stat(gpio8) _, err4 := os.Stat(gpio9) _, err5 := os.Stat(gpio10) + _, err6 := os.Stat(gpio20) if err1 != nil { if strings.Contains(err1.Error(), "no such file or directory") { _EEKIT_GPIOInit(eekit_DO1, eekit_Out) @@ -91,6 +97,12 @@ func _EEKIT_GPIOAllInit() int { fmt.Println("EEKIT_GPIOAllInit DI3 In Mode Ok") } } + if err6 != nil { + if strings.Contains(err5.Error(), "no such file or directory") { + _EEKIT_GPIOInit(eekit_USER_GPIO, eekit_Out) + fmt.Println("EEKIT_GPIOAllInit USER_GPIO Out Mode Ok") + } + } // 返回值无用 return 1 } diff --git a/bspsupport/rhinopi_gpio_ctrl.go b/bspsupport/rhinopi_gpio_ctrl.go index 4385b81b6..008ddeaf1 100644 --- a/bspsupport/rhinopi_gpio_ctrl.go +++ b/bspsupport/rhinopi_gpio_ctrl.go @@ -15,6 +15,19 @@ package archsupport +//----------------------------------------------- +// 这是EEKIT网关的DI-DO支持库 +//----------------------------------------------- +/* + pins map + + DO1 -> PA6 + DO2 -> PA7 + DI1 -> PA8 + DI2 -> PA9 + DI3 -> PA10 + USER_GPIO -> PA20 +*/ import ( "fmt" "os" @@ -27,11 +40,6 @@ import ( */ const ( __h3_GPIO_PATH = "/sys/class/gpio/gpio%v/value" - // __h3_DO1 = "/sys/class/gpio/gpio6/value" // gpio6 - // __h3_DO2 = "/sys/class/gpio/gpio7/value" // gpio7 - // __h3_DI1 = "/sys/class/gpio/gpio8/value" // gpio8 - // __h3_DI2 = "/sys/class/gpio/gpio9/value" // gpio9 - // __h3_DI3 = "/sys/class/gpio/gpio10/value" // gpio10 ) /* @@ -54,6 +62,9 @@ func EEKIT_GPIOGetDI2() (int, error) { func EEKIT_GPIOGetDI3() (int, error) { return EEKIT_GPIOGetByFile(10) } +func EEKIT_GPIOGetUserGpio() (int, error) { + return EEKIT_GPIOGetByFile(20) +} func EEKIT_GPIOGetByFile(pin byte) (int, error) { return __GPIOGet(fmt.Sprintf(__h3_GPIO_PATH, pin)) } @@ -91,6 +102,9 @@ func EEKIT_GPIOSetDI2(value int) error { func EEKIT_GPIOSetDI3(value int) error { return EEKIT_GPIOSetByFile(10, value) } +func EEKIT_GPIOSetUserGpio(value int) error { + return EEKIT_GPIOSetByFile(20, value) +} func EEKIT_GPIOSetByFile(pin, value int) error { return __GPIOSet(fmt.Sprintf(__h3_GPIO_PATH, pin), value) diff --git a/component/appstack/appstack_lua_runtime.go b/component/appstack/appstack_lua_runtime.go index c83f70279..4148f9dd1 100644 --- a/component/appstack/appstack_lua_runtime.go +++ b/component/appstack/appstack_lua_runtime.go @@ -186,6 +186,9 @@ func LoadAppLib(app *Application, e typex.RuleX) { addAppLib(app, e, "rhinopi", "DI1Get", rulexlib.H3DI1Get(e)) addAppLib(app, e, "rhinopi", "DI2Get", rulexlib.H3DI2Get(e)) addAppLib(app, e, "rhinopi", "DI3Get", rulexlib.H3DI3Get(e)) + // LED + addAppLib(app, e, "rhinopi", "LedOn", rulexlib.LedOn(e)) + addAppLib(app, e, "rhinopi", "LedOff", rulexlib.LedOff(e)) } { diff --git a/engine/rule_lua_runtime.go b/engine/rule_lua_runtime.go index f1a083c76..18784d6e6 100644 --- a/engine/rule_lua_runtime.go +++ b/engine/rule_lua_runtime.go @@ -132,6 +132,9 @@ func LoadBuildInLuaLib(e typex.RuleX, r *typex.Rule) { r.AddLib(e, "rhinopi", "DI1Get", rulexlib.H3DI1Get(e)) r.AddLib(e, "rhinopi", "DI2Get", rulexlib.H3DI2Get(e)) r.AddLib(e, "rhinopi", "DI3Get", rulexlib.H3DI3Get(e)) + // Led + r.AddLib(e, "rhinopi", "LedOn", rulexlib.LedOn(e)) + r.AddLib(e, "rhinopi", "LedOff", rulexlib.LedOff(e)) } // Modbus diff --git a/release_pkg.sh b/release_pkg.sh index ade84ad52..1a319eb52 100755 --- a/release_pkg.sh +++ b/release_pkg.sh @@ -153,7 +153,7 @@ fetch_dashboard() { gen_changelog() { echo -e "[.]Version Change log:" - log=$(git log --oneline --pretty=format:"\033[0;31m[#]\033[0m%s\n" $(git describe --abbrev=0 --tags).. | cat) + log=$(git log --oneline --pretty=format:" \033[0;31m[#]\033[0m%s\n" $(git describe --abbrev=0 --tags).. | cat) echo -e $log } diff --git a/rulexlib/eekith3_adda_lib.go b/rulexlib/eekith3_adda_lib.go index d88e4c96d..814cbec1c 100644 --- a/rulexlib/eekith3_adda_lib.go +++ b/rulexlib/eekith3_adda_lib.go @@ -115,3 +115,27 @@ func H3DI3Get(rx typex.RuleX) func(*lua.LState) int { return 2 } } + +// User Gpio operation +func LedOn(rx typex.RuleX) func(*lua.LState) int { + return func(l *lua.LState) int { + e := archsupport.EEKIT_GPIOSetUserGpio(0) + if e != nil { + l.Push(lua.LString(e.Error())) + } else { + l.Push(lua.LNil) + } + return 1 + } +} +func LedOff(rx typex.RuleX) func(*lua.LState) int { + return func(l *lua.LState) int { + e := archsupport.EEKIT_GPIOSetUserGpio(1) + if e != nil { + l.Push(lua.LString(e.Error())) + } else { + l.Push(lua.LNil) + } + return 1 + } +} diff --git a/script/rulex-systemctl.sh b/script/rulex-systemctl.sh index 86f5f6cc5..6dc6035fe 100644 --- a/script/rulex-systemctl.sh +++ b/script/rulex-systemctl.sh @@ -45,7 +45,8 @@ EOL chmod +x $source_dir/rulex cp "$source_dir/rulex" "$executable" cp "$source_dir/rulex.ini" "$config_file" - cp "$source_dir/license.*" /usr/local/ + cp "$source_dir/license.key" /usr/local/ + cp "$source_dir/license.lic" /usr/local/ systemctl daemon-reload systemctl enable rulex systemctl start rulex @@ -77,7 +78,12 @@ stop(){ } remove_files(){ if ls $1 1> /dev/null 2>&1; then - rm $1 + rm -rf $1 + if [[ $path == *"/upload"* ]]; then + rm -rf $1 + else + rm $1 + fi echo "[!] $1 files removed." else echo "[#] $1 files not found. No need to remove." @@ -93,7 +99,8 @@ uninstall(){ remove_files $working_directory/rulex.db remove_files $working_directory/*.txt remove_files $working_directory/upload/ - remove_files $working_directory/license.* + remove_files $working_directory/license.key + remove_files $working_directory/license.lic remove_files $working_directory/*.txt.gz systemctl daemon-reload systemctl reset-failed From 5ff972da54b9f39cb68ba88e89aa8193f92863a3 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 15:49:23 +0800 Subject: [PATCH 021/138] dev: optimize user led --- component/appstack/appstack_lua_runtime.go | 4 ++-- engine/rule_lua_runtime.go | 4 ++-- rulexlib/eekith3_adda_lib.go | 5 +++-- test/apps/user_led_ctrl.lua | 19 +++++++++++++++++++ 4 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 test/apps/user_led_ctrl.lua diff --git a/component/appstack/appstack_lua_runtime.go b/component/appstack/appstack_lua_runtime.go index 4148f9dd1..6bc0f82c9 100644 --- a/component/appstack/appstack_lua_runtime.go +++ b/component/appstack/appstack_lua_runtime.go @@ -187,8 +187,8 @@ func LoadAppLib(app *Application, e typex.RuleX) { addAppLib(app, e, "rhinopi", "DI2Get", rulexlib.H3DI2Get(e)) addAppLib(app, e, "rhinopi", "DI3Get", rulexlib.H3DI3Get(e)) // LED - addAppLib(app, e, "rhinopi", "LedOn", rulexlib.LedOn(e)) - addAppLib(app, e, "rhinopi", "LedOff", rulexlib.LedOff(e)) + addAppLib(app, e, "rhinopi", "Led1On", rulexlib.Led1On(e)) + addAppLib(app, e, "rhinopi", "Led1Off", rulexlib.Led1Off(e)) } { diff --git a/engine/rule_lua_runtime.go b/engine/rule_lua_runtime.go index 18784d6e6..7481a246b 100644 --- a/engine/rule_lua_runtime.go +++ b/engine/rule_lua_runtime.go @@ -133,8 +133,8 @@ func LoadBuildInLuaLib(e typex.RuleX, r *typex.Rule) { r.AddLib(e, "rhinopi", "DI2Get", rulexlib.H3DI2Get(e)) r.AddLib(e, "rhinopi", "DI3Get", rulexlib.H3DI3Get(e)) // Led - r.AddLib(e, "rhinopi", "LedOn", rulexlib.LedOn(e)) - r.AddLib(e, "rhinopi", "LedOff", rulexlib.LedOff(e)) + r.AddLib(e, "rhinopi", "Led1On", rulexlib.Led1On(e)) + r.AddLib(e, "rhinopi", "Led1Off", rulexlib.Led1Off(e)) } // Modbus diff --git a/rulexlib/eekith3_adda_lib.go b/rulexlib/eekith3_adda_lib.go index 814cbec1c..1307509a2 100644 --- a/rulexlib/eekith3_adda_lib.go +++ b/rulexlib/eekith3_adda_lib.go @@ -117,7 +117,8 @@ func H3DI3Get(rx typex.RuleX) func(*lua.LState) int { } // User Gpio operation -func LedOn(rx typex.RuleX) func(*lua.LState) int { +// 注意:低电平亮 +func Led1On(rx typex.RuleX) func(*lua.LState) int { return func(l *lua.LState) int { e := archsupport.EEKIT_GPIOSetUserGpio(0) if e != nil { @@ -128,7 +129,7 @@ func LedOn(rx typex.RuleX) func(*lua.LState) int { return 1 } } -func LedOff(rx typex.RuleX) func(*lua.LState) int { +func Led1Off(rx typex.RuleX) func(*lua.LState) int { return func(l *lua.LState) int { e := archsupport.EEKIT_GPIOSetUserGpio(1) if e != nil { diff --git a/test/apps/user_led_ctrl.lua b/test/apps/user_led_ctrl.lua new file mode 100644 index 000000000..d280a0f3b --- /dev/null +++ b/test/apps/user_led_ctrl.lua @@ -0,0 +1,19 @@ +---@diagnostic disable: undefined-global +-- +-- App use lua syntax, goto https://hootrhino.github.io for more document +-- APPID: APP6b28330ff4be4b0ba2f3e9317c4e2a47 +-- +AppNAME = "LED-RGB" +AppVERSION = "1.0.0" +AppDESCRIPTION = "" +-- +-- Main +-- +function Main(arg) + while true do + rhinopi:Led1On() + time:Sleep(200) + rhinopi:Led1Off() + time:Sleep(200) + end +end From 74e1f9b67703c38ce993c85f127b5c226a7f4bb2 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 22:26:25 +0800 Subject: [PATCH 022/138] ci: fix ci --- .github/workflows/2_build_and_test.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/2_build_and_test.yml b/.github/workflows/2_build_and_test.yml index 3d71ab932..e07dfa78c 100644 --- a/.github/workflows/2_build_and_test.yml +++ b/.github/workflows/2_build_and_test.yml @@ -18,7 +18,12 @@ jobs: - name: Linux 构建测试 run: | sudo apt update -y - sudo apt install jq cloc protobuf-compiler -y + sudo apt install jq cloc protobuf-compiler \ + gcc-mingw-w64-x86-64 \ + gcc-arm-linux-gnueabi \ + gcc-mips-linux-gnu \ + gcc-mingw-w64 \ + gcc-aarch64-linux-gnu -y cloc ./ make # for test mqtt From 57d499215c3c92ead0a09d772c334b2c24d226ef Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 22:46:59 +0800 Subject: [PATCH 023/138] dev: optimize build script --- script/rulex-daemon.sh | 31 +++++++++++++++++++++++-------- script/rulex-systemctl.sh | 12 ++++++------ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index 11eadea36..2402cb76d 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -14,16 +14,31 @@ install_files() { cp "$working_directory"/rulex /usr/local/ cp "$working_directory"/rulex.ini /usr/local/ } +remove_files() { + if [ -e "$1" ]; then + if [[ $1 == *"/upload"* ]]; then + rm -rf "$1" + else + rm "$1" + fi + echo "[!] $1 files removed." + else + echo "[#] $1 files not found. No need to remove." + fi +} # Function to uninstall the service -uninstall_files() { - rm -f /usr/local/rulex - rm -f /usr/local/rulex.ini - rm -f /usr/local/rulex.db - rm -f /usr/local/*.txt - rm -f /usr/local/license.* - rm -rf /usr/local/upload/ - rm -f /usr/local/*.txt.gz +uninstall(){ + local working_directory="/usr/local" + remove_files $working_directory/rulex + remove_files $working_directory/rulex.ini + remove_files $working_directory/rulex.db + remove_files $working_directory/*.txt + remove_files $working_directory/upload/ + remove_files $working_directory/license.key + remove_files $working_directory/license.lic + remove_files $working_directory/*.txt.gz + echo "[√] Rulex has been uninstalled." } start_service() { diff --git a/script/rulex-systemctl.sh b/script/rulex-systemctl.sh index 6dc6035fe..99860c945 100644 --- a/script/rulex-systemctl.sh +++ b/script/rulex-systemctl.sh @@ -76,19 +76,19 @@ stop(){ systemctl stop rulex echo "[√] Service Rulex has been stopped." } -remove_files(){ - if ls $1 1> /dev/null 2>&1; then - rm -rf $1 - if [[ $path == *"/upload"* ]]; then - rm -rf $1 +remove_files() { + if [ -e "$1" ]; then + if [[ $1 == *"/upload"* ]]; then + rm -rf "$1" else - rm $1 + rm "$1" fi echo "[!] $1 files removed." else echo "[#] $1 files not found. No need to remove." fi } + uninstall(){ local working_directory="/usr/local" systemctl stop rulex From ad1abf49fff659473ab057807c2ec25cb9bd7839 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 22:51:53 +0800 Subject: [PATCH 024/138] dev: optimize linux daemon --- script/rulex-daemon.sh | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index 2402cb76d..4c3559a4f 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -7,12 +7,14 @@ USE_PROCD=1 # Check if the service is disabled [ -e /etc/config/rulex_daemon ] && . /etc/config/rulex_daemon -working_directory="./" +working_directory="/usr/local/" # Function to copy files to /usr/local install_files() { - cp "$working_directory"/rulex /usr/local/ - cp "$working_directory"/rulex.ini /usr/local/ + cp "./rulex $working_directory + cp "./rulex.ini $working_directory + cp "./license.key" $working_directory + cp "./license.lic" $working_directory } remove_files() { if [ -e "$1" ]; then @@ -27,20 +29,6 @@ remove_files() { fi } -# Function to uninstall the service -uninstall(){ - local working_directory="/usr/local" - remove_files $working_directory/rulex - remove_files $working_directory/rulex.ini - remove_files $working_directory/rulex.db - remove_files $working_directory/*.txt - remove_files $working_directory/upload/ - remove_files $working_directory/license.key - remove_files $working_directory/license.lic - remove_files $working_directory/*.txt.gz - echo "[√] Rulex has been uninstalled." -} - start_service() { if [ "$DISABLED" -eq 0 ]; then procd_open_instance @@ -72,7 +60,15 @@ enable_service() { # Function to uninstall the service uninstall_service() { - uninstall_files + procd_close_instance + remove_files $working_directory/rulex + remove_files $working_directory/rulex.ini + remove_files $working_directory/rulex.db + remove_files $working_directory/*.txt + remove_files $working_directory/upload/ + remove_files $working_directory/license.key + remove_files $working_directory/license.lic + remove_files $working_directory/*.txt.gz /etc/init.d/rulex_daemon stop /etc/init.d/rulex_daemon disable rm /etc/init.d/rulex_daemon From 4b46764a61387cee3afea9e2e1a1f9a353fd50ae Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 23:29:39 +0800 Subject: [PATCH 025/138] dev: add network:Ping function --- Makefile | 8 ++ component/appstack/appstack_lua_runtime.go | 2 + engine/rule_lua_runtime.go | 2 + main.go | 3 +- rulexlib/network_lib.go | 92 ++++++++++++++++++++++ typex/version.go | 4 +- 6 files changed, 108 insertions(+), 3 deletions(-) create mode 100644 rulexlib/network_lib.go diff --git a/Makefile b/Makefile index 075825100..cd30cc159 100644 --- a/Makefile +++ b/Makefile @@ -19,15 +19,18 @@ all: @echo "\e[41m[*] Host \e[0m: \e[36m ${host} \e[0m" @echo "\e[41m[*] IP \e[0m: \e[36m ${ip} \e[0m" @echo "\e[41m[*] Disk \e[0m: \e[36m ${disk} \e[0m" + go generate make build .PHONY: build build: CGO_ENABLED=1 GOOS=linux + go generate go build -v -ldflags "-s -w" -o ${APP} .PHONY: x64linux x64linux: + go generate CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=gcc\ go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-x64linux @@ -38,28 +41,33 @@ windows: .PHONY: arm32 arm32: + go generate CGO_ENABLED=1 GOOS=linux GOARCH=arm CC=arm-linux-gnueabi-gcc\ go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-arm32linux .PHONY: arm64 arm64: + go generate CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=aarch64-linux-gnu-gcc\ go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-arm64linux .PHONY: mips32 mips32: + go generate # sudo apt-get install gcc-mips-linux-gnu GOOS=linux GOARCH=mips CGO_ENABLED=1 CC=mips-linux-gnu-gcc\ go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-mips32linux .PHONY: mips64 mips64: + go generate # sudo apt-get install gcc-mips-linux-gnu GOOS=linux GOARCH=mips64 CGO_ENABLED=1 CC=mips-linux-gnu-gcc\ go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-mips64linux .PHONY: mipsel mipsle: + go generate # sudo apt-get install gcc-mipsel-linux-gnu GOOS=linux GOARCH=mipsle CGO_ENABLED=1 GOMIPS=softfloat CC=mipsel-linux-gnu-gcc\ go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-mipslelinux diff --git a/component/appstack/appstack_lua_runtime.go b/component/appstack/appstack_lua_runtime.go index 6bc0f82c9..2f47fa1fb 100644 --- a/component/appstack/appstack_lua_runtime.go +++ b/component/appstack/appstack_lua_runtime.go @@ -213,4 +213,6 @@ func LoadAppLib(app *Application, e typex.RuleX) { addAppLib(app, e, "rpc", "Request", rulexlib.Request(e)) // jq addAppLib(app, e, "jq", "Execute", rulexlib.JqSelect(e)) + // Ping + addAppLib(app, e, "network", "Ping", rulexlib.PingIp(e)) } diff --git a/engine/rule_lua_runtime.go b/engine/rule_lua_runtime.go index 7481a246b..9fb3ca3e1 100644 --- a/engine/rule_lua_runtime.go +++ b/engine/rule_lua_runtime.go @@ -154,6 +154,8 @@ func LoadBuildInLuaLib(e typex.RuleX, r *typex.Rule) { r.AddLib(e, "math", "TFloat", rulexlib.TruncateFloat(e)) // LocalDBQuery r.AddLib(e, "datacenter", "DBQuery", rulexlib.LocalDBQuery(e)) + // + r.AddLib(e, "network", "Ping", rulexlib.PingIp(e)) } diff --git a/main.go b/main.go index 4ca2fd2ab..19de16ec7 100644 --- a/main.go +++ b/main.go @@ -36,6 +36,7 @@ func init() { typex.DefaultVersion.Arch = arch } +//go:generate bash ./gen_info.sh func main() { app := &cli.App{ Name: "RULEX Gateway FrameWork", @@ -160,7 +161,7 @@ func main() { Usage: "active admin password", }, }, - + Action: func(c *cli.Context) error { host := c.String("H") if host == "" { diff --git a/rulexlib/network_lib.go b/rulexlib/network_lib.go new file mode 100644 index 000000000..382af4d1a --- /dev/null +++ b/rulexlib/network_lib.go @@ -0,0 +1,92 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// if Duration, err := pingQ(ip, 2000*time.Millisecond); err != nil { +// glogger.GLogger.WithFields(Fields).Info(fmt.Sprintf( +// "[Count:%d] Ping Error:%s", i, +// err.Error())) +// } else { +// +// glogger.GLogger.WithFields(Fields).Info(fmt.Sprintf( +// "[Count:%d] Ping Reply From %s: time=%v ms TTL=128", i, +// tt, Duration)) +// } +package rulexlib + +import ( + "net" + "time" + + lua "github.com/hootrhino/gopher-lua" + "github.com/hootrhino/rulex/typex" +) + +/* +* +* Ping +* + */ +func PingIp(rx typex.RuleX) func(l *lua.LState) int { + return func(l *lua.LState) int { + ip := l.ToString(2) + Duration, err := pingQ(ip, 5000*time.Millisecond) + l.Push(lua.LNumber(Duration)) + l.Push(lua.LString(err.Error())) + return 2 + } +} + +// -------------------------------------------------------------------------------------------------- +// private +// -------------------------------------------------------------------------------------------------- +func pingQ(ip string, timeout time.Duration) (time.Duration, error) { + const IcmpLen = 8 + msg := [32]byte{ + 8, 0, 0, 0, 0, 13, 0, 37, + } + check := checkSum(msg[:IcmpLen]) + msg[2] = byte(check >> 8) + msg[3] = byte(check & 255) + + remoteAddr, err := net.ResolveIPAddr("ip", ip) + if err != nil { + return 0, err + } + conn, err := net.DialIP("ip:icmp", nil, remoteAddr) + if err != nil { + return 0, err + } + start := time.Now() + if _, err := conn.Write(msg[:IcmpLen]); err != nil { + return 0, err + } + conn.SetReadDeadline(time.Now().Add(timeout)) + _, err1 := conn.Read(msg[:]) + conn.SetReadDeadline(time.Time{}) + if err1 != nil { + return 0, err1 + } + return time.Since(start), nil +} + +func checkSum(msg []byte) uint16 { + sum := 0 + for n := 0; n < len(msg); n += 2 { + sum += int(msg[n])<<8 + int(msg[n+1]) + } + sum = (sum >> 16) + sum&0xffff + sum += sum >> 16 + return uint16(^sum) +} diff --git a/typex/version.go b/typex/version.go index bb3463b52..9aa7a3f75 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,10 +12,10 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-14 21:53:36", + ReleaseTime: "2023-11-20 23:27:53", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-014c2c4e2cf3603 +** Version: v0.6.4-d4274c17c76b9c4 ** Document: https://hootrhino.github.io ` From f7c09c7c8bbaf2c6d336ddfe1d10e8214bfaf90e Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 23:32:31 +0800 Subject: [PATCH 026/138] dev: rm cached index.html --- plugin/http_server/server/www/index.html | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 plugin/http_server/server/www/index.html diff --git a/plugin/http_server/server/www/index.html b/plugin/http_server/server/www/index.html deleted file mode 100644 index 5a04e3493..000000000 --- a/plugin/http_server/server/www/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - rulex - - - - - - hello,rulex - - - \ No newline at end of file From 65f6d160c71aa9fb160a18e22fc321ba4c3e8b8f Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 23:35:18 +0800 Subject: [PATCH 027/138] dev: rename file --- plugin/http_server/server/www/index.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 plugin/http_server/server/www/index.html diff --git a/plugin/http_server/server/www/index.html b/plugin/http_server/server/www/index.html new file mode 100644 index 000000000..824fec1b7 --- /dev/null +++ b/plugin/http_server/server/www/index.html @@ -0,0 +1,18 @@ + + + + + + + + Rulex + + + + + + Hello,Rulex + + + \ No newline at end of file From b4cb62b53a95e9147a2e324d5bc64fd4f8683028 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 20 Nov 2023 23:56:04 +0800 Subject: [PATCH 028/138] fix :fix udp target delete panic --- plugin/http_server/server/www/index.html | 2 +- target/udp_target.go | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugin/http_server/server/www/index.html b/plugin/http_server/server/www/index.html index 824fec1b7..8e6265367 100644 --- a/plugin/http_server/server/www/index.html +++ b/plugin/http_server/server/www/index.html @@ -12,7 +12,7 @@ - Hello,Rulex + Hello,Rulex. \ No newline at end of file diff --git a/target/udp_target.go b/target/udp_target.go index 037f82f00..6807f7ca9 100644 --- a/target/udp_target.go +++ b/target/udp_target.go @@ -90,7 +90,9 @@ func (udpt *UdpTarget) To(data interface{}) (interface{}, error) { func (udpt *UdpTarget) Stop() { udpt.status = typex.SOURCE_STOP - udpt.CancelCTX() + if udpt.CancelCTX != nil { + udpt.CancelCTX() + } } func (udpt *UdpTarget) Details() *typex.OutEnd { return udpt.RuleEngine.GetOutEnd(udpt.PointId) From f14054b56516eb0cab18c4e9cfb06cdb2e5dec60 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 00:08:41 +0800 Subject: [PATCH 029/138] dev: rename data to udp --- test/apps/complex_data_push.lua | 2 +- test/apps/complex_data_push1.lua | 2 +- test/apps/data_to_screen_test.lua | 2 +- test/apps/data_udp_server.lua | 2 +- test/apps/h3_loop_di10.lua | 2 +- test/apps/h3_loop_di8.lua | 2 +- test/apps/h3_loop_di9.lua | 2 +- test/apps/read_multi_device1.lua | 2 +- test/target_data_toudp_test.go | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/apps/complex_data_push.lua b/test/apps/complex_data_push.lua index dfa1450a2..71adf330b 100644 --- a/test/apps/complex_data_push.lua +++ b/test/apps/complex_data_push.lua @@ -28,7 +28,7 @@ function Main(arg) state = string.sub(jsonT['out'], 9, 10) } print("udpData => ", udpData) - local err4 = applib:DataToUdp(udpServerUUID, udpData) + local err4 = data:ToUdp(udpServerUUID, udpData) print('DataToUdp success? =>', err4 == nil) time:Sleep(1000) until true diff --git a/test/apps/complex_data_push1.lua b/test/apps/complex_data_push1.lua index d657bc608..2cbd0bb1c 100644 --- a/test/apps/complex_data_push1.lua +++ b/test/apps/complex_data_push1.lua @@ -28,7 +28,7 @@ function Main(arg) state = string.sub(jsonT['out'], 9, 10) } print("udpData => ", udpData) - local err4 = applib:DataToUdp(udpServerUUID, udpData) + local err4 = data:ToUdp(udpServerUUID, udpData) print('DataToUdp success? =>', err4 == nil) time:Sleep(1000) end diff --git a/test/apps/data_to_screen_test.lua b/test/apps/data_to_screen_test.lua index 690061ac8..767c39e0b 100644 --- a/test/apps/data_to_screen_test.lua +++ b/test/apps/data_to_screen_test.lua @@ -21,7 +21,7 @@ function ToScreen(In, Out, Data) state = string.sub(jsonT['out'], 14, 14) } print("udpData => ", udpData) - local err4 = applib:DataToUdp(Out, udpData) + local err4 = data:ToUdp(Out, udpData) print('DataToUdp success? =>', err4 == nil) end diff --git a/test/apps/data_udp_server.lua b/test/apps/data_udp_server.lua index 1c5b0c6d8..4ac1f4be8 100644 --- a/test/apps/data_udp_server.lua +++ b/test/apps/data_udp_server.lua @@ -3,7 +3,7 @@ AppVERSION = '0.0.1' function Main(arg) for i = 1, 10, 1 do local data = { name = 'Demo', sn = 'A123456', state = '00' } - local err = applib:DataToUdp('UdpServer', applib:T2J(data)) + local err = data:ToUdp('UdpServer', applib:T2J(data)) applib:log('DataToUdp success? =>', err == nil) time:Sleep(100) end diff --git a/test/apps/h3_loop_di10.lua b/test/apps/h3_loop_di10.lua index 8e3dc0637..f02141b65 100644 --- a/test/apps/h3_loop_di10.lua +++ b/test/apps/h3_loop_di10.lua @@ -29,7 +29,7 @@ function Main(arg) break else if v ~= s then - local err0 = applib:DataToUdp('udpServerUUID', 'hello gpio10:' .. v) + local err0 = data:ToUdp('udpServerUUID', 'hello gpio10:' .. v) print('DataToUdp success? =>', err0 == nil) end s = v diff --git a/test/apps/h3_loop_di8.lua b/test/apps/h3_loop_di8.lua index cad27182c..14c2fe095 100644 --- a/test/apps/h3_loop_di8.lua +++ b/test/apps/h3_loop_di8.lua @@ -29,7 +29,7 @@ function Main(arg) break else if v ~= s then - local err0 = applib:DataToUdp('udpServerUUID', 'hello gpio8:' .. v) + local err0 = data:ToUdp('udpServerUUID', 'hello gpio8:' .. v) print('DataToUdp success? =>', err0 == nil) end s = v diff --git a/test/apps/h3_loop_di9.lua b/test/apps/h3_loop_di9.lua index 5078606ca..60acd5040 100644 --- a/test/apps/h3_loop_di9.lua +++ b/test/apps/h3_loop_di9.lua @@ -29,7 +29,7 @@ function Main(arg) break else if v ~= s then - local err0 = applib:DataToUdp('udpServerUUID', 'hello gpio9:' .. v) + local err0 = data:ToUdp('udpServerUUID', 'hello gpio9:' .. v) print('DataToUdp success? =>', err0 == nil) end s = v diff --git a/test/apps/read_multi_device1.lua b/test/apps/read_multi_device1.lua index 0fe8fec1b..c971aabe6 100644 --- a/test/apps/read_multi_device1.lua +++ b/test/apps/read_multi_device1.lua @@ -29,7 +29,7 @@ function Main(arg) state = string.sub(jsonT['out'], 9, 10) } print("UdpData => ", udpDataJson) - local err4 = applib:DataToUdp(udpServerUUID, udpDataJson) + local err4 = data:ToUdp(udpServerUUID, udpDataJson) print('DataToUdp success? =>', err4 == nil) time:Sleep(1000) end diff --git a/test/target_data_toudp_test.go b/test/target_data_toudp_test.go index 6937a0b50..8261afee4 100644 --- a/test/target_data_toudp_test.go +++ b/test/target_data_toudp_test.go @@ -16,7 +16,7 @@ import ( "github.com/hootrhino/rulex/typex" ) -var _DataToUdp_luaCase = `function Main(arg) for i = 1, 3, 1 do local err = applib:DataToUdp('UdpServer',applib:T2J({temp = 20,humi = 13.45})) applib:log('result =>',err) time:Sleep(100) end return 0 end` +var _DataToUdp_luaCase = `function Main(arg) for i = 1, 3, 1 do local err = data:ToUdp('UdpServer',applib:T2J({temp = 20,humi = 13.45})) applib:log('result =>',err) time:Sleep(100) end return 0 end` // go test -timeout 30s -run ^Test_DataToUdp github.com/hootrhino/rulex/test -v -count=1 From 5c19c2acd44090d4afc94f85759a706ff350ad44 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 11:57:26 +0800 Subject: [PATCH 030/138] dev: optimize queue --- component/interqueue/xqueue.go | 24 +++++++++++------------- conf/rulex.ini | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/component/interqueue/xqueue.go b/component/interqueue/xqueue.go index a88bc46a3..27db3aa61 100644 --- a/component/interqueue/xqueue.go +++ b/component/interqueue/xqueue.go @@ -5,8 +5,8 @@ import ( "errors" "fmt" - "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/component/intermetric" + "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" ) @@ -64,7 +64,7 @@ func InitDataCacheQueue(rulex typex.RuleX, maxQueueSize int) XQueue { return DefaultDataCacheQueue } func (q *DataCacheQueue) GetSize() int { - return cap(q.Queue) + return len(q.Queue) } /* @@ -73,8 +73,6 @@ func (q *DataCacheQueue) GetSize() int { * */ func (q *DataCacheQueue) Push(d QueueData) error { - // glogger.GLogger.Debug("DataCacheQueue Push:", d.Data) - // 比较数据和容积 if len(q.Queue)+1 > q.GetSize() { msg := fmt.Sprintf("attached max queue size, max size is:%v, current size is: %v", q.GetSize(), len(q.Queue)+1) glogger.GLogger.Error(msg) @@ -144,10 +142,10 @@ func StartDataCacheQueue() { func (q *DataCacheQueue) PushQueue(qd QueueData) error { err := DefaultDataCacheQueue.Push(qd) if err != nil { - glogger.GLogger.Error("PushQueue error:", err) - // q.rulex.MetricStatistics.IncInFailed() + glogger.GLogger.Error("PushInQueue error:", err) + intermetric.IncInFailed() } else { - // e.MetricStatistics.IncIn() + intermetric.IncIn() } return err } @@ -161,9 +159,9 @@ func (q *DataCacheQueue) PushInQueue(in *typex.InEnd, data string) error { err := DefaultDataCacheQueue.Push(qd) if err != nil { glogger.GLogger.Error("PushInQueue error:", err) - // e.MetricStatistics.IncInFailed() + intermetric.IncInFailed() } else { - // e.MetricStatistics.IncIn() + intermetric.IncIn() } return err } @@ -184,9 +182,9 @@ func (q *DataCacheQueue) PushDeviceQueue(Device *typex.Device, data string) erro err := DefaultDataCacheQueue.Push(qd) if err != nil { glogger.GLogger.Error("PushInQueue error:", err) - // q.rulex.MetricStatistics.IncInFailed() + intermetric.IncInFailed() } else { - // q.rulex.MetricStatistics.IncIn() + intermetric.IncIn() } return err } @@ -201,9 +199,9 @@ func (q *DataCacheQueue) PushOutQueue(out *typex.OutEnd, data string) error { err := DefaultDataCacheQueue.Push(qd) if err != nil { glogger.GLogger.Error("PushOutQueue error:", err) - // e.MetricStatistics.IncInFailed() + intermetric.IncInFailed() } else { - // e.MetricStatistics.IncIn() + intermetric.IncIn() } return err } diff --git a/conf/rulex.ini b/conf/rulex.ini index e34c5a047..e977b4855 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -26,7 +26,7 @@ app_debug_mode = false # debug # info # -log_level = all +log_level = info # # log path # From f4a2594cef6d1f15e932f74430e7d5eba55b5d1c Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 14:33:50 +0800 Subject: [PATCH 031/138] fix: fix tcp target --- component/datacenter/datacenter.go | 8 ++--- component/datacenter/datacenter_localdb.go | 4 +-- conf/rulex.ini | 4 +-- rulexlib/data_to_localdb_lib.go | 2 +- target/ttcp_target.go | 40 ++++++++++------------ test/conf/rulex.ini | 4 +-- typex/version.go | 2 +- 7 files changed, 31 insertions(+), 33 deletions(-) diff --git a/component/datacenter/datacenter.go b/component/datacenter/datacenter.go index 2a03c09f2..5702eedb0 100644 --- a/component/datacenter/datacenter.go +++ b/component/datacenter/datacenter.go @@ -54,7 +54,7 @@ func InitDataCenter(rulex typex.RuleX) { func SchemaList() []SchemaDetail { Schemas := []SchemaDetail{} // 本地内部数据中心 - Schemas = append(Schemas, __DefaultDataCenter.LocalDb.GetSchemaDetail("INTERNAL_DATACENTER")) + Schemas = append(Schemas, __DefaultDataCenter.LocalDb.GetSchemaDetail("RULEX_INTERNAL_DATACENTER")) // RPC的 trailer.AllGoods().Range(func(key, value any) bool { goodsPs := (value.(*trailer.GoodsProcess)) @@ -82,10 +82,10 @@ func SchemaList() []SchemaDetail { func GetSchemaDefine(goodsId string) (SchemaDefine, error) { schemaDefine := SchemaDefine{} // Rows 来自本地Sqlite查询 - if goodsId == "INTERNAL_DATACENTER" { + if goodsId == "RULEX_INTERNAL_DATACENTER" { return SchemaDefine{ // 本地是固定写法INTERNAL_DATACENTER - UUID: "INTERNAL_DATACENTER", + UUID: "RULEX_INTERNAL_DATACENTER", Columns: []Column{}, }, nil } @@ -193,7 +193,7 @@ func Query(goodsId, query string) ([]map[string]any, error) { // 本地 // Rows 来自本地Sqlite查询 - if goodsId == "INTERNAL_DATACENTER" { + if goodsId == "RULEX_INTERNAL_DATACENTER" { LocalResult, err := __DefaultDataCenter.LocalDb.Query(goodsId, query) return LocalResult, err } diff --git a/component/datacenter/datacenter_localdb.go b/component/datacenter/datacenter_localdb.go index a9bd0f0ce..e5ac7f0ef 100644 --- a/component/datacenter/datacenter_localdb.go +++ b/component/datacenter/datacenter_localdb.go @@ -44,8 +44,8 @@ func (ldb *LocalDb) Init() error { func (ldb *LocalDb) GetSchemaDetail(goodsId string) SchemaDetail { return SchemaDetail{ - UUID: "INTERNAL_DATACENTER", - SchemaType: "INTERNAL_DATACENTER", + UUID: "RULEX_INTERNAL_DATACENTER", + SchemaType: "RULEX_INTERNAL_DATACENTER", Name: "RULEX内置轻量级数据仓库", LocalPath: ".local", NetAddr: ".local", diff --git a/conf/rulex.ini b/conf/rulex.ini index e977b4855..478d7b001 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -197,8 +197,8 @@ enable = true # # Enable # -license_path = ./license.lic +license_path = ./conf/license.lic # # Enable # -key_path = ./license.key \ No newline at end of file +key_path = ./conf/license.key \ No newline at end of file diff --git a/rulexlib/data_to_localdb_lib.go b/rulexlib/data_to_localdb_lib.go index 4800a6f41..5cc4c4bf7 100644 --- a/rulexlib/data_to_localdb_lib.go +++ b/rulexlib/data_to_localdb_lib.go @@ -31,7 +31,7 @@ import ( func LocalDBQuery(rx typex.RuleX) func(*lua.LState) int { return func(l *lua.LState) int { sql := l.ToString(2) - Map, err := datacenter.Query("INTERNAL_DATACENTER", sql) + Map, err := datacenter.Query("RULEX_INTERNAL_DATACENTER", sql) if err != nil { l.Push(lua.LNil) l.Push(lua.LString(err.Error())) diff --git a/target/ttcp_target.go b/target/ttcp_target.go index c09ce2f81..9c9fcee4a 100644 --- a/target/ttcp_target.go +++ b/target/ttcp_target.go @@ -21,18 +21,20 @@ import ( "net" "time" + "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) +type __TcpCommonConfig struct { + DataMode string `json:"dataMode" validate:"required"` + AllowPing *bool `json:"allowPing" validate:"required"` + PingPacket string `json:"pingPacket" validate:"required"` +} type _TcpMainConfig struct { - DataMode string `json:"dataMode" validate:"required"` // RAW_STRING ; HEX_STRING - AllowPing *bool `json:"allowPing" validate:"required"` // 是否开启ping - PingPacket string `json:"pingPacket" validate:"required"` // Ping 包内容, 必填16字符以内 - Host string `json:"host" validate:"required" title:"服务地址"` - Port int `json:"port" validate:"required" title:"服务端口"` - Timeout int `json:"timeout,omitempty" title:"连接超时"` + CommonConfig __TcpCommonConfig `json:"commonConfig"` + HostConfig common.HostConfig `json:"hostConfig"` } type TTcpTarget struct { typex.XStatus @@ -50,15 +52,11 @@ func NewTTcpTarget(e typex.RuleX) typex.XTarget { ht := new(TTcpTarget) ht.RuleEngine = e ht.mainConfig = _TcpMainConfig{ - DataMode: "RAW_STRING", - AllowPing: func() *bool { + CommonConfig: __TcpCommonConfig{AllowPing: func() *bool { b := true return &b - }(), - PingPacket: "HR0001", // 默认每隔5秒发送PING包 - Host: "127.0.0.1", - Port: 2585, - Timeout: 3000, + }()}, + HostConfig: common.HostConfig{}, } ht.status = typex.SOURCE_DOWN return ht @@ -76,7 +74,7 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { ht.Ctx = cctx.Ctx ht.CancelCTX = cctx.CancelCTX var err error - host := fmt.Sprintf("%s:%d", ht.mainConfig.Host, ht.mainConfig.Port) + host := fmt.Sprintf("%s:%d", ht.mainConfig.HostConfig.Host, ht.mainConfig.HostConfig.Port) serverAddr, err := net.ResolveTCPAddr("tcp", host) if err != nil { return err @@ -88,7 +86,7 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { if err != nil { return err } - if *ht.mainConfig.AllowPing { + if *ht.mainConfig.CommonConfig.AllowPing { go func(ht *TTcpTarget) { for { select { @@ -101,10 +99,10 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { } } ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * time.Millisecond)), ) - _, err1 := ht.client.Write([]byte(ht.mainConfig.PingPacket)) + _, err1 := ht.client.Write([]byte(ht.mainConfig.CommonConfig.PingPacket)) ht.client.SetReadDeadline(time.Time{}) if err1 != nil { glogger.GLogger.Error("TTcpTarget Ping Error:", err1) @@ -133,9 +131,9 @@ func (ht *TTcpTarget) To(data interface{}) (interface{}, error) { if ht.client != nil { switch s := data.(type) { case string: - if ht.mainConfig.DataMode == "RAW_STRING" { + if ht.mainConfig.CommonConfig.DataMode == "RAW_STRING" { ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * time.Millisecond)), ) _, err0 := ht.client.Write([]byte(s)) @@ -144,13 +142,13 @@ func (ht *TTcpTarget) To(data interface{}) (interface{}, error) { return 0, err0 } } - if ht.mainConfig.DataMode == "HEX_STRING" { + if ht.mainConfig.CommonConfig.DataMode == "HEX_STRING" { dByte, err1 := hex.DecodeString(s) if err1 != nil { return 0, err1 } ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * time.Millisecond)), ) _, err0 := ht.client.Write(dByte) diff --git a/test/conf/rulex.ini b/test/conf/rulex.ini index 78b6b49f2..3a2c92a41 100644 --- a/test/conf/rulex.ini +++ b/test/conf/rulex.ini @@ -202,8 +202,8 @@ enable = true # # Enable # -license_path = ./license.lic +license_path = test/conf/license.lic # # Enable # -key_path = ./license.key \ No newline at end of file +key_path = test/conf/license.key \ No newline at end of file diff --git a/typex/version.go b/typex/version.go index 9aa7a3f75..99a2a7312 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-20 23:27:53", + ReleaseTime: "2023-11-21 14:22:58", } var Banner = ` ** Welcome to RULEX framework world <'_'> From aedda0f29ff83d335ef883bf5793081723ff44cd Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 16:38:40 +0800 Subject: [PATCH 032/138] dev: optimize tcp target --- conf/rulex.ini | 4 ++-- release_pkg.sh | 2 +- script/rulex-daemon.sh | 2 +- script/rulex-systemctl.sh | 10 +++++++--- target/ttcp_target.go | 39 +++++++++++++++++++-------------------- typex/version.go | 2 +- 6 files changed, 31 insertions(+), 28 deletions(-) diff --git a/conf/rulex.ini b/conf/rulex.ini index 478d7b001..e977b4855 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -197,8 +197,8 @@ enable = true # # Enable # -license_path = ./conf/license.lic +license_path = ./license.lic # # Enable # -key_path = ./conf/license.key \ No newline at end of file +key_path = ./license.key \ No newline at end of file diff --git a/release_pkg.sh b/release_pkg.sh index 1a319eb52..6433c1759 100755 --- a/release_pkg.sh +++ b/release_pkg.sh @@ -153,7 +153,7 @@ fetch_dashboard() { gen_changelog() { echo -e "[.]Version Change log:" - log=$(git log --oneline --pretty=format:" \033[0;31m[#]\033[0m%s\n" $(git describe --abbrev=0 --tags).. | cat) + log=$(git log --oneline --pretty=format:" \033[0;31m[*]\033[0m%s\n" $(git describe --abbrev=0 --tags).. | cat) echo -e $log } diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index 4c3559a4f..ae2149c2f 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -25,7 +25,7 @@ remove_files() { fi echo "[!] $1 files removed." else - echo "[#] $1 files not found. No need to remove." + echo "[*] $1 files not found. No need to remove." fi } diff --git a/script/rulex-systemctl.sh b/script/rulex-systemctl.sh index 99860c945..44c2e440e 100644 --- a/script/rulex-systemctl.sh +++ b/script/rulex-systemctl.sh @@ -43,10 +43,14 @@ RestartSec=5 WantedBy=multi-user.target EOL chmod +x $source_dir/rulex + echo "[.] Copy $source_dir/rulex to $working_directory." cp "$source_dir/rulex" "$executable" + echo "[.] Copy $source_dir/rulex.ini to $working_directory." cp "$source_dir/rulex.ini" "$config_file" - cp "$source_dir/license.key" /usr/local/ - cp "$source_dir/license.lic" /usr/local/ + echo "[.] Copy $source_dir/license.key to /usr/local/license.key." + cp "$source_dir/license.key" "/usr/local/license.key" + echo "[.] Copy $source_dir/license.lic to /usr/local/license.lic." + cp "$source_dir/license.lic" "/usr/local/license.lic" systemctl daemon-reload systemctl enable rulex systemctl start rulex @@ -85,7 +89,7 @@ remove_files() { fi echo "[!] $1 files removed." else - echo "[#] $1 files not found. No need to remove." + echo "[*] $1 files not found. No need to remove." fi } diff --git a/target/ttcp_target.go b/target/ttcp_target.go index 9c9fcee4a..6de8ef61d 100644 --- a/target/ttcp_target.go +++ b/target/ttcp_target.go @@ -21,20 +21,18 @@ import ( "net" "time" - "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) -type __TcpCommonConfig struct { - DataMode string `json:"dataMode" validate:"required"` - AllowPing *bool `json:"allowPing" validate:"required"` - PingPacket string `json:"pingPacket" validate:"required"` -} type _TcpMainConfig struct { - CommonConfig __TcpCommonConfig `json:"commonConfig"` - HostConfig common.HostConfig `json:"hostConfig"` + AllowPing *bool `json:"allowPing"` + DataMode string `json:"dataMode"` + Host string `json:"host"` + PingPacket string `json:"pingPacket"` + Port int `json:"port"` + Timeout int `json:"timeout"` } type TTcpTarget struct { typex.XStatus @@ -52,11 +50,10 @@ func NewTTcpTarget(e typex.RuleX) typex.XTarget { ht := new(TTcpTarget) ht.RuleEngine = e ht.mainConfig = _TcpMainConfig{ - CommonConfig: __TcpCommonConfig{AllowPing: func() *bool { + AllowPing: func() *bool { b := true return &b - }()}, - HostConfig: common.HostConfig{}, + }(), } ht.status = typex.SOURCE_DOWN return ht @@ -67,6 +64,7 @@ func (ht *TTcpTarget) Init(outEndId string, configMap map[string]interface{}) er if err := utils.BindSourceConfig(configMap, &ht.mainConfig); err != nil { return err } + ht.mainConfig.PingPacket += "\r\n" return nil } @@ -74,7 +72,7 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { ht.Ctx = cctx.Ctx ht.CancelCTX = cctx.CancelCTX var err error - host := fmt.Sprintf("%s:%d", ht.mainConfig.HostConfig.Host, ht.mainConfig.HostConfig.Port) + host := fmt.Sprintf("%s:%d", ht.mainConfig.Host, ht.mainConfig.Port) serverAddr, err := net.ResolveTCPAddr("tcp", host) if err != nil { return err @@ -86,7 +84,7 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { if err != nil { return err } - if *ht.mainConfig.CommonConfig.AllowPing { + if *ht.mainConfig.AllowPing { go func(ht *TTcpTarget) { for { select { @@ -99,10 +97,10 @@ func (ht *TTcpTarget) Start(cctx typex.CCTX) error { } } ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.Timeout) * time.Millisecond)), ) - _, err1 := ht.client.Write([]byte(ht.mainConfig.CommonConfig.PingPacket)) + _, err1 := ht.client.Write([]byte(ht.mainConfig.PingPacket)) ht.client.SetReadDeadline(time.Time{}) if err1 != nil { glogger.GLogger.Error("TTcpTarget Ping Error:", err1) @@ -131,26 +129,27 @@ func (ht *TTcpTarget) To(data interface{}) (interface{}, error) { if ht.client != nil { switch s := data.(type) { case string: - if ht.mainConfig.CommonConfig.DataMode == "RAW_STRING" { + if ht.mainConfig.DataMode == "RAW_STRING" { ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.Timeout) * time.Millisecond)), ) - _, err0 := ht.client.Write([]byte(s)) + _, err0 := ht.client.Write([]byte(s + "\r\n")) ht.client.SetReadDeadline(time.Time{}) if err0 != nil { return 0, err0 } } - if ht.mainConfig.CommonConfig.DataMode == "HEX_STRING" { + if ht.mainConfig.DataMode == "HEX_STRING" { dByte, err1 := hex.DecodeString(s) if err1 != nil { return 0, err1 } ht.client.SetReadDeadline( - time.Now().Add((time.Duration(ht.mainConfig.HostConfig.Timeout) * + time.Now().Add((time.Duration(ht.mainConfig.Timeout) * time.Millisecond)), ) + dByte = append(dByte, []byte{'\r', '\n'}...) _, err0 := ht.client.Write(dByte) ht.client.SetReadDeadline(time.Time{}) if err0 != nil { diff --git a/typex/version.go b/typex/version.go index 99a2a7312..8fd145763 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-21 14:22:58", + ReleaseTime: "2023-11-21 15:34:40", } var Banner = ` ** Welcome to RULEX framework world <'_'> From c27bd7d58e8f741ebd079b2814f70fee53deab5d Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 16:59:43 +0800 Subject: [PATCH 033/138] dev: fix xquque capcity --- component/interqueue/xqueue.go | 4 ++-- conf/rulex.ini | 4 ++-- test/conf/rulex.ini | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/component/interqueue/xqueue.go b/component/interqueue/xqueue.go index 27db3aa61..f940971ea 100644 --- a/component/interqueue/xqueue.go +++ b/component/interqueue/xqueue.go @@ -64,7 +64,7 @@ func InitDataCacheQueue(rulex typex.RuleX, maxQueueSize int) XQueue { return DefaultDataCacheQueue } func (q *DataCacheQueue) GetSize() int { - return len(q.Queue) + return cap(q.Queue) } /* @@ -73,7 +73,7 @@ func (q *DataCacheQueue) GetSize() int { * */ func (q *DataCacheQueue) Push(d QueueData) error { - if len(q.Queue)+1 > q.GetSize() { + if len(q.Queue)+1 > 52428800 { // 50Mb msg := fmt.Sprintf("attached max queue size, max size is:%v, current size is: %v", q.GetSize(), len(q.Queue)+1) glogger.GLogger.Error(msg) return errors.New(msg) diff --git a/conf/rulex.ini b/conf/rulex.ini index e977b4855..a5eb70b49 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -32,9 +32,9 @@ log_level = info # log_path = rulexlog # -# Max data cache size, default is 20MB +# Max data cache size, default is 50MB # -max_queue_size = 204800 +max_queue_size = 52428800 # # Max store size, default is 20MB # diff --git a/test/conf/rulex.ini b/test/conf/rulex.ini index 3a2c92a41..f3af4f3f3 100644 --- a/test/conf/rulex.ini +++ b/test/conf/rulex.ini @@ -36,9 +36,9 @@ log_path = rulex-log.txt # lua_log_path = rulex-lua-log.txt # -# Max data cache size, default is 20MB +# Max data cache size, default is 50MB # -max_queue_size = 204800 +max_queue_size = 52428800 # # Max store size, default is 20MB # From 8fc0a1a47733cfb5ce3afbc46f9fe9303b74d897 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 19:32:47 +0800 Subject: [PATCH 034/138] dev: enhance http target --- target/http_target.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target/http_target.go b/target/http_target.go index ad9e6070c..6259a8fb3 100644 --- a/target/http_target.go +++ b/target/http_target.go @@ -69,9 +69,10 @@ func (ht *HTTPTarget) To(data interface{}) (interface{}, error) { func (ht *HTTPTarget) Stop() { ht.status = typex.SOURCE_STOP - ht.CancelCTX() + if ht.CancelCTX != nil { + ht.CancelCTX() + } } func (ht *HTTPTarget) Details() *typex.OutEnd { return ht.RuleEngine.GetOutEnd(ht.PointId) } - From ce0dc4f73728a82328b09adeeba46cd8f2569279 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 19:45:23 +0800 Subject: [PATCH 035/138] dev: optimize Mem Percent --- .../http_server/service/memory_usage_linux.go | 62 +++++-------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/plugin/http_server/service/memory_usage_linux.go b/plugin/http_server/service/memory_usage_linux.go index 64d55ac59..3d29b666f 100644 --- a/plugin/http_server/service/memory_usage_linux.go +++ b/plugin/http_server/service/memory_usage_linux.go @@ -24,58 +24,28 @@ import ( "strings" ) -// GetMemPercent 获取Linux内存使用百分比 func GetMemPercent() (float64, error) { - // 打开 /proc/meminfo 文件 - file, err := os.Open("/proc/meminfo") + content, err := ioutil.ReadFile("/proc/meminfo") if err != nil { - return 0, fmt.Errorf("Open /proc/meminfo error: %v", err) + return 0.0, err } - defer file.Close() - // 初始化变量用于存储内存信息 - var totalMem, freeMem int64 + meminfo := string(content) - // 逐行读取文件内容 - scanner := bufio.NewScanner(file) - for scanner.Scan() { - line := scanner.Text() + var memTotal, memAvailable float64 + lines := strings.Split(meminfo, "\n") + for _, line := range lines { fields := strings.Fields(line) - if len(fields) == 3 { - // 提取字段名、值和单位 - fieldName := fields[0] - fieldValue := fields[1] - - // 将值转换为整数 - value, err := parseMemInfoValue(fieldValue) - if err != nil { - return 0, fmt.Errorf("parse MemInfo Value error: %v", err) - } - - // 根据字段名更新内存信息 - switch fieldName { - case "MemTotal:": - totalMem = value - case "MemFree:": - freeMem = value - } + if len(fields) < 2 { + continue + } + switch fields[0] { + case "MemTotal:": + fmt.Sscan(fields[1], &memTotal) + case "MemAvailable:": + fmt.Sscan(fields[1], &memAvailable) } } - - // 计算已使用内存 - usedMem := totalMem - freeMem - - // 计算内存使用百分比 - memUsagePercent := float64(usedMem) / float64(totalMem) * 100 - - return math.Round(memUsagePercent*100) / 100, nil -} - -// parseMemInfoValue 解析 /proc/meminfo 文件中的内存值(以 KB 为单位) -func parseMemInfoValue(valueStr string) (int64, error) { - value, err := strconv.ParseInt(valueStr, 10, 64) - if err != nil { - return 0, err - } - return value * 1024, nil + memPercent := 100.0 * (1.0 - memAvailable/memTotal) + return memPercent, nil } From 5405691acd2f265e78e761a33b425f3236da983e Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 20:26:48 +0800 Subject: [PATCH 036/138] fix: remove unused package --- plugin/http_server/service/memory_usage_linux.go | 5 +---- typex/version.go | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/plugin/http_server/service/memory_usage_linux.go b/plugin/http_server/service/memory_usage_linux.go index 3d29b666f..299e92aec 100644 --- a/plugin/http_server/service/memory_usage_linux.go +++ b/plugin/http_server/service/memory_usage_linux.go @@ -16,16 +16,13 @@ package service import ( - "bufio" "fmt" - "math" "os" - "strconv" "strings" ) func GetMemPercent() (float64, error) { - content, err := ioutil.ReadFile("/proc/meminfo") + content, err := os.ReadFile("/proc/meminfo") if err != nil { return 0.0, err } diff --git a/typex/version.go b/typex/version.go index 8fd145763..587ceea63 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-21 15:34:40", + ReleaseTime: "2023-11-21 20:26:31", } var Banner = ` ** Welcome to RULEX framework world <'_'> From e170ffeb7bf5fa4ec60d3e689ef0bc523d3795e1 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 20:44:50 +0800 Subject: [PATCH 037/138] dev: rename dir --- component/cron_task/cron_manager.go | 2 +- component/cron_task/process_manager.go | 5 +++-- engine/runner.go | 2 +- glogger/ws_logger.md | 4 ++-- plugin/http_server/server/www/index.html | 18 ---------------- .../apis/aibase_api.go | 2 +- .../apis/appstack_api.go | 6 +++--- .../apis/crontask_api.go | 7 +++--- .../apis/crontaskresult_api.go | 4 ++-- .../apis/datacenter_api.go | 2 +- .../apis/dataschema_api.go | 6 +++--- .../apis/device_api.go | 8 +++---- .../apis/group_api.go | 6 +++--- .../apis/hw_port_api.go | 6 +++--- .../apis/inend_api.go | 8 +++---- .../apis/outend_api.go | 8 +++---- .../apis/plugin_api.go | 2 +- .../apis/protocolapp_api.go | 0 .../apis/rhinoh3_firmware_api.go | 2 +- .../apis/rhinoh3_iproute_api.go | 6 +++--- .../apis/rhinopi_4g_api.go | 20 +++++++++--------- .../apis/rhinopi_wifi_api.go | 2 +- .../apis/rtsp_stream_api.go | 0 .../apis/rule_api.go | 8 +++---- .../apis/site_config_api.go | 6 +++--- .../apis/sysconfig_backup_api.go | 2 +- .../apis/system_api.go | 4 ++-- .../apis/system_config_api.go | 6 +++--- .../apis/system_firmware_api.go | 2 +- .../apis/system_settings_linux.go | 2 +- .../apis/system_settings_windows.go | 2 +- .../apis/trailer_api.go | 6 +++--- .../apis/user_api.go | 6 +++--- .../apis/vendor_security_api.go | 2 +- .../apis/visual_api.go | 6 +++--- .../common/response.go | 0 .../dto/crontask_dto.go | 0 .../dto/data_schema.go | 0 .../dto/etcnet_config.go | 0 .../dto/netplan_config.go | 0 .../http_api_server.go | 8 +++---- .../model/data_schema.go | 0 .../model/hw_interface.go | 0 .../model/iproute_config.go | 0 .../model/model.go | 0 .../model/site_config.go | 0 .../model/syslogo.go | 0 .../readme.md | 0 .../server/apiserver.go | 6 +++--- .../server/auth.go | 0 .../server/cros.go | 0 .../server/hello_api.go | 0 .../server/rate_limit.go | 0 .../server/res_loader.go | 2 +- .../server/res_supervisor.go | 0 .../server/staticfs.go | 0 .../service/crontask_service.go | 5 +++-- .../service/dao.go | 2 +- .../service/data_schema_service.go | 2 +- .../service/database_manage_service.go | 0 .../service/group_service.go | 2 +- .../service/hw_intrerface_service.go | 2 +- .../service/linux_network_config_service.go | 2 +- .../service/linux_wlan_config_service.go | 4 ++-- .../service/linuxamixer.md | 0 .../service/linuxnetcfg.md | 0 .../service/linuxtimecfg.md | 0 .../service/memory_usage_linux.go | 0 .../service/memory_usage_windows.go | 0 .../service/page_service.go | 5 +++-- .../rhinoh3_ubuntu18_iproute_service.go | 2 +- .../service/site_config_service.go | 2 +- .../service/visual_screen_service.go | 2 +- .../service/windows.md | 0 .../service/windows_eth_config.go | 0 .../structure.png | Bin test/appstack_httpapi_test.go | 2 +- test/binary_lua_test.go | 2 +- test/custom_tcp_server_test.go | 2 +- test/device_485ther_gw_test.go | 2 +- test/device_custom_protocol_device_test.go | 2 +- test/device_daccall_test.go | 2 +- test/device_g776dtu_test.go | 2 +- test/device_generic_ais_rxtx_device_test.go | 2 +- test/device_generic_camera_stream_test.go | 2 +- test/device_generic_modbus_device_test.go | 2 +- test/device_generic_opcua_device_test.go | 2 +- test/device_generic_snmp_device_test.go | 2 +- test/device_generic_uart_device_test.go | 2 +- test/device_gos7_plc_data_parse_test.go | 2 +- test/device_icmp_sender_test.go | 2 +- test/device_modbus_wite_with_app_test.go | 2 +- test/device_th_485_sensor_data_parse_test.go | 2 +- test/device_tss200_test.go | 2 +- test/device_yk8_with_rulex_test.go | 2 +- test/fully_test.go | 2 +- test/http_api_device_snmp_curd_test.go | 2 +- test/init_data_test.go | 6 +++--- test/jq_test.go | 2 +- test/modbus_parse_test.go | 2 +- test/rpc_codec_test.go | 2 +- test/rule_id_get_test.go | 2 +- test/rulex_snapshot_dump_test.go | 2 +- test/source_http_source_test.go | 2 +- test/suorce_txiothub_test.go | 2 +- test/target_data_to_mongodb_test.go | 2 +- test/target_data_tohttp_test.go | 4 ++-- test/target_data_toudp_test.go | 4 ++-- test/target_tdengine_test.go | 2 +- test/test_utils.go | 2 +- test/trailer_test.go | 2 +- typex/version.go | 2 +- 112 files changed, 145 insertions(+), 159 deletions(-) delete mode 100644 plugin/http_server/server/www/index.html rename plugin/{http_server => rulex_api_server}/apis/aibase_api.go (94%) rename plugin/{http_server => rulex_api_server}/apis/appstack_api.go (97%) rename plugin/{http_server => rulex_api_server}/apis/crontask_api.go (96%) rename plugin/{http_server => rulex_api_server}/apis/crontaskresult_api.go (90%) rename plugin/{http_server => rulex_api_server}/apis/datacenter_api.go (97%) rename plugin/{http_server => rulex_api_server}/apis/dataschema_api.go (95%) rename plugin/{http_server => rulex_api_server}/apis/device_api.go (97%) rename plugin/{http_server => rulex_api_server}/apis/group_api.go (96%) rename plugin/{http_server => rulex_api_server}/apis/hw_port_api.go (95%) rename plugin/{http_server => rulex_api_server}/apis/inend_api.go (95%) rename plugin/{http_server => rulex_api_server}/apis/outend_api.go (95%) rename plugin/{http_server => rulex_api_server}/apis/plugin_api.go (94%) rename plugin/{http_server => rulex_api_server}/apis/protocolapp_api.go (100%) rename plugin/{http_server => rulex_api_server}/apis/rhinoh3_firmware_api.go (96%) rename plugin/{http_server => rulex_api_server}/apis/rhinoh3_iproute_api.go (96%) rename plugin/{http_server => rulex_api_server}/apis/rhinopi_4g_api.go (92%) rename plugin/{http_server => rulex_api_server}/apis/rhinopi_wifi_api.go (94%) rename plugin/{http_server => rulex_api_server}/apis/rtsp_stream_api.go (100%) rename plugin/{http_server => rulex_api_server}/apis/rule_api.go (98%) rename plugin/{http_server => rulex_api_server}/apis/site_config_api.go (89%) rename plugin/{http_server => rulex_api_server}/apis/sysconfig_backup_api.go (96%) rename plugin/{http_server => rulex_api_server}/apis/system_api.go (98%) rename plugin/{http_server => rulex_api_server}/apis/system_config_api.go (98%) rename plugin/{http_server => rulex_api_server}/apis/system_firmware_api.go (98%) rename plugin/{http_server => rulex_api_server}/apis/system_settings_linux.go (98%) rename plugin/{http_server => rulex_api_server}/apis/system_settings_windows.go (92%) rename plugin/{http_server => rulex_api_server}/apis/trailer_api.go (98%) rename plugin/{http_server => rulex_api_server}/apis/user_api.go (97%) rename plugin/{http_server => rulex_api_server}/apis/vendor_security_api.go (95%) rename plugin/{http_server => rulex_api_server}/apis/visual_api.go (97%) rename plugin/{http_server => rulex_api_server}/common/response.go (100%) rename plugin/{http_server => rulex_api_server}/dto/crontask_dto.go (100%) rename plugin/{http_server => rulex_api_server}/dto/data_schema.go (100%) rename plugin/{http_server => rulex_api_server}/dto/etcnet_config.go (100%) rename plugin/{http_server => rulex_api_server}/dto/netplan_config.go (100%) rename plugin/{http_server => rulex_api_server}/http_api_server.go (98%) rename plugin/{http_server => rulex_api_server}/model/data_schema.go (100%) rename plugin/{http_server => rulex_api_server}/model/hw_interface.go (100%) rename plugin/{http_server => rulex_api_server}/model/iproute_config.go (100%) rename plugin/{http_server => rulex_api_server}/model/model.go (100%) rename plugin/{http_server => rulex_api_server}/model/site_config.go (100%) rename plugin/{http_server => rulex_api_server}/model/syslogo.go (100%) rename plugin/{http_server => rulex_api_server}/readme.md (100%) rename plugin/{http_server => rulex_api_server}/server/apiserver.go (96%) rename plugin/{http_server => rulex_api_server}/server/auth.go (100%) rename plugin/{http_server => rulex_api_server}/server/cros.go (100%) rename plugin/{http_server => rulex_api_server}/server/hello_api.go (100%) rename plugin/{http_server => rulex_api_server}/server/rate_limit.go (100%) rename plugin/{http_server => rulex_api_server}/server/res_loader.go (98%) rename plugin/{http_server => rulex_api_server}/server/res_supervisor.go (100%) rename plugin/{http_server => rulex_api_server}/server/staticfs.go (100%) rename plugin/{http_server => rulex_api_server}/service/crontask_service.go (94%) rename plugin/{http_server => rulex_api_server}/service/dao.go (99%) rename plugin/{http_server => rulex_api_server}/service/data_schema_service.go (96%) rename plugin/{http_server => rulex_api_server}/service/database_manage_service.go (100%) rename plugin/{http_server => rulex_api_server}/service/group_service.go (98%) rename plugin/{http_server => rulex_api_server}/service/hw_intrerface_service.go (98%) rename plugin/{http_server => rulex_api_server}/service/linux_network_config_service.go (98%) rename plugin/{http_server => rulex_api_server}/service/linux_wlan_config_service.go (96%) rename plugin/{http_server => rulex_api_server}/service/linuxamixer.md (100%) rename plugin/{http_server => rulex_api_server}/service/linuxnetcfg.md (100%) rename plugin/{http_server => rulex_api_server}/service/linuxtimecfg.md (100%) rename plugin/{http_server => rulex_api_server}/service/memory_usage_linux.go (100%) rename plugin/{http_server => rulex_api_server}/service/memory_usage_windows.go (100%) rename plugin/{http_server => rulex_api_server}/service/page_service.go (94%) rename plugin/{http_server => rulex_api_server}/service/rhinoh3_ubuntu18_iproute_service.go (98%) rename plugin/{http_server => rulex_api_server}/service/site_config_service.go (95%) rename plugin/{http_server => rulex_api_server}/service/visual_screen_service.go (94%) rename plugin/{http_server => rulex_api_server}/service/windows.md (100%) rename plugin/{http_server => rulex_api_server}/service/windows_eth_config.go (100%) rename plugin/{http_server => rulex_api_server}/structure.png (100%) diff --git a/component/cron_task/cron_manager.go b/component/cron_task/cron_manager.go index c10b4fa67..4fa653fcc 100644 --- a/component/cron_task/cron_manager.go +++ b/component/cron_task/cron_manager.go @@ -11,7 +11,7 @@ import ( "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "github.com/robfig/cron/v3" ) diff --git a/component/cron_task/process_manager.go b/component/cron_task/process_manager.go index b57534126..c70e5ebb2 100644 --- a/component/cron_task/process_manager.go +++ b/component/cron_task/process_manager.go @@ -4,11 +4,12 @@ import ( "encoding/base64" "encoding/json" "errors" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/http_server/model" "io" "os/exec" "sync" + + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) // ProcessManager diff --git a/engine/runner.go b/engine/runner.go index e3fd2d7f8..f106ea6ef 100644 --- a/engine/runner.go +++ b/engine/runner.go @@ -32,9 +32,9 @@ import ( "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" icmpsender "github.com/hootrhino/rulex/plugin/icmp_sender" license_manager "github.com/hootrhino/rulex/plugin/license_manager" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/glogger/ws_logger.md b/glogger/ws_logger.md index 6f5f9db0e..4675e2afa 100644 --- a/glogger/ws_logger.md +++ b/glogger/ws_logger.md @@ -63,7 +63,7 @@ $$ { "appId":"rulex", "file":"C:/Users/wangwenhai/workspace/rulex/plugin/http_server/rule_api.go:580", - "func":"github.com/hootrhino/rulex/plugin/http_server.TestSourceCallback", + "func":"github.com/hootrhino/rulex/plugin/rulex_api_server.TestSourceCallback", "level":"debug", "msg":"string", "time":"2023-06-30T17:52:31+08:00", @@ -75,7 +75,7 @@ $$ { "appId":"rulex", "file":"C:/Users/wangwenhai/workspace/rulex/plugin/http_server/rule_api.go:580", - "func":"github.com/hootrhino/rulex/plugin/http_server.TestSourceCallback", + "func":"github.com/hootrhino/rulex/plugin/rulex_api_server.TestSourceCallback", "level":"debug", "msg":"string", "time":"2023-06-30T17:52:31+08:00", diff --git a/plugin/http_server/server/www/index.html b/plugin/http_server/server/www/index.html deleted file mode 100644 index 8e6265367..000000000 --- a/plugin/http_server/server/www/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - Rulex - - - - - - Hello,Rulex. - - - \ No newline at end of file diff --git a/plugin/http_server/apis/aibase_api.go b/plugin/rulex_api_server/apis/aibase_api.go similarity index 94% rename from plugin/http_server/apis/aibase_api.go rename to plugin/rulex_api_server/apis/aibase_api.go index c41fd2537..181e27bff 100644 --- a/plugin/http_server/apis/aibase_api.go +++ b/plugin/rulex_api_server/apis/aibase_api.go @@ -3,7 +3,7 @@ package apis import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/aibase" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/appstack_api.go b/plugin/rulex_api_server/apis/appstack_api.go similarity index 97% rename from plugin/http_server/apis/appstack_api.go rename to plugin/rulex_api_server/apis/appstack_api.go index 90d95f2c9..6461d55fe 100644 --- a/plugin/http_server/apis/appstack_api.go +++ b/plugin/rulex_api_server/apis/appstack_api.go @@ -3,9 +3,9 @@ package apis import ( "fmt" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/appstack" diff --git a/plugin/http_server/apis/crontask_api.go b/plugin/rulex_api_server/apis/crontask_api.go similarity index 96% rename from plugin/http_server/apis/crontask_api.go rename to plugin/rulex_api_server/apis/crontask_api.go index 381e1bff7..8beee66fc 100644 --- a/plugin/http_server/apis/crontask_api.go +++ b/plugin/rulex_api_server/apis/crontask_api.go @@ -2,12 +2,13 @@ package apis import ( "errors" + "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/cron_task" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/dto" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + "github.com/hootrhino/rulex/plugin/rulex_api_server/dto" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/crontaskresult_api.go b/plugin/rulex_api_server/apis/crontaskresult_api.go similarity index 90% rename from plugin/http_server/apis/crontaskresult_api.go rename to plugin/rulex_api_server/apis/crontaskresult_api.go index c4df50157..1d443db41 100644 --- a/plugin/http_server/apis/crontaskresult_api.go +++ b/plugin/rulex_api_server/apis/crontaskresult_api.go @@ -3,8 +3,8 @@ package apis import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/datacenter_api.go b/plugin/rulex_api_server/apis/datacenter_api.go similarity index 97% rename from plugin/http_server/apis/datacenter_api.go rename to plugin/rulex_api_server/apis/datacenter_api.go index 07871b35e..49dde5498 100644 --- a/plugin/http_server/apis/datacenter_api.go +++ b/plugin/rulex_api_server/apis/datacenter_api.go @@ -18,7 +18,7 @@ package apis import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/datacenter" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/dataschema_api.go b/plugin/rulex_api_server/apis/dataschema_api.go similarity index 95% rename from plugin/http_server/apis/dataschema_api.go rename to plugin/rulex_api_server/apis/dataschema_api.go index 86b7b6ab1..000e4ca46 100644 --- a/plugin/http_server/apis/dataschema_api.go +++ b/plugin/rulex_api_server/apis/dataschema_api.go @@ -5,9 +5,9 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/core" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/http_server/apis/device_api.go b/plugin/rulex_api_server/apis/device_api.go similarity index 97% rename from plugin/http_server/apis/device_api.go rename to plugin/rulex_api_server/apis/device_api.go index 2509f3e52..6558eecd5 100644 --- a/plugin/http_server/apis/device_api.go +++ b/plugin/rulex_api_server/apis/device_api.go @@ -5,10 +5,10 @@ import ( "io" "strconv" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/server" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/server" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/xuri/excelize/v2" diff --git a/plugin/http_server/apis/group_api.go b/plugin/rulex_api_server/apis/group_api.go similarity index 96% rename from plugin/http_server/apis/group_api.go rename to plugin/rulex_api_server/apis/group_api.go index 69bf99301..e8a44d7e9 100644 --- a/plugin/http_server/apis/group_api.go +++ b/plugin/rulex_api_server/apis/group_api.go @@ -4,9 +4,9 @@ import ( "fmt" "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/http_server/apis/hw_port_api.go b/plugin/rulex_api_server/apis/hw_port_api.go similarity index 95% rename from plugin/http_server/apis/hw_port_api.go rename to plugin/rulex_api_server/apis/hw_port_api.go index c3d6ad960..6b6f29921 100644 --- a/plugin/http_server/apis/hw_port_api.go +++ b/plugin/rulex_api_server/apis/hw_port_api.go @@ -20,9 +20,9 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/hwportmanager" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/http_server/apis/inend_api.go b/plugin/rulex_api_server/apis/inend_api.go similarity index 95% rename from plugin/http_server/apis/inend_api.go rename to plugin/rulex_api_server/apis/inend_api.go index 55a403d53..72027c806 100644 --- a/plugin/http_server/apis/inend_api.go +++ b/plugin/rulex_api_server/apis/inend_api.go @@ -2,10 +2,10 @@ package apis import ( "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/server" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/server" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "gopkg.in/square/go-jose.v2/json" diff --git a/plugin/http_server/apis/outend_api.go b/plugin/rulex_api_server/apis/outend_api.go similarity index 95% rename from plugin/http_server/apis/outend_api.go rename to plugin/rulex_api_server/apis/outend_api.go index b98028894..4ec5a7a40 100644 --- a/plugin/http_server/apis/outend_api.go +++ b/plugin/rulex_api_server/apis/outend_api.go @@ -1,10 +1,10 @@ package apis import ( - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/server" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/server" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" diff --git a/plugin/http_server/apis/plugin_api.go b/plugin/rulex_api_server/apis/plugin_api.go similarity index 94% rename from plugin/http_server/apis/plugin_api.go rename to plugin/rulex_api_server/apis/plugin_api.go index 93a168552..0479a749c 100644 --- a/plugin/http_server/apis/plugin_api.go +++ b/plugin/rulex_api_server/apis/plugin_api.go @@ -3,7 +3,7 @@ package apis import ( "fmt" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" "github.com/gin-gonic/gin" diff --git a/plugin/http_server/apis/protocolapp_api.go b/plugin/rulex_api_server/apis/protocolapp_api.go similarity index 100% rename from plugin/http_server/apis/protocolapp_api.go rename to plugin/rulex_api_server/apis/protocolapp_api.go diff --git a/plugin/http_server/apis/rhinoh3_firmware_api.go b/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go similarity index 96% rename from plugin/http_server/apis/rhinoh3_firmware_api.go rename to plugin/rulex_api_server/apis/rhinoh3_firmware_api.go index c6cbee5b6..b592690a6 100644 --- a/plugin/http_server/apis/rhinoh3_firmware_api.go +++ b/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go @@ -21,7 +21,7 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/rhinoh3_iproute_api.go b/plugin/rulex_api_server/apis/rhinoh3_iproute_api.go similarity index 96% rename from plugin/http_server/apis/rhinoh3_iproute_api.go rename to plugin/rulex_api_server/apis/rhinoh3_iproute_api.go index 5937e68f2..fedcac6f6 100644 --- a/plugin/http_server/apis/rhinoh3_iproute_api.go +++ b/plugin/rulex_api_server/apis/rhinoh3_iproute_api.go @@ -20,9 +20,9 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/http_server/apis/rhinopi_4g_api.go b/plugin/rulex_api_server/apis/rhinopi_4g_api.go similarity index 92% rename from plugin/http_server/apis/rhinopi_4g_api.go rename to plugin/rulex_api_server/apis/rhinopi_4g_api.go index e59db5d2d..233eab3ca 100644 --- a/plugin/http_server/apis/rhinopi_4g_api.go +++ b/plugin/rulex_api_server/apis/rhinopi_4g_api.go @@ -20,7 +20,7 @@ import ( "github.com/gin-gonic/gin" archsupport "github.com/hootrhino/rulex/bspsupport" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) @@ -120,11 +120,11 @@ func Get4GCOPS(c *gin.Context, ruleEngine typex.RuleX) { */ // ptype int, apn, username, password string, auth, cdmaPwd int type APNFormVo struct { - SenceId int `json:"senceId"` - PTytpe int `json:"ptytpe"` - Auth int `json:"auth"` - CDMAPWD int `json:"cdmapwd"` - APN string `json:"apn"` + SenceId int `json:"senceId"` + PTytpe int `json:"ptytpe"` + Auth int `json:"auth"` + CDMAPWD int `json:"cdmapwd"` + APN string `json:"apn"` Username string `json:"apn_username"` Password string `json:"apn_password"` } @@ -169,10 +169,10 @@ func Get4GICCID(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) } else { // +QCCID: 89860426102180397625 - len1:=len("+QCCID: ") - iccid:="" - if len(result)>len1 { - iccid=result[len1:] + len1 := len("+QCCID: ") + iccid := "" + if len(result) > len1 { + iccid = result[len1:] } c.JSON(common.HTTP_OK, common.OkWithData(iccid)) } diff --git a/plugin/http_server/apis/rhinopi_wifi_api.go b/plugin/rulex_api_server/apis/rhinopi_wifi_api.go similarity index 94% rename from plugin/http_server/apis/rhinopi_wifi_api.go rename to plugin/rulex_api_server/apis/rhinopi_wifi_api.go index 9fe6185bf..99a03eb78 100644 --- a/plugin/http_server/apis/rhinopi_wifi_api.go +++ b/plugin/rulex_api_server/apis/rhinopi_wifi_api.go @@ -18,7 +18,7 @@ package apis import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/rtsp_stream_api.go b/plugin/rulex_api_server/apis/rtsp_stream_api.go similarity index 100% rename from plugin/http_server/apis/rtsp_stream_api.go rename to plugin/rulex_api_server/apis/rtsp_stream_api.go diff --git a/plugin/http_server/apis/rule_api.go b/plugin/rulex_api_server/apis/rule_api.go similarity index 98% rename from plugin/http_server/apis/rule_api.go rename to plugin/rulex_api_server/apis/rule_api.go index 843c33455..429a55718 100644 --- a/plugin/http_server/apis/rule_api.go +++ b/plugin/rulex_api_server/apis/rule_api.go @@ -5,10 +5,10 @@ import ( "github.com/hootrhino/rulex/component/interqueue" "github.com/hootrhino/rulex/glogger" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/server" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/server" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/sirupsen/logrus" "github.com/hootrhino/rulex/core" diff --git a/plugin/http_server/apis/site_config_api.go b/plugin/rulex_api_server/apis/site_config_api.go similarity index 89% rename from plugin/http_server/apis/site_config_api.go rename to plugin/rulex_api_server/apis/site_config_api.go index 54c2a8bf7..fc55d5f1c 100644 --- a/plugin/http_server/apis/site_config_api.go +++ b/plugin/rulex_api_server/apis/site_config_api.go @@ -17,9 +17,9 @@ package apis import ( "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/sysconfig_backup_api.go b/plugin/rulex_api_server/apis/sysconfig_backup_api.go similarity index 96% rename from plugin/http_server/apis/sysconfig_backup_api.go rename to plugin/rulex_api_server/apis/sysconfig_backup_api.go index 3c6b86971..1b4cccae9 100644 --- a/plugin/http_server/apis/sysconfig_backup_api.go +++ b/plugin/rulex_api_server/apis/sysconfig_backup_api.go @@ -10,7 +10,7 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/system_api.go b/plugin/rulex_api_server/apis/system_api.go similarity index 98% rename from plugin/http_server/apis/system_api.go rename to plugin/rulex_api_server/apis/system_api.go index b6d426d82..732e53d6b 100644 --- a/plugin/http_server/apis/system_api.go +++ b/plugin/rulex_api_server/apis/system_api.go @@ -13,8 +13,8 @@ import ( "github.com/hootrhino/rulex/component/intermetric" "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/utils" "github.com/hootrhino/rulex/device" diff --git a/plugin/http_server/apis/system_config_api.go b/plugin/rulex_api_server/apis/system_config_api.go similarity index 98% rename from plugin/http_server/apis/system_config_api.go rename to plugin/rulex_api_server/apis/system_config_api.go index f749385c7..dca7bf3c9 100644 --- a/plugin/http_server/apis/system_config_api.go +++ b/plugin/rulex_api_server/apis/system_config_api.go @@ -13,9 +13,9 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/http_server/apis/system_firmware_api.go b/plugin/rulex_api_server/apis/system_firmware_api.go similarity index 98% rename from plugin/http_server/apis/system_firmware_api.go rename to plugin/rulex_api_server/apis/system_firmware_api.go index a22c6087d..3c7b53d4f 100644 --- a/plugin/http_server/apis/system_firmware_api.go +++ b/plugin/rulex_api_server/apis/system_firmware_api.go @@ -27,7 +27,7 @@ import ( "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/http_server/apis/system_settings_linux.go b/plugin/rulex_api_server/apis/system_settings_linux.go similarity index 98% rename from plugin/http_server/apis/system_settings_linux.go rename to plugin/rulex_api_server/apis/system_settings_linux.go index ed12f128b..f184be065 100644 --- a/plugin/http_server/apis/system_settings_linux.go +++ b/plugin/rulex_api_server/apis/system_settings_linux.go @@ -1,6 +1,6 @@ package apis -import "github.com/hootrhino/rulex/plugin/http_server/server" +import "github.com/hootrhino/rulex/plugin/rulex_api_server/server" // Copyright (C) 2023 wwhai // diff --git a/plugin/http_server/apis/system_settings_windows.go b/plugin/rulex_api_server/apis/system_settings_windows.go similarity index 92% rename from plugin/http_server/apis/system_settings_windows.go rename to plugin/rulex_api_server/apis/system_settings_windows.go index 6a17778ea..6652165f1 100644 --- a/plugin/http_server/apis/system_settings_windows.go +++ b/plugin/rulex_api_server/apis/system_settings_windows.go @@ -1,6 +1,6 @@ package apis -import "github.com/hootrhino/rulex/plugin/http_server/server" +import "github.com/hootrhino/rulex/plugin/rulex_api_server/server" // Copyright (C) 2023 wwhai // diff --git a/plugin/http_server/apis/trailer_api.go b/plugin/rulex_api_server/apis/trailer_api.go similarity index 98% rename from plugin/http_server/apis/trailer_api.go rename to plugin/rulex_api_server/apis/trailer_api.go index dbf547cdc..8dba8e160 100644 --- a/plugin/http_server/apis/trailer_api.go +++ b/plugin/rulex_api_server/apis/trailer_api.go @@ -12,9 +12,9 @@ import ( "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/glogger" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "google.golang.org/grpc" diff --git a/plugin/http_server/apis/user_api.go b/plugin/rulex_api_server/apis/user_api.go similarity index 97% rename from plugin/http_server/apis/user_api.go rename to plugin/rulex_api_server/apis/user_api.go index 7c396f76b..a40130ea4 100644 --- a/plugin/http_server/apis/user_api.go +++ b/plugin/rulex_api_server/apis/user_api.go @@ -12,9 +12,9 @@ import ( "time" "unicode/utf8" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/dgrijalva/jwt-go" diff --git a/plugin/http_server/apis/vendor_security_api.go b/plugin/rulex_api_server/apis/vendor_security_api.go similarity index 95% rename from plugin/http_server/apis/vendor_security_api.go rename to plugin/rulex_api_server/apis/vendor_security_api.go index 01478d8fe..606e3cef5 100644 --- a/plugin/http_server/apis/vendor_security_api.go +++ b/plugin/rulex_api_server/apis/vendor_security_api.go @@ -21,7 +21,7 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/core" - common "github.com/hootrhino/rulex/plugin/http_server/common" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" "gopkg.in/ini.v1" ) diff --git a/plugin/http_server/apis/visual_api.go b/plugin/rulex_api_server/apis/visual_api.go similarity index 97% rename from plugin/http_server/apis/visual_api.go rename to plugin/rulex_api_server/apis/visual_api.go index 316872c2e..e6bf6a142 100644 --- a/plugin/http_server/apis/visual_api.go +++ b/plugin/rulex_api_server/apis/visual_api.go @@ -9,9 +9,9 @@ import ( "time" "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/http_server/common/response.go b/plugin/rulex_api_server/common/response.go similarity index 100% rename from plugin/http_server/common/response.go rename to plugin/rulex_api_server/common/response.go diff --git a/plugin/http_server/dto/crontask_dto.go b/plugin/rulex_api_server/dto/crontask_dto.go similarity index 100% rename from plugin/http_server/dto/crontask_dto.go rename to plugin/rulex_api_server/dto/crontask_dto.go diff --git a/plugin/http_server/dto/data_schema.go b/plugin/rulex_api_server/dto/data_schema.go similarity index 100% rename from plugin/http_server/dto/data_schema.go rename to plugin/rulex_api_server/dto/data_schema.go diff --git a/plugin/http_server/dto/etcnet_config.go b/plugin/rulex_api_server/dto/etcnet_config.go similarity index 100% rename from plugin/http_server/dto/etcnet_config.go rename to plugin/rulex_api_server/dto/etcnet_config.go diff --git a/plugin/http_server/dto/netplan_config.go b/plugin/rulex_api_server/dto/netplan_config.go similarity index 100% rename from plugin/http_server/dto/netplan_config.go rename to plugin/rulex_api_server/dto/netplan_config.go diff --git a/plugin/http_server/http_api_server.go b/plugin/rulex_api_server/http_api_server.go similarity index 98% rename from plugin/http_server/http_api_server.go rename to plugin/rulex_api_server/http_api_server.go index fbedf58e4..b6d1d7ff5 100644 --- a/plugin/http_server/http_api_server.go +++ b/plugin/rulex_api_server/http_api_server.go @@ -10,10 +10,10 @@ import ( "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/core" - "github.com/hootrhino/rulex/plugin/http_server/apis" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/server" - "github.com/hootrhino/rulex/plugin/http_server/service" + "github.com/hootrhino/rulex/plugin/rulex_api_server/apis" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/server" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" diff --git a/plugin/http_server/model/data_schema.go b/plugin/rulex_api_server/model/data_schema.go similarity index 100% rename from plugin/http_server/model/data_schema.go rename to plugin/rulex_api_server/model/data_schema.go diff --git a/plugin/http_server/model/hw_interface.go b/plugin/rulex_api_server/model/hw_interface.go similarity index 100% rename from plugin/http_server/model/hw_interface.go rename to plugin/rulex_api_server/model/hw_interface.go diff --git a/plugin/http_server/model/iproute_config.go b/plugin/rulex_api_server/model/iproute_config.go similarity index 100% rename from plugin/http_server/model/iproute_config.go rename to plugin/rulex_api_server/model/iproute_config.go diff --git a/plugin/http_server/model/model.go b/plugin/rulex_api_server/model/model.go similarity index 100% rename from plugin/http_server/model/model.go rename to plugin/rulex_api_server/model/model.go diff --git a/plugin/http_server/model/site_config.go b/plugin/rulex_api_server/model/site_config.go similarity index 100% rename from plugin/http_server/model/site_config.go rename to plugin/rulex_api_server/model/site_config.go diff --git a/plugin/http_server/model/syslogo.go b/plugin/rulex_api_server/model/syslogo.go similarity index 100% rename from plugin/http_server/model/syslogo.go rename to plugin/rulex_api_server/model/syslogo.go diff --git a/plugin/http_server/readme.md b/plugin/rulex_api_server/readme.md similarity index 100% rename from plugin/http_server/readme.md rename to plugin/rulex_api_server/readme.md diff --git a/plugin/http_server/server/apiserver.go b/plugin/rulex_api_server/server/apiserver.go similarity index 96% rename from plugin/http_server/server/apiserver.go rename to plugin/rulex_api_server/server/apiserver.go index 46c9bfdbe..7dda03cca 100644 --- a/plugin/http_server/server/apiserver.go +++ b/plugin/rulex_api_server/server/apiserver.go @@ -14,9 +14,9 @@ import ( "github.com/hootrhino/rulex/device" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/ossupport" - response "github.com/hootrhino/rulex/plugin/http_server/common" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + response "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/source" "github.com/hootrhino/rulex/target" "github.com/hootrhino/rulex/typex" diff --git a/plugin/http_server/server/auth.go b/plugin/rulex_api_server/server/auth.go similarity index 100% rename from plugin/http_server/server/auth.go rename to plugin/rulex_api_server/server/auth.go diff --git a/plugin/http_server/server/cros.go b/plugin/rulex_api_server/server/cros.go similarity index 100% rename from plugin/http_server/server/cros.go rename to plugin/rulex_api_server/server/cros.go diff --git a/plugin/http_server/server/hello_api.go b/plugin/rulex_api_server/server/hello_api.go similarity index 100% rename from plugin/http_server/server/hello_api.go rename to plugin/rulex_api_server/server/hello_api.go diff --git a/plugin/http_server/server/rate_limit.go b/plugin/rulex_api_server/server/rate_limit.go similarity index 100% rename from plugin/http_server/server/rate_limit.go rename to plugin/rulex_api_server/server/rate_limit.go diff --git a/plugin/http_server/server/res_loader.go b/plugin/rulex_api_server/server/res_loader.go similarity index 98% rename from plugin/http_server/server/res_loader.go rename to plugin/rulex_api_server/server/res_loader.go index 5609ac52e..6c75b9e40 100644 --- a/plugin/http_server/server/res_loader.go +++ b/plugin/rulex_api_server/server/res_loader.go @@ -4,7 +4,7 @@ import ( "errors" "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/http_server/service" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "gopkg.in/square/go-jose.v2/json" ) diff --git a/plugin/http_server/server/res_supervisor.go b/plugin/rulex_api_server/server/res_supervisor.go similarity index 100% rename from plugin/http_server/server/res_supervisor.go rename to plugin/rulex_api_server/server/res_supervisor.go diff --git a/plugin/http_server/server/staticfs.go b/plugin/rulex_api_server/server/staticfs.go similarity index 100% rename from plugin/http_server/server/staticfs.go rename to plugin/rulex_api_server/server/staticfs.go diff --git a/plugin/http_server/service/crontask_service.go b/plugin/rulex_api_server/service/crontask_service.go similarity index 94% rename from plugin/http_server/service/crontask_service.go rename to plugin/rulex_api_server/service/crontask_service.go index f221ab06c..2cf263b10 100644 --- a/plugin/http_server/service/crontask_service.go +++ b/plugin/rulex_api_server/service/crontask_service.go @@ -3,10 +3,11 @@ package service import ( "encoding/json" "errors" + "github.com/hootrhino/rulex/component/cron_task" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/dto" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/dto" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/http_server/service/dao.go b/plugin/rulex_api_server/service/dao.go similarity index 99% rename from plugin/http_server/service/dao.go rename to plugin/rulex_api_server/service/dao.go index 6408fe0c3..bd74bb8c4 100644 --- a/plugin/http_server/service/dao.go +++ b/plugin/rulex_api_server/service/dao.go @@ -2,7 +2,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "gorm.io/gorm" ) diff --git a/plugin/http_server/service/data_schema_service.go b/plugin/rulex_api_server/service/data_schema_service.go similarity index 96% rename from plugin/http_server/service/data_schema_service.go rename to plugin/rulex_api_server/service/data_schema_service.go index 0b6bd0283..1cd3d956f 100644 --- a/plugin/http_server/service/data_schema_service.go +++ b/plugin/rulex_api_server/service/data_schema_service.go @@ -17,7 +17,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) // 获取DataSchema列表 diff --git a/plugin/http_server/service/database_manage_service.go b/plugin/rulex_api_server/service/database_manage_service.go similarity index 100% rename from plugin/http_server/service/database_manage_service.go rename to plugin/rulex_api_server/service/database_manage_service.go diff --git a/plugin/http_server/service/group_service.go b/plugin/rulex_api_server/service/group_service.go similarity index 98% rename from plugin/http_server/service/group_service.go rename to plugin/rulex_api_server/service/group_service.go index 2ba743f9c..a14ef3a6c 100644 --- a/plugin/http_server/service/group_service.go +++ b/plugin/rulex_api_server/service/group_service.go @@ -17,7 +17,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) // 获取GenericGroup列表 diff --git a/plugin/http_server/service/hw_intrerface_service.go b/plugin/rulex_api_server/service/hw_intrerface_service.go similarity index 98% rename from plugin/http_server/service/hw_intrerface_service.go rename to plugin/rulex_api_server/service/hw_intrerface_service.go index dc58dc908..2e1f2336d 100644 --- a/plugin/http_server/service/hw_intrerface_service.go +++ b/plugin/rulex_api_server/service/hw_intrerface_service.go @@ -21,7 +21,7 @@ import ( "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/ossupport" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "go.bug.st/serial" ) diff --git a/plugin/http_server/service/linux_network_config_service.go b/plugin/rulex_api_server/service/linux_network_config_service.go similarity index 98% rename from plugin/http_server/service/linux_network_config_service.go rename to plugin/rulex_api_server/service/linux_network_config_service.go index 6327702cc..b3f470540 100644 --- a/plugin/http_server/service/linux_network_config_service.go +++ b/plugin/rulex_api_server/service/linux_network_config_service.go @@ -6,7 +6,7 @@ import ( "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) /* diff --git a/plugin/http_server/service/linux_wlan_config_service.go b/plugin/rulex_api_server/service/linux_wlan_config_service.go similarity index 96% rename from plugin/http_server/service/linux_wlan_config_service.go rename to plugin/rulex_api_server/service/linux_wlan_config_service.go index 7df67de8e..085ad01e2 100644 --- a/plugin/http_server/service/linux_wlan_config_service.go +++ b/plugin/rulex_api_server/service/linux_wlan_config_service.go @@ -1,9 +1,9 @@ package service import ( - "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) /* diff --git a/plugin/http_server/service/linuxamixer.md b/plugin/rulex_api_server/service/linuxamixer.md similarity index 100% rename from plugin/http_server/service/linuxamixer.md rename to plugin/rulex_api_server/service/linuxamixer.md diff --git a/plugin/http_server/service/linuxnetcfg.md b/plugin/rulex_api_server/service/linuxnetcfg.md similarity index 100% rename from plugin/http_server/service/linuxnetcfg.md rename to plugin/rulex_api_server/service/linuxnetcfg.md diff --git a/plugin/http_server/service/linuxtimecfg.md b/plugin/rulex_api_server/service/linuxtimecfg.md similarity index 100% rename from plugin/http_server/service/linuxtimecfg.md rename to plugin/rulex_api_server/service/linuxtimecfg.md diff --git a/plugin/http_server/service/memory_usage_linux.go b/plugin/rulex_api_server/service/memory_usage_linux.go similarity index 100% rename from plugin/http_server/service/memory_usage_linux.go rename to plugin/rulex_api_server/service/memory_usage_linux.go diff --git a/plugin/http_server/service/memory_usage_windows.go b/plugin/rulex_api_server/service/memory_usage_windows.go similarity index 100% rename from plugin/http_server/service/memory_usage_windows.go rename to plugin/rulex_api_server/service/memory_usage_windows.go diff --git a/plugin/http_server/service/page_service.go b/plugin/rulex_api_server/service/page_service.go similarity index 94% rename from plugin/http_server/service/page_service.go rename to plugin/rulex_api_server/service/page_service.go index 28fc93247..4ef7993db 100644 --- a/plugin/http_server/service/page_service.go +++ b/plugin/rulex_api_server/service/page_service.go @@ -1,10 +1,11 @@ package service import ( + "strconv" + "github.com/gin-gonic/gin" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "gorm.io/gorm" - "strconv" ) func Paginate(page model.PageRequest) func(db *gorm.DB) *gorm.DB { diff --git a/plugin/http_server/service/rhinoh3_ubuntu18_iproute_service.go b/plugin/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go similarity index 98% rename from plugin/http_server/service/rhinoh3_ubuntu18_iproute_service.go rename to plugin/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go index 650154693..2416e3615 100644 --- a/plugin/http_server/service/rhinoh3_ubuntu18_iproute_service.go +++ b/plugin/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go @@ -21,7 +21,7 @@ import ( "strings" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) /* diff --git a/plugin/http_server/service/site_config_service.go b/plugin/rulex_api_server/service/site_config_service.go similarity index 95% rename from plugin/http_server/service/site_config_service.go rename to plugin/rulex_api_server/service/site_config_service.go index 089df46db..a6fd88978 100644 --- a/plugin/http_server/service/site_config_service.go +++ b/plugin/rulex_api_server/service/site_config_service.go @@ -17,7 +17,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) func GetSiteConfig() (model.MSiteConfig, error) { diff --git a/plugin/http_server/service/visual_screen_service.go b/plugin/rulex_api_server/service/visual_screen_service.go similarity index 94% rename from plugin/http_server/service/visual_screen_service.go rename to plugin/rulex_api_server/service/visual_screen_service.go index 93a0a3e5b..a0e994fb0 100644 --- a/plugin/http_server/service/visual_screen_service.go +++ b/plugin/rulex_api_server/service/visual_screen_service.go @@ -2,7 +2,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) // 获取Visual列表 diff --git a/plugin/http_server/service/windows.md b/plugin/rulex_api_server/service/windows.md similarity index 100% rename from plugin/http_server/service/windows.md rename to plugin/rulex_api_server/service/windows.md diff --git a/plugin/http_server/service/windows_eth_config.go b/plugin/rulex_api_server/service/windows_eth_config.go similarity index 100% rename from plugin/http_server/service/windows_eth_config.go rename to plugin/rulex_api_server/service/windows_eth_config.go diff --git a/plugin/http_server/structure.png b/plugin/rulex_api_server/structure.png similarity index 100% rename from plugin/http_server/structure.png rename to plugin/rulex_api_server/structure.png diff --git a/test/appstack_httpapi_test.go b/test/appstack_httpapi_test.go index bdecb1785..94f5fbee8 100644 --- a/test/appstack_httpapi_test.go +++ b/test/appstack_httpapi_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/go-playground/assert/v2" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) /* diff --git a/test/binary_lua_test.go b/test/binary_lua_test.go index 223e1d9e0..26648bba2 100644 --- a/test/binary_lua_test.go +++ b/test/binary_lua_test.go @@ -10,7 +10,7 @@ import ( "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/plugin/demo_plugin" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/custom_tcp_server_test.go b/test/custom_tcp_server_test.go index 86dd7f79b..94ce31e91 100644 --- a/test/custom_tcp_server_test.go +++ b/test/custom_tcp_server_test.go @@ -7,7 +7,7 @@ import ( "time" "github.com/hootrhino/rulex/component/appstack" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/test/device_485ther_gw_test.go b/test/device_485ther_gw_test.go index 07ba6dddf..660a0896b 100644 --- a/test/device_485ther_gw_test.go +++ b/test/device_485ther_gw_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" diff --git a/test/device_custom_protocol_device_test.go b/test/device_custom_protocol_device_test.go index 9d985e195..f2f71cbcb 100644 --- a/test/device_custom_protocol_device_test.go +++ b/test/device_custom_protocol_device_test.go @@ -10,7 +10,7 @@ import ( serial "github.com/wwhai/tarmserial" "github.com/hootrhino/rulex/component/rulexrpc" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "google.golang.org/grpc" diff --git a/test/device_daccall_test.go b/test/device_daccall_test.go index fbf97bca8..c159201a7 100644 --- a/test/device_daccall_test.go +++ b/test/device_daccall_test.go @@ -5,8 +5,8 @@ import ( "time" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" mqttserver "github.com/hootrhino/rulex/plugin/mqtt_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/test/device_g776dtu_test.go b/test/device_g776dtu_test.go index 5dec70c89..61faac9ca 100644 --- a/test/device_g776dtu_test.go +++ b/test/device_g776dtu_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/test/device_generic_ais_rxtx_device_test.go b/test/device_generic_ais_rxtx_device_test.go index ea1e73d8c..78bdee473 100644 --- a/test/device_generic_ais_rxtx_device_test.go +++ b/test/device_generic_ais_rxtx_device_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/adrianmo/go-nmea" "github.com/hootrhino/rulex/typex" diff --git a/test/device_generic_camera_stream_test.go b/test/device_generic_camera_stream_test.go index 42da1a584..178a6128c 100644 --- a/test/device_generic_camera_stream_test.go +++ b/test/device_generic_camera_stream_test.go @@ -2,7 +2,7 @@ package test import ( "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" "time" diff --git a/test/device_generic_modbus_device_test.go b/test/device_generic_modbus_device_test.go index ead7af0d5..53431c25d 100644 --- a/test/device_generic_modbus_device_test.go +++ b/test/device_generic_modbus_device_test.go @@ -4,7 +4,7 @@ import ( "context" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" mbserver "github.com/tbrandon/mbserver" "testing" diff --git a/test/device_generic_opcua_device_test.go b/test/device_generic_opcua_device_test.go index 63cc145ca..45b310bc7 100644 --- a/test/device_generic_opcua_device_test.go +++ b/test/device_generic_opcua_device_test.go @@ -6,7 +6,7 @@ import ( "github.com/hootrhino/rulex/device" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/test/device_generic_snmp_device_test.go b/test/device_generic_snmp_device_test.go index 7eb3f0987..7b22ced18 100644 --- a/test/device_generic_snmp_device_test.go +++ b/test/device_generic_snmp_device_test.go @@ -2,7 +2,7 @@ package test import ( "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" "time" diff --git a/test/device_generic_uart_device_test.go b/test/device_generic_uart_device_test.go index ecf75bb6e..bfd65a4fa 100644 --- a/test/device_generic_uart_device_test.go +++ b/test/device_generic_uart_device_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" diff --git a/test/device_gos7_plc_data_parse_test.go b/test/device_gos7_plc_data_parse_test.go index aa8200032..e6ae39077 100644 --- a/test/device_gos7_plc_data_parse_test.go +++ b/test/device_gos7_plc_data_parse_test.go @@ -7,7 +7,7 @@ import ( "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/device_icmp_sender_test.go b/test/device_icmp_sender_test.go index bc0b9d1f6..46a0142a9 100644 --- a/test/device_icmp_sender_test.go +++ b/test/device_icmp_sender_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" diff --git a/test/device_modbus_wite_with_app_test.go b/test/device_modbus_wite_with_app_test.go index 325e389dc..46a3a5a41 100644 --- a/test/device_modbus_wite_with_app_test.go +++ b/test/device_modbus_wite_with_app_test.go @@ -5,7 +5,7 @@ import ( "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/component/appstack" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" diff --git a/test/device_th_485_sensor_data_parse_test.go b/test/device_th_485_sensor_data_parse_test.go index 96f240c58..e0cae2fff 100644 --- a/test/device_th_485_sensor_data_parse_test.go +++ b/test/device_th_485_sensor_data_parse_test.go @@ -7,7 +7,7 @@ import ( "time" "github.com/hootrhino/rulex/component/rulexrpc" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/device_tss200_test.go b/test/device_tss200_test.go index 148bdbe48..3062b1505 100644 --- a/test/device_tss200_test.go +++ b/test/device_tss200_test.go @@ -2,7 +2,7 @@ package test import ( "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" "time" diff --git a/test/device_yk8_with_rulex_test.go b/test/device_yk8_with_rulex_test.go index da20ede05..ebb6d431b 100644 --- a/test/device_yk8_with_rulex_test.go +++ b/test/device_yk8_with_rulex_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" diff --git a/test/fully_test.go b/test/fully_test.go index 1e6752781..96aac572a 100644 --- a/test/fully_test.go +++ b/test/fully_test.go @@ -5,7 +5,7 @@ import ( "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "testing" diff --git a/test/http_api_device_snmp_curd_test.go b/test/http_api_device_snmp_curd_test.go index 2c468ce07..29c1adea6 100644 --- a/test/http_api_device_snmp_curd_test.go +++ b/test/http_api_device_snmp_curd_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/go-playground/assert/v2" - "github.com/hootrhino/rulex/plugin/http_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) /* diff --git a/test/init_data_test.go b/test/init_data_test.go index 61ea2eda8..40732c4ac 100644 --- a/test/init_data_test.go +++ b/test/init_data_test.go @@ -7,9 +7,9 @@ import ( "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" - "github.com/hootrhino/rulex/plugin/http_server/model" - "github.com/hootrhino/rulex/plugin/http_server/service" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" ) diff --git a/test/jq_test.go b/test/jq_test.go index ccccedeef..1916538ce 100644 --- a/test/jq_test.go +++ b/test/jq_test.go @@ -7,7 +7,7 @@ import ( "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/modbus_parse_test.go b/test/modbus_parse_test.go index 02d192914..5edaaaa9a 100644 --- a/test/modbus_parse_test.go +++ b/test/modbus_parse_test.go @@ -13,7 +13,7 @@ import ( "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/plugin/demo_plugin" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/rpc_codec_test.go b/test/rpc_codec_test.go index 94700a4ca..d8b638921 100644 --- a/test/rpc_codec_test.go +++ b/test/rpc_codec_test.go @@ -8,7 +8,7 @@ import ( "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/rule_id_get_test.go b/test/rule_id_get_test.go index 5e8363a32..a712d517b 100644 --- a/test/rule_id_get_test.go +++ b/test/rule_id_get_test.go @@ -7,7 +7,7 @@ import ( "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/rulex_snapshot_dump_test.go b/test/rulex_snapshot_dump_test.go index 768ccaecd..771274163 100644 --- a/test/rulex_snapshot_dump_test.go +++ b/test/rulex_snapshot_dump_test.go @@ -13,7 +13,7 @@ import ( "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/plugin/demo_plugin" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/source_http_source_test.go b/test/source_http_source_test.go index f59ab0994..56cd4bef0 100644 --- a/test/source_http_source_test.go +++ b/test/source_http_source_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/utils" "github.com/hootrhino/rulex/typex" diff --git a/test/suorce_txiothub_test.go b/test/suorce_txiothub_test.go index 4a3fae310..da782e79a 100644 --- a/test/suorce_txiothub_test.go +++ b/test/suorce_txiothub_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" diff --git a/test/target_data_to_mongodb_test.go b/test/target_data_to_mongodb_test.go index f57187162..90277d978 100644 --- a/test/target_data_to_mongodb_test.go +++ b/test/target_data_to_mongodb_test.go @@ -9,7 +9,7 @@ import ( "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/target_data_tohttp_test.go b/test/target_data_tohttp_test.go index 4d818bbaa..216f1d9b6 100644 --- a/test/target_data_tohttp_test.go +++ b/test/target_data_tohttp_test.go @@ -10,8 +10,8 @@ import ( "time" "github.com/go-playground/assert/v2" - httpserver "github.com/hootrhino/rulex/plugin/http_server" - "github.com/hootrhino/rulex/plugin/http_server/model" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "github.com/hootrhino/rulex/typex" ) diff --git a/test/target_data_toudp_test.go b/test/target_data_toudp_test.go index 8261afee4..7da3deb4d 100644 --- a/test/target_data_toudp_test.go +++ b/test/target_data_toudp_test.go @@ -10,8 +10,8 @@ import ( "time" "github.com/go-playground/assert/v2" - httpserver "github.com/hootrhino/rulex/plugin/http_server" - "github.com/hootrhino/rulex/plugin/http_server/model" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "github.com/hootrhino/rulex/typex" ) diff --git a/test/target_tdengine_test.go b/test/target_tdengine_test.go index 795564eab..5974d393f 100644 --- a/test/target_tdengine_test.go +++ b/test/target_tdengine_test.go @@ -8,7 +8,7 @@ import ( "time" "github.com/hootrhino/rulex/component/rulexrpc" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/test_utils.go b/test/test_utils.go index 6f173a4db..0a1d0662b 100644 --- a/test/test_utils.go +++ b/test/test_utils.go @@ -10,7 +10,7 @@ import ( "testing" "time" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/engine" diff --git a/test/trailer_test.go b/test/trailer_test.go index 0093ece49..c87e14487 100644 --- a/test/trailer_test.go +++ b/test/trailer_test.go @@ -9,7 +9,7 @@ import ( "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/http_server" + httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) diff --git a/typex/version.go b/typex/version.go index 587ceea63..364afb765 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-21 20:26:31", + ReleaseTime: "2023-11-21 20:42:49", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 63ec8e137fb8ab08b4697cce19cf23e95afb8769 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 20:46:31 +0800 Subject: [PATCH 038/138] dev: rename __DEFAULT_DB_PATH --- component/datacenter/datecenter_sqlite_driver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/datacenter/datecenter_sqlite_driver.go b/component/datacenter/datecenter_sqlite_driver.go index 3d2eedc2f..fa8b4fe6e 100644 --- a/component/datacenter/datecenter_sqlite_driver.go +++ b/component/datacenter/datecenter_sqlite_driver.go @@ -13,7 +13,7 @@ import ( "gorm.io/gorm/logger" ) -const __DEFAULT_DB_PATH string = "./INTERNAL_DATACENTER.db" +const __DEFAULT_DB_PATH string = "./RULEX_INTERNAL_DATACENTER.db" var __Sqlite *SqliteDAO From 0aa73278d845da3536da1bca0708483535de0d6f Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 21:11:31 +0800 Subject: [PATCH 039/138] dev: add default index --- plugin/rulex_api_server/server/www/index.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 plugin/rulex_api_server/server/www/index.html diff --git a/plugin/rulex_api_server/server/www/index.html b/plugin/rulex_api_server/server/www/index.html new file mode 100644 index 000000000..8e6265367 --- /dev/null +++ b/plugin/rulex_api_server/server/www/index.html @@ -0,0 +1,18 @@ + + + + + + + + Rulex + + + + + + Hello,Rulex. + + + \ No newline at end of file From 56b446e8c992b2dc9fdf5b253212b498d4700d34 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 21:14:04 +0800 Subject: [PATCH 040/138] dev: update ignore --- .gitignore | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 654332c27..7098302fc 100644 --- a/.gitignore +++ b/.gitignore @@ -19,11 +19,11 @@ _build* lua-log* *.txt *.txt.gz -plugin/http_server/www/* -plugin/http_server/server/www/* +plugin/rulex_api_server/www/* +plugin/rulex_api_server/server/www/* dist/ apps/*.lua -plugin/http_server/www/index.html -plugin/http_server/server/www/index.html +plugin/rulex_api_server/www/index.html +plugin/rulex_api_server/server/www/index.html test/script/_temp/* upload/* From ce3a2988aec8e5cf5902bb0a8a88427436d5ef0d Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 21:37:14 +0800 Subject: [PATCH 041/138] dev: optimize recovery --- main.go | 4 ++-- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 19de16ec7..dff8678fd 100644 --- a/main.go +++ b/main.go @@ -128,9 +128,9 @@ func main() { log.Println("[DATA RECOVER] Stop rulex error", err) return err } - dir := "./upload/Backup/" + dir := "/usr/local/upload/Backup/" fileName := "recovery.db" - if err := ossupport.MoveFile(dir+fileName, "./rulex.db"); err != nil { + if err := ossupport.MoveFile(dir+fileName, "/usr/local/rulex.db"); err != nil { log.Println("[DATA RECOVER] Move Db File error", err) return err } diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index c66b02dce..8d6c13d8b 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -55,7 +55,7 @@ func Restart() error { } { - cmd := exec.Command("sudo", "service", "rulex", "start") + cmd := exec.Command("sudo", "service", "rulex", "restart") cmd.SysProcAttr = NewSysProcAttr() out, err := cmd.CombinedOutput() if err != nil { From 97e343fd25f2698c1bfc3a5019ecff56ce5223fe Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 22:23:44 +0800 Subject: [PATCH 042/138] fix: fix recover failed --- main.go | 10 ++++++---- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 10 +++++----- typex/version.go | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index dff8678fd..4620cf89e 100644 --- a/main.go +++ b/main.go @@ -122,18 +122,20 @@ func main() { }, Action: func(c *cli.Context) error { if !c.Bool("recover") { - return nil + return fmt.Errorf("[DATA RECOVER] Nothing todo") } if err := ossupport.StopRulex(); err != nil { log.Println("[DATA RECOVER] Stop rulex error", err) return err } - dir := "/usr/local/upload/Backup/" - fileName := "recovery.db" - if err := ossupport.MoveFile(dir+fileName, "/usr/local/rulex.db"); err != nil { + recoveryDb := "/usr/local/upload/Backup/recovery.db" + log.Println("[DATA RECOVER] Move Db File") + if err := ossupport.MoveFile(recoveryDb, "/usr/local/rulex.db"); err != nil { log.Println("[DATA RECOVER] Move Db File error", err) return err } + log.Println("[DATA RECOVER] Move Db File Finished") + log.Println("[DATA RECOVER] Try to Restart rulex") if err := ossupport.Restart(); err != nil { log.Println("[DATA RECOVER] Restart rulex error", err) return err diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index 8d6c13d8b..f53ec1c77 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -45,7 +45,7 @@ func StopRulex() error { */ func Restart() error { { - cmd := exec.Command("sudo", "systemctl", "daemon-reload") + cmd := exec.Command("systemctl", "daemon-reload") cmd.SysProcAttr = NewSysProcAttr() out, err := cmd.CombinedOutput() if err != nil { @@ -55,7 +55,7 @@ func Restart() error { } { - cmd := exec.Command("sudo", "service", "rulex", "restart") + cmd := exec.Command("service", "rulex", "restart") cmd.SysProcAttr = NewSysProcAttr() out, err := cmd.CombinedOutput() if err != nil { @@ -79,18 +79,18 @@ func Restart() error { */ func StartRecoverProcess() { log.Printf("Start Recover Process Pid=%d, Gid=%d", os.Getpid(), os.Getegid()) - cmd := exec.Command("bash", "-c", "/usr/local/rulex -recover=true") + cmd := exec.Command("bash", "-c", "/usr/local/rulex recover -recover=true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if cmd.Process != nil { - cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! + cmd.Process.Release() } err := cmd.Start() if cmd.Process != nil { - cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! + cmd.Process.Release() } if err != nil { log.Println("Start Recover Process Failed:", err) diff --git a/typex/version.go b/typex/version.go index 364afb765..c2168313c 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-21 20:42:49", + ReleaseTime: "2023-11-21 22:18:51", } var Banner = ` ** Welcome to RULEX framework world <'_'> From e3f0b37fda737ef7a3efa549adcad73c0441d66f Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 23:38:17 +0800 Subject: [PATCH 043/138] dev: update upgrade api --- main.go | 18 +++++++ ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 12 ++--- .../apis/system_firmware_api.go | 14 ++---- release_pkg.sh | 50 +++++++++++-------- typex/version.go | 2 +- 5 files changed, 58 insertions(+), 38 deletions(-) diff --git a/main.go b/main.go index 4620cf89e..bd8a28e54 100644 --- a/main.go +++ b/main.go @@ -76,6 +76,13 @@ func main() { }, }, Action: func(c *cli.Context) error { + file, err := os.Create("/usr/local/local-upgrade-log.txt") + if err != nil { + return fmt.Errorf("[DATA RECOVER] Error creating file:%s", err) + } + defer file.Close() + os.Stdout = file + os.Stderr = file OldPid := c.Int("oldpid") log.Println("[RULEX UPGRADE] Updater Pid=", os.Getpid(), "Gid=", os.Getegid(), " OldPid:", OldPid) @@ -121,15 +128,26 @@ func main() { }, }, Action: func(c *cli.Context) error { + file, err := os.Create("/usr/local/local-upgrade-log.txt") + if err != nil { + return fmt.Errorf("[DATA RECOVER] Error creating file:%s", err) + } + defer file.Close() + os.Stdout = file + os.Stderr = file if !c.Bool("recover") { return fmt.Errorf("[DATA RECOVER] Nothing todo") } + if err := ossupport.StopRulex(); err != nil { log.Println("[DATA RECOVER] Stop rulex error", err) return err } recoveryDb := "/usr/local/upload/Backup/recovery.db" log.Println("[DATA RECOVER] Move Db File") + if err := os.Remove("/usr/local/rulex.db"); err != nil { + return fmt.Errorf("[DATA RECOVER] Remove Old Db File error:%s", err) + } if err := ossupport.MoveFile(recoveryDb, "/usr/local/rulex.db"); err != nil { log.Println("[DATA RECOVER] Move Db File error", err) return err diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index f53ec1c77..d6e8ae2a8 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -82,9 +82,9 @@ func StartRecoverProcess() { cmd := exec.Command("bash", "-c", "/usr/local/rulex recover -recover=true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + cmd.Stdin = nil + cmd.Stdout = nil + cmd.Stderr = nil if cmd.Process != nil { cmd.Process.Release() } @@ -109,9 +109,9 @@ func StartUpgradeProcess(path string, args []string) { cmd := exec.Command("bash", "-c", path+" "+strings.Join(args, " ")) cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + cmd.Stdin = nil + cmd.Stdout = nil + cmd.Stderr = nil if cmd.Process != nil { cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! } diff --git a/plugin/rulex_api_server/apis/system_firmware_api.go b/plugin/rulex_api_server/apis/system_firmware_api.go index 3c7b53d4f..9fc2659ee 100644 --- a/plugin/rulex_api_server/apis/system_firmware_api.go +++ b/plugin/rulex_api_server/apis/system_firmware_api.go @@ -94,19 +94,13 @@ func UpgradeFirmWare(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error("invalid sum md5!")) return } - // 将其移动到一个临时目录 - if err := MoveFile(tempPath+"/rulex", tempPath+"/rulex-temp"); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + if err3 := os.RemoveAll(tempPath); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err3)) return } - if err := chmodX(tempPath + "/rulex-temp"); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - c.JSON(common.HTTP_OK, common.Ok()) - ossupport.StartUpgradeProcess(tempPath+"/rulex-temp", - []string{"upgrade", "-oldpid", fmt.Sprintf("%d", os.Getpid())}) + ossupport.StartUpgradeProcess("/usr/local/rulex", []string{"upgrade", "-oldpid", + fmt.Sprintf("%d", os.Getpid())}) } diff --git a/release_pkg.sh b/release_pkg.sh index 6433c1759..d66f98ede 100755 --- a/release_pkg.sh +++ b/release_pkg.sh @@ -121,30 +121,38 @@ calculate_and_save_md5() { # # fetch dashboard # +#!/bin/bash + fetch_dashboard() { - local www_zip="./www.zip" - local http_server_dir="./plugin/http_server/www" + local owner="hootrhino" + local repo="hootrhino-eekit-web" - # 检查文件是否存在 - if [ -f "$www_zip" ]; then - echo -e "\033[44;32m [√] File www.zip already downloaded \033[0m" - unzip -q "$www_zip" -d "$http_server_dir" - else - VERSION="$(git describe --tags $(git rev-list --tags --max-count=1))" - local URL="${RESPOSITORY}/hootrhino-eekit-web/releases/download/${VERSION}/www.zip" - echo -e "\033[41;37m [*] Fetch www.zip from: ${URL}\033[0m" - # 发送HEAD请求来检查URL是否存在 - response=$(curl -s --head -w %{http_code} "$URL" -o /dev/null) - - if [ "$response" = "200" ]; then - echo -e "\033[40;32m [*] Unzip www.zip to:${http_server_dir} \033[0m" - wget -q --show-progress "$URL" - unzip -q "$www_zip" -d "$http_server_dir" - else - echo -e "\033[41;30m [x] Error with http code 404, check if ${URL} exists \033[0m" - exit 1 - fi + # 检查当前目录是否已经存在 www.zip 文件 + if [ -f "www.zip" ]; then + echo "[!] www.zip already exists. No need to download." + exit 0 + fi + + # 获取最新 release 的 tag 名称 + local tag=$(curl -s "https://api.github.com/repos/$owner/$repo/releases/latest" | jq -r .tag_name) + + # 获取最新 release 中的 www.zip 下载链接 + local zip_url=$(curl -s "https://api.github.com/repos/$owner/$repo/releases/latest" | jq -r '.assets[] | select(.name == "www.zip") | .browser_download_url') + + if [ -z "$zip_url" ]; then + echo "[x] Error: www.zip not found in the release assets." + exit 1 fi + + # 下载 www.zip 文件 + curl -L -o www.zip "$zip_url" + + echo "[√] Download complete. Tag: $tag" + + # 解压 www.zip 文件到指定目录 + unzip -o www.zip -d /plugin/rulex_api_server/server/www/ + + echo "[√] Extraction complete. www.zip contents have been overwritten to /plugin/rulex_api_server/server/www/." } # diff --git a/typex/version.go b/typex/version.go index c2168313c..2e19e3173 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-21 22:18:51", + ReleaseTime: "2023-11-21 23:21:53", } var Banner = ` ** Welcome to RULEX framework world <'_'> From a1f0c148712423048cf1108335f58a79b85c5c57 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 21 Nov 2023 23:44:36 +0800 Subject: [PATCH 044/138] dev: optimize mem Percent --- plugin/rulex_api_server/service/memory_usage_linux.go | 3 ++- typex/version.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin/rulex_api_server/service/memory_usage_linux.go b/plugin/rulex_api_server/service/memory_usage_linux.go index 299e92aec..a64b4a0ac 100644 --- a/plugin/rulex_api_server/service/memory_usage_linux.go +++ b/plugin/rulex_api_server/service/memory_usage_linux.go @@ -19,6 +19,7 @@ import ( "fmt" "os" "strings" + "math" ) func GetMemPercent() (float64, error) { @@ -44,5 +45,5 @@ func GetMemPercent() (float64, error) { } } memPercent := 100.0 * (1.0 - memAvailable/memTotal) - return memPercent, nil + return math.Round(memPercent*100) / 100, nil } diff --git a/typex/version.go b/typex/version.go index 2e19e3173..f0e0f932e 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-21 23:21:53", + ReleaseTime: "2023-11-21 23:44:32", } var Banner = ` ** Welcome to RULEX framework world <'_'> From c47efe9970f9d8288ee38379884727f2895c132e Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 22 Nov 2023 11:50:47 +0800 Subject: [PATCH 045/138] dev: optimize mem Percent --- plugin/rulex_api_server/service/memory_usage_linux.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/plugin/rulex_api_server/service/memory_usage_linux.go b/plugin/rulex_api_server/service/memory_usage_linux.go index a64b4a0ac..073fd7271 100644 --- a/plugin/rulex_api_server/service/memory_usage_linux.go +++ b/plugin/rulex_api_server/service/memory_usage_linux.go @@ -17,13 +17,13 @@ package service import ( "fmt" - "os" - "strings" + "io/ioutil" "math" + "strings" ) func GetMemPercent() (float64, error) { - content, err := os.ReadFile("/proc/meminfo") + content, err := ioutil.ReadFile("/proc/meminfo") if err != nil { return 0.0, err } @@ -44,6 +44,7 @@ func GetMemPercent() (float64, error) { fmt.Sscan(fields[1], &memAvailable) } } - memPercent := 100.0 * (1.0 - memAvailable/memTotal) - return math.Round(memPercent*100) / 100, nil + + memPercent := math.Round(100.0*(1.0-memAvailable/memTotal)*100) / 100 + return memPercent, nil } From b1763656f8a4ed4c544b44187b090e0b16953145 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 22 Nov 2023 15:12:49 +0800 Subject: [PATCH 046/138] dev: optimize stream play --- component/rtspserver/rtsp_server.go | 25 +++----------- device/generic_camera_stream.go | 8 +++-- test/data/h264-stream-play.html | 41 +++++++++++++++++++++++ test/device_generic_camera_stream_test.go | 32 ++++++++++++++++-- typex/version.go | 2 +- 5 files changed, 82 insertions(+), 26 deletions(-) create mode 100644 test/data/h264-stream-play.html diff --git a/component/rtspserver/rtsp_server.go b/component/rtspserver/rtsp_server.go index 5f64ecdd7..73837bc0d 100644 --- a/component/rtspserver/rtsp_server.go +++ b/component/rtspserver/rtsp_server.go @@ -68,7 +68,7 @@ func InitRtspServer() *rtspServer { group.POST("/ffmpegPush", func(ctx *gin.Context) { LiveId := ctx.Query("liveId") // Token := ctx.Query("token") - glogger.GLogger.Info("Try to load RTSP From:", LiveId) + glogger.GLogger.Info("Receive stream push From:", LiveId) // http://127.0.0.1:9400 :后期通过参数传进 // 启动一个FFMPEG开始从摄像头拉流 bodyReader := bufio.NewReader(ctx.Request.Body) @@ -97,10 +97,10 @@ func InitRtspServer() *rtspServer { return __DefaultRtspServer } func pushToWebsocket(liveId string, data []byte) { - // fmt.Println(liveId, data) if C, Ok := __DefaultRtspServer.websocketPlayerManager.Clients[liveId]; Ok { - C.WriteMessage(2, data) + C.WriteMessage(websocket.BinaryMessage, data) } + } /* @@ -168,13 +168,7 @@ func NewPlayerManager() *websocketPlayerManager { * 启动服务 * */ -type wsToken struct { - Token string `json:"token"` - LiveId string `json:"live_id"` -} - func wsServerEndpoint(c *gin.Context) { - //upgrade get request to websocket protocol wsConn, err := __DefaultRtspServer.websocketPlayerManager.WsServer.Upgrade(c.Writer, c.Request, nil) if err != nil { return @@ -183,19 +177,18 @@ func wsServerEndpoint(c *gin.Context) { Token := c.Query("token") if Token != "WebRtspPlayer" { - wsConn.WriteMessage(1, []byte("Invalid client token")) + wsConn.WriteMessage(websocket.CloseMessage, []byte("Invalid client token")) wsConn.Close() return } glogger.GLogger.Debugf("Request live:%s, Token is :%s", LiveId, Token) // 最多允许连接10个客户端,实际情况下根本用不了那么多 - if len(__DefaultRtspServer.websocketPlayerManager.Clients) >= 2 { + if len(__DefaultRtspServer.websocketPlayerManager.Clients) >= 10 { wsConn.WriteMessage(websocket.CloseMessage, []byte{}) wsConn.Close() return } __DefaultRtspServer.websocketPlayerManager.Clients[LiveId] = wsConn - wsConn.WriteMessage(websocket.TextMessage, []byte("Connected")) glogger.GLogger.Info("WebSocket Player connected:" + wsConn.RemoteAddr().String()) wsConn.SetCloseHandler(func(code int, text string) error { glogger.GLogger.Info("wsConn CloseHandler:", wsConn.RemoteAddr().String()) @@ -211,14 +204,6 @@ func wsServerEndpoint(c *gin.Context) { return nil }) go func(wsConn *websocket.Conn) { - defer func() { - if wsConn != nil { - glogger.GLogger.Info("wsConn Disconnect By accident:", wsConn.RemoteAddr().String()) - __DefaultRtspServer.websocketPlayerManager.lock.Lock() - delete(__DefaultRtspServer.websocketPlayerManager.Clients, wsConn.RemoteAddr().String()) - __DefaultRtspServer.websocketPlayerManager.lock.Unlock() - } - }() for { select { case <-typex.GCTX.Done(): diff --git a/device/generic_camera_stream.go b/device/generic_camera_stream.go index 09bf70c1a..a4ae713ae 100644 --- a/device/generic_camera_stream.go +++ b/device/generic_camera_stream.go @@ -169,7 +169,7 @@ func (vc *videoCamera) startFFMPEGProcess(rtspUrl, pushAddr string) { }() paramsVideo := []string{ "-f", "dshow", - "-i", fmt.Sprintf("video=%s", rtspUrl), + "-i", fmt.Sprintf("video='%s'", rtspUrl), "-c:v", "libx264", "-preset", "veryfast", "-tune", "zerolatency", @@ -220,9 +220,11 @@ func (vc *videoCamera) startFFMPEGProcess(rtspUrl, pushAddr string) { cmd.Stdin = nil cmd.Stdout = inOut cmd.Stderr = inOut + } else { + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr + vc.ffmpegProcess = cmd // 等待 FFmpeg 进程完成 if err := vc.ffmpegProcess.Wait(); err != nil { diff --git a/test/data/h264-stream-play.html b/test/data/h264-stream-play.html new file mode 100644 index 000000000..d9fd5b635 --- /dev/null +++ b/test/data/h264-stream-play.html @@ -0,0 +1,41 @@ + + + + + + + WebSocket FLV Stream Player + + + + + + + + + + \ No newline at end of file diff --git a/test/device_generic_camera_stream_test.go b/test/device_generic_camera_stream_test.go index 178a6128c..a32f0a3ad 100644 --- a/test/device_generic_camera_stream_test.go +++ b/test/device_generic_camera_stream_test.go @@ -24,7 +24,7 @@ func Test_Generic_Local_camera(t *testing.T) { hh := httpserver.NewHttpApiServer(engine) // HttpApiServer loaded default if err := engine.LoadPlugin("plugin.http_server", hh); err != nil { - glogger.GLogger.Fatal("Rule load failed:", err) + glogger.GLogger.Fatal("http_server load failed:", err) t.Fatal(err) } GENERIC_CAMERA := typex.NewDevice(typex.GENERIC_CAMERA, @@ -66,7 +66,35 @@ func Test_Generic_RTSP_camera(t *testing.T) { "inputMode": "RTSP", "device": "video0", "rtspUrl": "rtsp://192.168.0.101:554/av0_0", - "outputMode": "JPEG_STREAM", + "outputMode": "H264_STREAM", + "outputAddr": "0.0.0.0:2599", + }) + ctx, cancelF := typex.NewCCTX() + if err := engine.LoadDeviceWithCtx(GENERIC_CAMERA, ctx, cancelF); err != nil { + t.Fatal(err) + } + time.Sleep(25 * time.Second) + engine.Stop() +} + +// go test -timeout 30s -run ^Test_Generic_LOCAL_camera github.com/hootrhino/rulex/test -v -count=1 + +func Test_Generic_LOCAL_camera(t *testing.T) { + engine := RunTestEngine() + engine.Start() + + hh := httpserver.NewHttpApiServer(engine) + if err := engine.LoadPlugin("plugin.http_server", hh); err != nil { + glogger.GLogger.Fatal("Rule load failed:", err) + t.Fatal(err) + } + GENERIC_CAMERA := typex.NewDevice(typex.GENERIC_CAMERA, + "GENERIC_CAMERA", "GENERIC_CAMERA", map[string]interface{}{ + "maxThread": 10, + "inputMode": "LOCAL", + "device": "video0", + "rtspUrl": "rtsp://192.168.0.101:554/av0_0", + "outputMode": "H264_STREAM", "outputAddr": "0.0.0.0:2599", }) ctx, cancelF := typex.NewCCTX() diff --git a/typex/version.go b/typex/version.go index f0e0f932e..a93b91391 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-21 23:44:32", + ReleaseTime: "2023-11-22 11:30:23", } var Banner = ` ** Welcome to RULEX framework world <'_'> From bb81747789f660b34c3951042b20d34dd1a2ba80 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 22 Nov 2023 15:25:00 +0800 Subject: [PATCH 047/138] dev: update doc --- device/generic_camera_stream.md | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/device/generic_camera_stream.md b/device/generic_camera_stream.md index 63601ea25..ac220dc24 100644 --- a/device/generic_camera_stream.md +++ b/device/generic_camera_stream.md @@ -17,36 +17,11 @@ } ``` ## 测试 -可以通过下面这个HTML页面来测试效果。 -```html - - +勃播放地址:`ws://127.0.0.1:9400/ws?token=WebRtspPlayer&liveId=a97607e47c81d43dba8ef6fa48a2cd45`,其中: +- URL: 固定路径`ws://127.0.0.1:9400/ws` +- token:固定值`WebRtspPlayer` +- liveId:播放源的名称的**md5Hash**,例如`USB2.0 PC CAMERA`的 liveId 是 `a97607e47c81d43dba8ef6fa48a2cd45`。 - - - - - Document - - - - - -
- - - -
-
- - - -
- - - -``` ## 维护 - From bc3ddd9f16147924680fe54b441e04d4c7ce6f6a Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 22 Nov 2023 16:33:48 +0800 Subject: [PATCH 048/138] dev: add hide_banner to ffmpeg --- device/generic_camera_stream.go | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/device/generic_camera_stream.go b/device/generic_camera_stream.go index a4ae713ae..ae36ca60e 100644 --- a/device/generic_camera_stream.go +++ b/device/generic_camera_stream.go @@ -9,7 +9,6 @@ import ( "regexp" "syscall" - "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" @@ -168,6 +167,8 @@ func (vc *videoCamera) startFFMPEGProcess(rtspUrl, pushAddr string) { vc.status = typex.DEV_DOWN }() paramsVideo := []string{ + "-hide_banner", + "-framerate", "24", "-f", "dshow", "-i", fmt.Sprintf("video='%s'", rtspUrl), "-c:v", "libx264", @@ -179,6 +180,8 @@ func (vc *videoCamera) startFFMPEGProcess(rtspUrl, pushAddr string) { paramsRtsp := []string{ // rtsp://192.168.199.243:554/av0_0 + "-hide_banner", + "-framerate", "24", "-rtsp_transport", "tcp", "-re", @@ -211,25 +214,10 @@ func (vc *videoCamera) startFFMPEGProcess(rtspUrl, pushAddr string) { } glogger.GLogger.Info("Start FFMPEG ffmpegProcess with:", cmd.String()) // 启动 FFmpeg 推流 - if err := cmd.Start(); err != nil { - glogger.GLogger.Error(err) - return - } - if core.GlobalConfig.AppDebugMode { - inOut := wsInOut{} - cmd.Stdin = nil - cmd.Stdout = inOut - cmd.Stderr = inOut - } else { - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - } - + cmd.Env = os.Environ() vc.ffmpegProcess = cmd - // 等待 FFmpeg 进程完成 - if err := vc.ffmpegProcess.Wait(); err != nil { - output, _ := cmd.CombinedOutput() - glogger.GLogger.Error(err, string(output)) + if output, err := cmd.CombinedOutput(); err != nil { + glogger.GLogger.Error("error: ", err, ", output: ", string(output)) return } glogger.GLogger.Info("stop Video Stream Endpoint:", rtspUrl) From 27d6f6a40849282a5c9136b4ba0e91395cdc26a8 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 22 Nov 2023 22:22:14 +0800 Subject: [PATCH 049/138] dev: fix update and recover --- main.go | 8 ++-- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 40 +++++++++++-------- ossupport/sysattr_linux.go | 4 +- .../apis/rhinoh3_firmware_api.go | 7 +--- .../apis/sysconfig_backup_api.go | 10 ++--- plugin/rulex_api_server/service/dao.go | 6 +-- typex/version.go | 2 +- 7 files changed, 36 insertions(+), 41 deletions(-) diff --git a/main.go b/main.go index bd8a28e54..ae0944fd8 100644 --- a/main.go +++ b/main.go @@ -128,16 +128,16 @@ func main() { }, }, Action: func(c *cli.Context) error { - file, err := os.Create("/usr/local/local-upgrade-log.txt") + if !c.Bool("recover") { + return fmt.Errorf("[DATA RECOVER] Nothing todo") + } + file, err := os.Create("/usr/local/local-recover-log.txt") if err != nil { return fmt.Errorf("[DATA RECOVER] Error creating file:%s", err) } defer file.Close() os.Stdout = file os.Stderr = file - if !c.Bool("recover") { - return fmt.Errorf("[DATA RECOVER] Nothing todo") - } if err := ossupport.StopRulex(); err != nil { log.Println("[DATA RECOVER] Stop rulex error", err) diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index d6e8ae2a8..6593855cb 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -78,24 +78,23 @@ func Restart() error { * */ func StartRecoverProcess() { - log.Printf("Start Recover Process Pid=%d, Gid=%d", os.Getpid(), os.Getegid()) - cmd := exec.Command("bash", "-c", "/usr/local/rulex recover -recover=true") - cmd.SysProcAttr = NewSysProcAttr() - cmd.Env = os.Environ() - cmd.Stdin = nil - cmd.Stdout = nil - cmd.Stderr = nil - if cmd.Process != nil { - cmd.Process.Release() + file, err1 := os.Create("/usr/local/local-recover-log.txt") + if err1 != nil { + return } + defer file.Close() + cmd := exec.Command("/usr/local/rulex", "recover", "-recover=true") + cmd.SysProcAttr = NewSysProcAttr() + cmd.Env = []string{} + cmd.Stdout = file + cmd.Stderr = file err := cmd.Start() - if cmd.Process != nil { - cmd.Process.Release() - } + log.Printf("Start Recover Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) if err != nil { log.Println("Start Recover Process Failed:", err) return } + log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } @@ -105,13 +104,18 @@ func StartRecoverProcess() { * */ func StartUpgradeProcess(path string, args []string) { - log.Printf("Start Upgrade Process Pid=%d, Gid=%d", os.Getpid(), os.Getegid()) + file, err1 := os.Create("/usr/local/local-upgrade-log.txt") + if err1 != nil { + return + } + defer file.Close() + cmd := exec.Command("bash", "-c", path+" "+strings.Join(args, " ")) cmd.SysProcAttr = NewSysProcAttr() - cmd.Env = os.Environ() - cmd.Stdin = nil - cmd.Stdout = nil - cmd.Stderr = nil + cmd.Env = []string{} + cmd.Stdout = file + cmd.Stderr = file + log.Printf("Start Upgrade Process Pid=%d, Gid=%d", os.Getpid(), os.Getegid()) if cmd.Process != nil { cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! } @@ -119,10 +123,12 @@ func StartUpgradeProcess(path string, args []string) { if cmd.Process != nil { cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! } + log.Printf("Start Upgrade Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) if err != nil { log.Println("Start Upgrade Process Failed:", err) return } + log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } diff --git a/ossupport/sysattr_linux.go b/ossupport/sysattr_linux.go index 1b8d22e8b..967cc5d1a 100644 --- a/ossupport/sysattr_linux.go +++ b/ossupport/sysattr_linux.go @@ -6,8 +6,6 @@ import ( func NewSysProcAttr() *syscall.SysProcAttr { return &syscall.SysProcAttr{ - Setsid: true, - Pdeathsig: syscall.SIGTERM, - Cloneflags: syscall.CLONE_NEWUTS, + Setsid: true, } } diff --git a/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go b/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go index b592690a6..db27898c9 100644 --- a/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go +++ b/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go @@ -42,7 +42,7 @@ func ReStartRulex(c *gin.Context, ruleEngine typex.RuleX) { func Reboot(c *gin.Context, ruleEngine typex.RuleX) { err := ossupport.Reboot() if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + c.JSON(common.HTTP_OK, common.OkWithData(err)) return } c.JSON(common.HTTP_OK, common.Ok()) @@ -54,7 +54,6 @@ func Reboot(c *gin.Context, ruleEngine typex.RuleX) { * */ func RecoverNew(c *gin.Context, ruleEngine typex.RuleX) { - c.JSON(common.HTTP_OK, common.Ok()) } @@ -65,9 +64,5 @@ func RecoverNew(c *gin.Context, ruleEngine typex.RuleX) { */ func GetUpGradeLog(c *gin.Context, ruleEngine typex.RuleX) { byteS, _ := os.ReadFile("local-upgrade-log.txt") - // if err != nil { - // c.JSON(common.HTTP_OK, common.Error400(err)) - // return - // } c.JSON(common.HTTP_OK, common.OkWithData(string(byteS))) } diff --git a/plugin/rulex_api_server/apis/sysconfig_backup_api.go b/plugin/rulex_api_server/apis/sysconfig_backup_api.go index 1b4cccae9..e96f31ada 100644 --- a/plugin/rulex_api_server/apis/sysconfig_backup_api.go +++ b/plugin/rulex_api_server/apis/sysconfig_backup_api.go @@ -41,24 +41,24 @@ func UploadSqlite(c *gin.Context, ruleEngine typex.RuleX) { // single file file, err := c.FormFile("file") if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + c.JSON(common.HTTP_OK, common.OkWithData(err)) return } fileName := "recovery.db" dir := "./upload/Backup/" if err := os.MkdirAll(filepath.Dir(dir), os.ModePerm); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + c.JSON(common.HTTP_OK, common.OkWithData(err)) return } if err := c.SaveUploadedFile(file, dir+fileName); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + c.JSON(common.HTTP_OK, common.OkWithData(err)) return } if _, err := ReadSQLiteFileMagicNumber(dir + fileName); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + c.JSON(common.HTTP_OK, common.OkWithData(err)) return } - c.JSON(common.HTTP_OK, common.Ok()) + c.JSON(common.HTTP_OK, common.OkWithData("")) ossupport.StartRecoverProcess() } diff --git a/plugin/rulex_api_server/service/dao.go b/plugin/rulex_api_server/service/dao.go index bd74bb8c4..209d45a4a 100644 --- a/plugin/rulex_api_server/service/dao.go +++ b/plugin/rulex_api_server/service/dao.go @@ -189,11 +189,7 @@ func AllDevices() []model.MDevice { // 获取设备列表 func GetMDeviceWithUUID(uuid string) (*model.MDevice, error) { m := new(model.MDevice) - if err := interdb.DB().Where("uuid=?", uuid).First(m).Error; err != nil { - return nil, err - } else { - return m, nil - } + return m, interdb.DB().Where("uuid=?", uuid).First(m).Error } // 删除设备 diff --git a/typex/version.go b/typex/version.go index a93b91391..95684219a 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-22 11:30:23", + ReleaseTime: "2023-11-22 22:00:23", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 47dd03b06ace350f746adaf74ba5e013495ef9a1 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 22 Nov 2023 23:22:51 +0800 Subject: [PATCH 050/138] dev: fix recover --- main.go | 15 -------------- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 23 ++++++---------------- typex/version.go | 2 +- 3 files changed, 7 insertions(+), 33 deletions(-) diff --git a/main.go b/main.go index ae0944fd8..aa2f79ac3 100644 --- a/main.go +++ b/main.go @@ -76,13 +76,6 @@ func main() { }, }, Action: func(c *cli.Context) error { - file, err := os.Create("/usr/local/local-upgrade-log.txt") - if err != nil { - return fmt.Errorf("[DATA RECOVER] Error creating file:%s", err) - } - defer file.Close() - os.Stdout = file - os.Stderr = file OldPid := c.Int("oldpid") log.Println("[RULEX UPGRADE] Updater Pid=", os.Getpid(), "Gid=", os.Getegid(), " OldPid:", OldPid) @@ -131,14 +124,6 @@ func main() { if !c.Bool("recover") { return fmt.Errorf("[DATA RECOVER] Nothing todo") } - file, err := os.Create("/usr/local/local-recover-log.txt") - if err != nil { - return fmt.Errorf("[DATA RECOVER] Error creating file:%s", err) - } - defer file.Close() - os.Stdout = file - os.Stderr = file - if err := ossupport.StopRulex(); err != nil { log.Println("[DATA RECOVER] Stop rulex error", err) return err diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index 6593855cb..be0a45d78 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -78,16 +78,11 @@ func Restart() error { * */ func StartRecoverProcess() { - file, err1 := os.Create("/usr/local/local-recover-log.txt") - if err1 != nil { - return - } - defer file.Close() cmd := exec.Command("/usr/local/rulex", "recover", "-recover=true") cmd.SysProcAttr = NewSysProcAttr() - cmd.Env = []string{} - cmd.Stdout = file - cmd.Stderr = file + cmd.Env = os.Environ() + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr err := cmd.Start() log.Printf("Start Recover Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) if err != nil { @@ -104,17 +99,11 @@ func StartRecoverProcess() { * */ func StartUpgradeProcess(path string, args []string) { - file, err1 := os.Create("/usr/local/local-upgrade-log.txt") - if err1 != nil { - return - } - defer file.Close() - cmd := exec.Command("bash", "-c", path+" "+strings.Join(args, " ")) cmd.SysProcAttr = NewSysProcAttr() - cmd.Env = []string{} - cmd.Stdout = file - cmd.Stderr = file + cmd.Env = os.Environ() + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr log.Printf("Start Upgrade Process Pid=%d, Gid=%d", os.Getpid(), os.Getegid()) if cmd.Process != nil { cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! diff --git a/typex/version.go b/typex/version.go index 95684219a..85b30ec44 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-22 22:00:23", + ReleaseTime: "2023-11-22 23:20:52", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 065188dc89075c1004723f0579b8b63e974a21ce Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 23 Nov 2023 16:34:30 +0800 Subject: [PATCH 051/138] dev: add openwrt daemon support --- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 19 +- script/readme-daemon.md | 47 ++-- script/readme-openwrt.md | 30 +++ script/rulex-daemon.sh | 252 +++++++++++++-------- script/rulex-openwrt.sh | 149 ++++++++++++ typex/version.go | 2 +- 6 files changed, 369 insertions(+), 130 deletions(-) create mode 100644 script/readme-openwrt.md create mode 100644 script/rulex-openwrt.sh diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index be0a45d78..1bba45276 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -30,7 +30,7 @@ import ( * */ func StopRulex() error { - cmd := exec.Command("service", "rulex", "stop") + cmd := exec.Command("sudo", "systemctl", "rulex", "stop") out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("%s,%s", err, string(out)) @@ -45,7 +45,7 @@ func StopRulex() error { */ func Restart() error { { - cmd := exec.Command("systemctl", "daemon-reload") + cmd := exec.Command("sudo", "systemctl", "daemon-reload") cmd.SysProcAttr = NewSysProcAttr() out, err := cmd.CombinedOutput() if err != nil { @@ -55,7 +55,7 @@ func Restart() error { } { - cmd := exec.Command("service", "rulex", "restart") + cmd := exec.Command("sudo", "systemctl", "rulex", "restart") cmd.SysProcAttr = NewSysProcAttr() out, err := cmd.CombinedOutput() if err != nil { @@ -78,12 +78,18 @@ func Restart() error { * */ func StartRecoverProcess() { - cmd := exec.Command("/usr/local/rulex", "recover", "-recover=true") + cmd := exec.Command("sudo", "/usr/local/rulex", "recover", "-recover=true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr + if cmd.Process != nil { + cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! + } err := cmd.Start() + if cmd.Process != nil { + cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! + } log.Printf("Start Recover Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) if err != nil { log.Println("Start Recover Process Failed:", err) @@ -99,12 +105,11 @@ func StartRecoverProcess() { * */ func StartUpgradeProcess(path string, args []string) { - cmd := exec.Command("bash", "-c", path+" "+strings.Join(args, " ")) + cmd := exec.Command("sudo", "bash", "-c", path+" "+strings.Join(args, " ")) cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - log.Printf("Start Upgrade Process Pid=%d, Gid=%d", os.Getpid(), os.Getegid()) if cmd.Process != nil { cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! } @@ -127,7 +132,7 @@ func StartUpgradeProcess(path string, args []string) { * */ func Reboot() error { - cmd := exec.Command("reboot") + cmd := exec.Command("sudo", "reboot") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { diff --git a/script/readme-daemon.md b/script/readme-daemon.md index 21e6861a7..56168a340 100644 --- a/script/readme-daemon.md +++ b/script/readme-daemon.md @@ -1,29 +1,30 @@ -# Linux script -该脚本是RULEX的`系统服务`操作脚本,处理RULEX的安装、启动、停止、卸载等。 +# Linux daemon script +该脚本是RULEX的`通用Linux系统`操作脚本,处理RULEX的安装、启动、停止、卸载等。 ## 基础使用 +### 下载 将安装包解压: ```sh -unzip rulex-arm32linux-v0.6.2.zip -d rulex +unzip rulex-arm32linux-$VERSION.zip -d rulex +``` +### 安装 +```sh +./rulex-daemon.sh install +``` + +### 卸载 +```sh +./rulex-daemon.sh uninstall ``` +### 使用 下面的脚本一定要在root权限下执行,或者使用sudo。 -- 安装 - ```sh - ./rulex_daemon.sh install - ``` -- 启动 - ```sh - ./rulex_daemon.sh start - ``` -- 状态 - ```sh - ./rulex_daemon.sh status - ``` -- 停止 - ```sh - ./rulex_daemon.sh stop - ``` -- 卸载 - ```sh - ./rulex_daemon.sh uninstall - ``` +```bash +# 启动 +./rulex-daemon.sh start +# 停止 +./rulex-daemon.sh stop +# 重启 +./rulex-daemon.sh restart +# 状态 +./rulex-daemon.sh status +``` diff --git a/script/readme-openwrt.md b/script/readme-openwrt.md new file mode 100644 index 000000000..44fcac3c7 --- /dev/null +++ b/script/readme-openwrt.md @@ -0,0 +1,30 @@ +# Openwrt daemon script +该脚本是RULEX的`Openwrt系统`操作脚本,处理RULEX的安装、启动、停止、卸载等。 +## 基础使用 +### 下载 +将安装包解压: +```sh +unzip rulex-arm32linux-$VERSION.zip -d rulex +``` +### 安装 +```sh +./rulex-openwrt.sh install +``` + +### 卸载 +```sh +./rulex-openwrt.sh uninstall +``` + +### 使用 +下面的脚本一定要在root权限下执行,或者使用sudo。 +```bash +# 启动 +./rulex-openwrt.sh start +# 停止 +./rulex-openwrt.sh stop +# 重启 +./rulex-openwrt.sh restart +# 状态 +./rulex-openwrt.sh status +``` diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index ae2149c2f..b398932c3 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -1,130 +1,184 @@ -#!/bin/sh /etc/rc.common -# rulex_daemon - Rulex daemon script for Linux +#!/bin/bash -START=99 -USE_PROCD=1 +### BEGIN INIT INFO +# Provides: rulex +# Required-Start: $network $local_fs $remote_fs +# Required-Stop: $network $local_fs $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Rulex Service +# Description: Rulex Service +### END INIT INFO -# Check if the service is disabled -[ -e /etc/config/rulex_daemon ] && . /etc/config/rulex_daemon +EXECUTABLE_PATH="/usr/local/rulex" +CONFIG_PATH="/usr/local/rulex.ini" +SERVICE_NAME="rulex" +WORKING_DIRECTORY="/usr/local/" +WAIT_TIME_SECONDS=3 +CHECK_INTERVAL_SECONDS=1 +PID_FILE="/var/run/$SERVICE_NAME.pid" +SCRIPT_PATH="/etc/init.d/rulex.sh" +PID_FILE="/var/run/rulex.pid" + +log() { + local level=$1 + shift + echo "[$level] $(date +'%Y-%m-%d %H:%M:%S') - $@" +} -working_directory="/usr/local/" -# Function to copy files to /usr/local -install_files() { - cp "./rulex $working_directory - cp "./rulex.ini $working_directory - cp "./license.key" $working_directory - cp "./license.lic" $working_directory +install(){ + local source_dir="$PWD" + local service_file="/etc/init.d/rulex.service" + local executable="/usr/local/rulex" + local working_directory="/usr/local/" + local config_file="/usr/local/rulex.ini" + local db_file="/usr/local/rulex.db" +cat > "$service_file" << EOL +#!/bin/sh $service_file +# Create Time: $(date +'%Y-%m-%d %H:%M:%S') +log() { + local level=\$1 + shift + echo "[$level] $(date +'%Y-%m-%d %H:%M:%S') - $@" } -remove_files() { - if [ -e "$1" ]; then - if [[ $1 == *"/upload"* ]]; then - rm -rf "$1" - else - rm "$1" - fi - echo "[!] $1 files removed." - else - echo "[*] $1 files not found. No need to remove." - fi + +start() { + log INFO "Starting rulex..." + nohup $executable run -config=$config_file nohup.log 2>&1 & + echo $! > "$PID_FILE" + log INFO "Starting rulex Finished" } -start_service() { - if [ "$DISABLED" -eq 0 ]; then - procd_open_instance - procd_set_param command /usr/local/rulex run -config /usr/local/rulex.ini - procd_set_param respawn - procd_set_param timeout 5 # 5 seconds timeout - procd_close_instance +stop() { + # Check if rulex process is running + if pgrep -x "rulex" > /dev/null; then + pid=$(pgrep -x "rulex") + log INFO "Killing rulex process with PID $pid" + kill "$pid" else - echo "Service is disabled. To enable, run: /etc/init.d/rulex_daemon enable" + log INFO "rulex process is not running." fi } -stop_service() { - procd_close_instance +restart() { + stop + start } -# Function to disable the service -disable_service() { - [ -e /etc/config/rulex_daemon ] && echo 'DISABLED=1' > /etc/config/rulex_daemon - /etc/init.d/rulex_daemon stop - /etc/init.d/rulex_daemon disable +status() { + log INFO "Checking rulex status..." + pid=$(pgrep -x "rulex") + if [ -n "$pid" ]; then + log INFO "rulex is running with Pid:${pid}" + else + log INFO "rulex is not running." + fi } -# Function to enable the service -enable_service() { - [ -e /etc/config/rulex_daemon ] && rm /etc/config/rulex_daemon - /etc/init.d/rulex_daemon enable -} +EOL -# Function to uninstall the service -uninstall_service() { - procd_close_instance - remove_files $working_directory/rulex - remove_files $working_directory/rulex.ini - remove_files $working_directory/rulex.db - remove_files $working_directory/*.txt - remove_files $working_directory/upload/ - remove_files $working_directory/license.key - remove_files $working_directory/license.lic - remove_files $working_directory/*.txt.gz - /etc/init.d/rulex_daemon stop - /etc/init.d/rulex_daemon disable - rm /etc/init.d/rulex_daemon - rm /etc/config/rulex_daemon - echo "Rulex uninstallation complete." + mkdir -p $working_directory + chmod +x $source_dir/rulex + cp -rfp "$source_dir/rulex" "$executable" + cp -rfp "$source_dir/rulex.ini" "$config_file" + cp -rfp "$source_dir/license.lic" "$working_directory" + cp -rfp "$source_dir/license.key" "$working_directory" + chmod 777 $service_file + if [ $? -eq 0 ]; then + log INFO "Rulex service has been created and extracted." + else + log ERROR "Failed to create the Rulex service or extract files." + fi + exit 0 } -# Function to check service status -status_service() { - if procd_status rulex_daemon > /dev/null; then - echo "Rulex is running." +__remove_files() { + local file=$1 + log INFO "Removing $file..." + if [ -e "$file" ]; then + if [ -d "$file" ]; then + rm -rf "$file" + else + rm "$file" + fi + log INFO "$file removed." else - echo "Rulex is not running." + log INFO "$file not found. No need to remove." fi } -service_triggers() { - procd_add_reload_trigger "rulex" +uninstall(){ + local working_directory="/usr/local" + __remove_files /etc/systemd/system/rulex.service + __remove_files $working_directory/rulex + __remove_files $working_directory/rulex.ini + __remove_files $working_directory/rulex.db + __remove_files $working_directory/license.lic + __remove_files $working_directory/license.key + __remove_files $working_directory/upload/ + __remove_files $working_directory/*.txt + __remove_files $working_directory/*.txt.gz + log INFO "Rulex has been uninstalled." } -reload_service() { - procd_send_signal rulex HUP +start() { + log INFO "Starting $SERVICE_NAME..." + nohup $EXECUTABLE_PATH run -config $CONFIG_PATH >output.log 2>&1 & + echo "$!" > "$PID_FILE" && log INFO "Service started." } -shutdown_service() { - procd_close_instance +stop() { + log INFO "Stopping $SERVICE_NAME..." + rm -f "$PID_FILE" && log INFO "PID file removed." + pid=$(pgrep -x "$SERVICE_NAME") + if [ -n "$pid" ]; then + kill -15 "$pid" && log INFO "Process $pid (rulex) terminated." + pkill -f "$SERVICE_NAME" + else + log INFO "Process rulex not found." + fi } -service_error() { - procd_close_instance - echo "Error starting rulex_daemon" >&2 +restart(){ + stop + start } -run() { - case "$1" in - install) - install_files - ;; - start) - start_service - ;; - restart) - reload_service - ;; - stop) - stop_service - ;; - uninstall) - uninstall_service - ;; - status) - status_service - ;; - *) - echo "Usage: $0 {install|start|restart|stop|uninstall|status}" - exit 1 - ;; - esac +status() { + log INFO "Checking $SERVICE_NAME status..." + pid=$(pgrep -x "$SERVICE_NAME") + if [ -n "$pid" ]; then + log INFO "$SERVICE_NAME is running with Pid:${pid}" + else + log INFO "$SERVICE_NAME is not running." + fi } + +case "$1" in + install) + install + ;; + start) + start + ;; + restart) + stop + start + ;; + stop) + stop + ;; + uninstall) + uninstall + ;; + status) + status + ;; + *) + log ERROR "Usage: $0 {install|start|restart|stop|uninstall|status}" + exit 1 + ;; +esac + +exit 0 diff --git a/script/rulex-openwrt.sh b/script/rulex-openwrt.sh new file mode 100644 index 000000000..28fe0ba5c --- /dev/null +++ b/script/rulex-openwrt.sh @@ -0,0 +1,149 @@ +#!/bin/bash +# Copyright (C) 2023 wwhai +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +log() { + local level=$1 + shift + echo "[$level] $(date +'%Y-%m-%d %H:%M:%S') - $@" +} + +install() { + local source_dir="$PWD" + local service_file="/etc/init.d/rulex.service" + local executable="/usr/local/rulex" + local working_directory="/usr/local/" + local config_file="/usr/local/rulex.ini" + local db_file="/usr/local/rulex.db" + + cat > "$service_file" << EOL +#!/bin/sh $service_file + +START=180 + +USE_PROCD=1 + +start() { + procd_open_instance + procd_set_param command "$executable run -config=$config_file -db=$db_file" + procd_set_param respawn 0 + procd_set_param stdout 1 + procd_set_param stderr 1 + procd_close_instance +} + +stop() { + service_stop "$executable" +} + +restart() { + stop + start +} + +status() { + log INFO "Checking rulex status..." + pid=$(pgrep -x "rulex") + if [ -n "$pid" ]; then + log INFO "rulex is running with Pid:${pid}" + else + log INFO "rulex is not running." + fi +} + +EOL + + mkdir -p "$working_directory" + chmod +x "$source_dir/rulex" + cp -rfp "$source_dir/rulex" "$executable" + cp -rfp "$source_dir/rulex.ini" "$config_file" + cp -rfp "$source_dir/license.lic" "$working_directory" + cp -rfp "$source_dir/license.key" "$working_directory" + + chmod 777 "$service_file" + "$service_file" enable + + if [ $? -eq 0 ]; then + log INFO "Rulex service has been created and extracted." + else + log ERROR "Failed to create the Rulex service or extract files." + fi + exit 0 +} + +__remove_files() { + local file=$1 + log INFO "Removing $file..." + if [ -e "$file" ]; then + if [ -d "$file" ]; then + rm -rf "$file" + else + rm "$file" + fi + log INFO "$file removed." + else + log INFO "$file not found. No need to remove." + fi +} + +uninstall() { + local service_file="$service_file.service" + "$service_file" stop + "$service_file" disable + local working_directory="/usr/local" + __remove_files /etc/systemd/system/rulex.service + __remove_files "$working_directory/rulex" "$working_directory/rulex.ini" "$working_directory/rulex.db" + __remove_files "$working_directory/license.lic" "$working_directory/license.key" + __remove_files "$working_directory/upload/" "$working_directory/"*.txt "$working_directory/"*.txt.gz + log INFO "Rulex has been uninstalled." +} + +start() { + $service_file start +} + +restart() { + $service_file restart +} + +stop() { + $service_file stop +} + +status() { + $service_file running +} + +main() { + case "$1" in + install | start | restart | stop | uninstall | create_user | status | openwrt) + $1 + ;; + *) + log ERROR "Invalid command: $1" + echo "[?] Usage: $0 " + exit 1 + ;; + esac + exit 0 +} + +if [ "$(id -u)" != "0" ]; then + log ERROR "This script must be run as root" + exit 1 +else + main "$1" +fi diff --git a/typex/version.go b/typex/version.go index 85b30ec44..b0b6af261 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-22 23:20:52", + ReleaseTime: "2023-11-23 11:42:13", } var Banner = ` ** Welcome to RULEX framework world <'_'> From fb2c6624f0b8ca2a8434bac73d24426d46df0c14 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 23 Nov 2023 18:10:43 +0800 Subject: [PATCH 052/138] dev: fix path error --- ...=> rhinoh3_ubuntu18_datetime_ctl_linux.go} | 25 ++++-- .../rhinoh3_ubuntu18_datetime_ctl_windows.go | 46 +++++++++++ ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 40 ++++----- ossupport/rhinoh3_ubuntu18_process_ctrl.go | 81 +++++++++++++++++++ ...nfig_api.go => system_config_api_linux.go} | 0 script/rulex-daemon.sh | 34 ++++---- script/rulex-openwrt.sh | 26 +++--- typex/version.go | 2 +- 8 files changed, 192 insertions(+), 62 deletions(-) rename ossupport/{rhinoh3_ubuntu18_datetime_ctl.go => rhinoh3_ubuntu18_datetime_ctl_linux.go} (89%) create mode 100644 ossupport/rhinoh3_ubuntu18_datetime_ctl_windows.go create mode 100644 ossupport/rhinoh3_ubuntu18_process_ctrl.go rename plugin/rulex_api_server/apis/{system_config_api.go => system_config_api_linux.go} (100%) diff --git a/ossupport/rhinoh3_ubuntu18_datetime_ctl.go b/ossupport/rhinoh3_ubuntu18_datetime_ctl_linux.go similarity index 89% rename from ossupport/rhinoh3_ubuntu18_datetime_ctl.go rename to ossupport/rhinoh3_ubuntu18_datetime_ctl_linux.go index 5e95a36ce..ef841ba44 100644 --- a/ossupport/rhinoh3_ubuntu18_datetime_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_datetime_ctl_linux.go @@ -17,6 +17,7 @@ package ossupport import ( "fmt" + "golang.org/x/sys/unix" "os/exec" "strings" "time" @@ -161,14 +162,22 @@ func SetTimeZone(timezone string) error { * 获取开机时间 * */ + func GetUptime() (string, error) { - shell := ` -awk '{print int($1 / 86400) " days " int(($1 % 86400) / 3600) " hours " int(($1 % 3600) / 60) " minutes"}' /proc/uptime -` - cmd := exec.Command("sh", "-c", shell) - output, err := cmd.CombinedOutput() - if err != nil { - return "", fmt.Errorf("GetUptime error:%s,%s", string(output), err.Error()) + var info unix.Sysinfo_t + + if err := unix.Sysinfo(&info); err != nil { + return "0:0:0", err } - return strings.Trim(string(output), "\n"), nil + + return formatUptime(int64(info.Uptime)), nil +} + +func formatUptime(uptime int64) string { + days := uptime / 86400 + hours := (uptime % 86400) / 3600 + minutes := (uptime % 3600) / 60 + seconds := uptime % 60 + + return fmt.Sprintf("%d days, %02d:%02d:%02d", days, hours, minutes, seconds) } diff --git a/ossupport/rhinoh3_ubuntu18_datetime_ctl_windows.go b/ossupport/rhinoh3_ubuntu18_datetime_ctl_windows.go new file mode 100644 index 000000000..6197c682c --- /dev/null +++ b/ossupport/rhinoh3_ubuntu18_datetime_ctl_windows.go @@ -0,0 +1,46 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package ossupport + +import ( + "fmt" + "github.com/hootrhino/wmi" +) + +/* +* +* 获取开机时间 +* + */ +type Win32OperatingSystem struct { + LastBootUpTime string +} + +func GetUptime() (string, error) { + var result []Win32OperatingSystem + query := "SELECT LastBootUpTime FROM Win32_OperatingSystem" + + err := wmi.Query(query, &result) + if err != nil { + return "", err + } + + if len(result) > 0 { + return result[0].LastBootUpTime, nil + } + + return "0:0:0", fmt.Errorf("Failed to retrieve system uptime") +} diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index 1bba45276..ebc1958f7 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -30,10 +30,13 @@ import ( * */ func StopRulex() error { - cmd := exec.Command("sudo", "systemctl", "rulex", "stop") - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("%s,%s", err, string(out)) + pid, err1 := GetEarliestProcessPID("rulex") + if err1 != nil { + return err1 + } + err2 := KillProcess(pid) + if err2 != nil { + return err2 } return nil } @@ -44,25 +47,10 @@ func StopRulex() error { * */ func Restart() error { - { - cmd := exec.Command("sudo", "systemctl", "daemon-reload") - cmd.SysProcAttr = NewSysProcAttr() - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("%s,%s", err, string(out)) - } - log.Println("[Prepare Stage] systemctl daemon-reload:", string(out)) - - } - { - cmd := exec.Command("sudo", "systemctl", "rulex", "restart") - cmd.SysProcAttr = NewSysProcAttr() - out, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("%s,%s", err, string(out)) - } - log.Println("[Prepare Stage] service start:", string(out)) - + cmd := exec.Command("/etc/systemd/system/rulex.service", "restart") + out, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("%s,%s", err, string(out)) } return nil } @@ -78,7 +66,7 @@ func Restart() error { * */ func StartRecoverProcess() { - cmd := exec.Command("sudo", "/usr/local/rulex", "recover", "-recover=true") + cmd := exec.Command("/usr/local/rulex", "recover", "-recover=true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() cmd.Stdout = os.Stdout @@ -105,7 +93,7 @@ func StartRecoverProcess() { * */ func StartUpgradeProcess(path string, args []string) { - cmd := exec.Command("sudo", "bash", "-c", path+" "+strings.Join(args, " ")) + cmd := exec.Command("bash", "-c", path+" "+strings.Join(args, " ")) cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() cmd.Stdout = os.Stdout @@ -132,7 +120,7 @@ func StartUpgradeProcess(path string, args []string) { * */ func Reboot() error { - cmd := exec.Command("sudo", "reboot") + cmd := exec.Command("reboot") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { diff --git a/ossupport/rhinoh3_ubuntu18_process_ctrl.go b/ossupport/rhinoh3_ubuntu18_process_ctrl.go new file mode 100644 index 000000000..591ed5971 --- /dev/null +++ b/ossupport/rhinoh3_ubuntu18_process_ctrl.go @@ -0,0 +1,81 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package ossupport + +import ( + "fmt" + "os/exec" + "sort" + "strconv" + "strings" +) + +/* +* +* kill -9 +* + */ +func KillProcess(processID int) error { + cmd := exec.Command("kill", "-9", fmt.Sprintf("%d", processID)) + err := cmd.Run() + return err +} + +/* +* +* pgrep rulex -> 38506\n +* + */ +func GetProcessPID(processName string) (int, error) { + cmd := exec.Command("pgrep", processName) + output, err := cmd.Output() + if err != nil { + return 0, err + } + pidString := strings.TrimSpace(string(output)) + pid, err := strconv.Atoi(pidString) + if err != nil { + return 0, err + } + return pid, nil +} + +/* +* +* 取最老的那个进程Id +* + */ +func GetEarliestProcessPID(processName string) (int, error) { + cmd := exec.Command("pgrep", processName) + output, err := cmd.Output() + if err != nil { + return 0, err + } + pidStrings := strings.Fields(string(output)) + var pids []int + for _, pidString := range pidStrings { + pid, err := strconv.Atoi(pidString) + if err == nil { + pids = append(pids, pid) + } + } + if len(pids) == 0 { + return 0, fmt.Errorf("No process found with name %s", processName) + } + sort.Ints(pids) + earliestPID := pids[0] + return earliestPID, nil +} diff --git a/plugin/rulex_api_server/apis/system_config_api.go b/plugin/rulex_api_server/apis/system_config_api_linux.go similarity index 100% rename from plugin/rulex_api_server/apis/system_config_api.go rename to plugin/rulex_api_server/apis/system_config_api_linux.go diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index b398932c3..ace3e4ee2 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -13,13 +13,13 @@ EXECUTABLE_PATH="/usr/local/rulex" CONFIG_PATH="/usr/local/rulex.ini" SERVICE_NAME="rulex" -WORKING_DIRECTORY="/usr/local/" +WORKING_DIRECTORY="/usr/local" WAIT_TIME_SECONDS=3 CHECK_INTERVAL_SECONDS=1 PID_FILE="/var/run/$SERVICE_NAME.pid" SCRIPT_PATH="/etc/init.d/rulex.sh" PID_FILE="/var/run/rulex.pid" - +service_file="/etc/init.d/rulex.service" log() { local level=$1 shift @@ -29,9 +29,7 @@ log() { install(){ local source_dir="$PWD" - local service_file="/etc/init.d/rulex.service" local executable="/usr/local/rulex" - local working_directory="/usr/local/" local config_file="/usr/local/rulex.ini" local db_file="/usr/local/rulex.db" cat > "$service_file" << EOL @@ -78,12 +76,12 @@ status() { EOL - mkdir -p $working_directory + mkdir -p $WORKING_DIRECTORY chmod +x $source_dir/rulex cp -rfp "$source_dir/rulex" "$executable" cp -rfp "$source_dir/rulex.ini" "$config_file" - cp -rfp "$source_dir/license.lic" "$working_directory" - cp -rfp "$source_dir/license.key" "$working_directory" + cp -rfp "$source_dir/license.lic" "$WORKING_DIRECTORY/" + cp -rfp "$source_dir/license.key" "$WORKING_DIRECTORY/" chmod 777 $service_file if [ $? -eq 0 ]; then log INFO "Rulex service has been created and extracted." @@ -109,16 +107,18 @@ __remove_files() { } uninstall(){ - local working_directory="/usr/local" - __remove_files /etc/systemd/system/rulex.service - __remove_files $working_directory/rulex - __remove_files $working_directory/rulex.ini - __remove_files $working_directory/rulex.db - __remove_files $working_directory/license.lic - __remove_files $working_directory/license.key - __remove_files $working_directory/upload/ - __remove_files $working_directory/*.txt - __remove_files $working_directory/*.txt.gz + __remove_files $service_file + __remove_files "$WORKING_DIRECTORY/rulex" + __remove_files "$WORKING_DIRECTORY/rulex.ini" + __remove_files "$WORKING_DIRECTORY/rulex.db" + __remove_files "$WORKING_DIRECTORY/license.lic" + __remove_files "$WORKING_DIRECTORY/license.key" + __remove_files "$WORKING_DIRECTORY/RULEX_INTERNAL_DATACENTER.db" + __remove_files "$WORKING_DIRECTORY/LICENSE" + __remove_files "$WORKING_DIRECTORY/md5.sum" + __remove_files "$WORKING_DIRECTORY/upload/" + __remove_files "$WORKING_DIRECTORY/"*.txt + __remove_files "$WORKING_DIRECTORY/"*.txt.gz log INFO "Rulex has been uninstalled." } diff --git a/script/rulex-openwrt.sh b/script/rulex-openwrt.sh index 28fe0ba5c..b97f9a522 100644 --- a/script/rulex-openwrt.sh +++ b/script/rulex-openwrt.sh @@ -13,6 +13,7 @@ # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +WORKING_DIRECTORY="/usr/local" log() { @@ -25,7 +26,6 @@ install() { local source_dir="$PWD" local service_file="/etc/init.d/rulex.service" local executable="/usr/local/rulex" - local working_directory="/usr/local/" local config_file="/usr/local/rulex.ini" local db_file="/usr/local/rulex.db" @@ -66,12 +66,12 @@ status() { EOL - mkdir -p "$working_directory" + mkdir -p "$WORKING_DIRECTORY/" chmod +x "$source_dir/rulex" cp -rfp "$source_dir/rulex" "$executable" cp -rfp "$source_dir/rulex.ini" "$config_file" - cp -rfp "$source_dir/license.lic" "$working_directory" - cp -rfp "$source_dir/license.key" "$working_directory" + cp -rfp "$source_dir/license.lic" "$WORKING_DIRECTORY/" + cp -rfp "$source_dir/license.key" "$WORKING_DIRECTORY/" chmod 777 "$service_file" "$service_file" enable @@ -100,14 +100,20 @@ __remove_files() { } uninstall() { - local service_file="$service_file.service" "$service_file" stop "$service_file" disable - local working_directory="/usr/local" - __remove_files /etc/systemd/system/rulex.service - __remove_files "$working_directory/rulex" "$working_directory/rulex.ini" "$working_directory/rulex.db" - __remove_files "$working_directory/license.lic" "$working_directory/license.key" - __remove_files "$working_directory/upload/" "$working_directory/"*.txt "$working_directory/"*.txt.gz + __remove_files $service_file + __remove_files "$WORKING_DIRECTORY/rulex" + __remove_files "$WORKING_DIRECTORY/rulex.ini" + __remove_files "$WORKING_DIRECTORY/rulex.db" + __remove_files "$WORKING_DIRECTORY/license.lic" + __remove_files "$WORKING_DIRECTORY/license.key" + __remove_files "$WORKING_DIRECTORY/RULEX_INTERNAL_DATACENTER.db" + __remove_files "$WORKING_DIRECTORY/LICENSE" + __remove_files "$WORKING_DIRECTORY/md5.sum" + __remove_files "$WORKING_DIRECTORY/upload/" + __remove_files "$WORKING_DIRECTORY/"*.txt + __remove_files "$WORKING_DIRECTORY/"*.txt.gz log INFO "Rulex has been uninstalled." } diff --git a/typex/version.go b/typex/version.go index b0b6af261..4d9ce2c07 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-23 11:42:13", + ReleaseTime: "2023-11-23 18:06:37", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 84639f05c95813e99d437beb086dbc7653d94b43 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 23 Nov 2023 22:45:38 +0800 Subject: [PATCH 053/138] dev: fix process nil --- main.go | 72 +++++++++------- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 55 ++++-------- .../apis/system_firmware_api.go | 3 +- plugin/rulex_api_server/http_api_server.go | 5 +- script/rulex-daemon.sh | 84 +++++++++++-------- script/rulex-openwrt.sh | 11 ++- typex/version.go | 2 +- 7 files changed, 119 insertions(+), 113 deletions(-) diff --git a/main.go b/main.go index aa2f79ac3..427d071cf 100644 --- a/main.go +++ b/main.go @@ -60,7 +60,7 @@ func main() { Action: func(c *cli.Context) error { fmt.Println(typex.Banner) engine.RunRulex(c.String("config")) - log.Printf("[RULEX UPGRADE] Run rulex successfully.") + fmt.Printf("[RULEX UPGRADE] Run rulex successfully.") return nil }, }, @@ -76,32 +76,40 @@ func main() { }, }, Action: func(c *cli.Context) error { + file, err := os.Create("./local-upgrade-log.txt") + if err != nil { + fmt.Println(err) + return err + } + defer file.Close() + os.Stdout = file + os.Stderr = file OldPid := c.Int("oldpid") - log.Println("[RULEX UPGRADE] Updater Pid=", + fmt.Println("[RULEX UPGRADE] Updater Pid=", os.Getpid(), "Gid=", os.Getegid(), " OldPid:", OldPid) if OldPid < 0 { - log.Printf("[RULEX UPGRADE] Invalid OldPid:%d", OldPid) + fmt.Printf("[RULEX UPGRADE] Invalid OldPid:%d", OldPid) return nil } // Try 5 times killOld := true - log.Println("[RULEX UPGRADE] Try to kill Old Process:", OldPid) + fmt.Println("[RULEX UPGRADE] Try to kill Old Process:", OldPid) if killOld { // EEKITH3 Use SystemCtl manage RULEX env := os.Getenv("ARCHSUPPORT") if runtime.GOOS == "linux" { - log.Println("[RULEX UPGRADE] Ready to Upgrade on product:", env) + fmt.Println("[RULEX UPGRADE] Ready to Upgrade on product:", env) if err := ossupport.UnzipFirmware( "/usr/local/upload/Firmware/Firmware.zip", "/usr/local"); err != nil { - log.Println("[RULEX UPGRADE] Unzip error:", err) + fmt.Println("[RULEX UPGRADE] Unzip error:", err) return err } - if err := ossupport.Restart(); err != nil { - log.Println("[RULEX UPGRADE] Restart rulex error", err) + if err := ossupport.RestartRulex(); err != nil { + fmt.Println("[RULEX UPGRADE] Restart rulex error", err) return err } - log.Println("[RULEX UPGRADE] Restart rulex success, Upgrade Process Exited") + fmt.Println("[RULEX UPGRADE] Restart rulex success, Upgrade Process Exited") } } os.Exit(0) @@ -121,29 +129,37 @@ func main() { }, }, Action: func(c *cli.Context) error { - if !c.Bool("recover") { - return fmt.Errorf("[DATA RECOVER] Nothing todo") - } - if err := ossupport.StopRulex(); err != nil { - log.Println("[DATA RECOVER] Stop rulex error", err) + file, err := os.Create("./local-recover-log.txt") + if err != nil { + fmt.Println(err) return err } - recoveryDb := "/usr/local/upload/Backup/recovery.db" - log.Println("[DATA RECOVER] Move Db File") - if err := os.Remove("/usr/local/rulex.db"); err != nil { - return fmt.Errorf("[DATA RECOVER] Remove Old Db File error:%s", err) + defer file.Close() + os.Stdout = file + os.Stderr = file + if !c.Bool("recover") { + fmt.Println("[DATA RECOVER] Nothing todo") + return nil + } + fmt.Println("[DATA RECOVER] Remove Old Db File") + if err := os.Remove("./rulex.db"); err != nil { + fmt.Println("[DATA RECOVER] Remove Old Db File error:", err) + return nil } - if err := ossupport.MoveFile(recoveryDb, "/usr/local/rulex.db"); err != nil { - log.Println("[DATA RECOVER] Move Db File error", err) - return err + fmt.Println("[DATA RECOVER] Remove Old Db File Finished") + fmt.Println("[DATA RECOVER] Move New Db File") + recoveryDb := "./upload/Backup/recovery.db" + if err := ossupport.MoveFile(recoveryDb, "./rulex.db"); err != nil { + fmt.Println("[DATA RECOVER] Move New Db File error", err) + return nil } - log.Println("[DATA RECOVER] Move Db File Finished") - log.Println("[DATA RECOVER] Try to Restart rulex") - if err := ossupport.Restart(); err != nil { - log.Println("[DATA RECOVER] Restart rulex error", err) - return err + fmt.Println("[DATA RECOVER] Move New Db File Finished") + fmt.Println("[DATA RECOVER] Try to Restart rulex") + if err := ossupport.RestartRulex(); err != nil { + fmt.Println("[DATA RECOVER] Restart rulex error", err) + return nil } - log.Println("[DATA RECOVER] Restart rulex success, Recover Process Exited") + fmt.Println("[DATA RECOVER] Restart rulex success, Recover Process Exited") os.Exit(0) return nil }, @@ -185,7 +201,7 @@ func main() { return err } // commercial version will implement it - log.Printf("[LICENCE ACTIVE]: Admin(%s,%s), mac addr:[%s] try to request license from %s\n", + fmt.Printf("[LICENCE ACTIVE]: Admin(%s,%s), mac addr:[%s] try to request license from %s\n", username, password, macAddr, host) return nil }, diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index ebc1958f7..a2392ad37 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -17,10 +17,10 @@ package ossupport import ( "fmt" - "io" "log" "os" "os/exec" + "path/filepath" "strings" ) @@ -46,8 +46,8 @@ func StopRulex() error { * 重启 * */ -func Restart() error { - cmd := exec.Command("/etc/systemd/system/rulex.service", "restart") +func RestartRulex() error { + cmd := exec.Command("/etc/init.d/rulex.service", "restart") out, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("%s,%s", err, string(out)) @@ -66,23 +66,15 @@ func Restart() error { * */ func StartRecoverProcess() { - cmd := exec.Command("/usr/local/rulex", "recover", "-recover=true") + cmd := exec.Command("./rulex", "recover", "-recover=true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if cmd.Process != nil { - cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! - } err := cmd.Start() - if cmd.Process != nil { - cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! - } - log.Printf("Start Recover Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) if err != nil { log.Println("Start Recover Process Failed:", err) return } + log.Printf("Start Recover Process Pid=%d, Cmd:%s\n", cmd.Process.Pid, cmd.String()) log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } @@ -92,24 +84,16 @@ func StartRecoverProcess() { * 启用升级进程 * */ -func StartUpgradeProcess(path string, args []string) { - cmd := exec.Command("bash", "-c", path+" "+strings.Join(args, " ")) +func StartUpgradeProcess() { + cmd := exec.Command("./rulex", "upgrade", "-oldpid=", fmt.Sprintf("%d", os.Getpid())) cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if cmd.Process != nil { - cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! - } err := cmd.Start() - if cmd.Process != nil { - cmd.Process.Release() // 用来分离进程用,简直天坑参数!!! - } - log.Printf("Start Upgrade Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) if err != nil { log.Println("Start Upgrade Process Failed:", err) return } + log.Printf("Start Upgrade Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } @@ -149,25 +133,14 @@ func UnzipFirmware(zipFile, destDir string) error { * */ func MoveFile(sourcePath, destPath string) error { - inputFile, err := os.Open(sourcePath) - if err != nil { - return fmt.Errorf("couldn't open source file: %s", err) - } - outputFile, err := os.Create(destPath) - if err != nil { - inputFile.Close() - return fmt.Errorf("couldn't open dest file: %s", err) - } - defer outputFile.Close() - _, err = io.Copy(outputFile, inputFile) - inputFile.Close() - if err != nil { - return fmt.Errorf("Writing to output file failed: %s", err) + + destDir := filepath.Dir(destPath) + if err := os.MkdirAll(destDir, 0755); err != nil { + return fmt.Errorf("failed to create destination directory: %w", err) } - // The copy was successful, so now delete the original file - err = os.Remove(sourcePath) + err := os.Rename(sourcePath, destPath) if err != nil { - return fmt.Errorf("Failed removing original file: %s", err) + return fmt.Errorf("failed to move file: %w", err) } return nil } diff --git a/plugin/rulex_api_server/apis/system_firmware_api.go b/plugin/rulex_api_server/apis/system_firmware_api.go index 9fc2659ee..936ef80c2 100644 --- a/plugin/rulex_api_server/apis/system_firmware_api.go +++ b/plugin/rulex_api_server/apis/system_firmware_api.go @@ -99,8 +99,7 @@ func UpgradeFirmWare(c *gin.Context, ruleEngine typex.RuleX) { return } c.JSON(common.HTTP_OK, common.Ok()) - ossupport.StartUpgradeProcess("/usr/local/rulex", []string{"upgrade", "-oldpid", - fmt.Sprintf("%d", os.Getpid())}) + ossupport.StartUpgradeProcess() } diff --git a/plugin/rulex_api_server/http_api_server.go b/plugin/rulex_api_server/http_api_server.go index b6d1d7ff5..4faff1e15 100644 --- a/plugin/rulex_api_server/http_api_server.go +++ b/plugin/rulex_api_server/http_api_server.go @@ -28,6 +28,7 @@ import ( type _serverConfig struct { DbPath string `ini:"dbpath"` + Port int `ini:"port"` } type ApiServerPlugin struct { uuid string @@ -38,7 +39,7 @@ type ApiServerPlugin struct { func NewHttpApiServer(ruleEngine typex.RuleX) *ApiServerPlugin { return &ApiServerPlugin{ uuid: "HTTP-API-SERVER", - mainConfig: _serverConfig{}, + mainConfig: _serverConfig{Port: 2580}, ruleEngine: ruleEngine, } } @@ -473,7 +474,7 @@ func (hs *ApiServerPlugin) LoadRoute() { func (hs *ApiServerPlugin) Start(r typex.RuleX) error { hs.ruleEngine = r hs.LoadRoute() - glogger.GLogger.Infof("Http server started on :%v", hs.mainConfig.DbPath) + glogger.GLogger.Infof("Http server started on :%v", 2580) return nil } diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index ace3e4ee2..cba58ef11 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -33,27 +33,34 @@ install(){ local config_file="/usr/local/rulex.ini" local db_file="/usr/local/rulex.db" cat > "$service_file" << EOL -#!/bin/sh $service_file +#!/bin/sh # Create Time: $(date +'%Y-%m-%d %H:%M:%S') + +WORKING_DIRECTORY="/usr/local" +PID_FILE="/var/run/rulex.pid" +executable="/usr/local/rulex" +config_file="/usr/local/rulex.ini" + log() { local level=\$1 shift - echo "[$level] $(date +'%Y-%m-%d %H:%M:%S') - $@" + echo "[\$level] \$(date +'%Y-%m-%d %H:%M:%S') - \$@" } start() { log INFO "Starting rulex..." - nohup $executable run -config=$config_file nohup.log 2>&1 & - echo $! > "$PID_FILE" + cd \$WORKING_DIRECTORY + nohup \$executable run -config=\$config_file > run-nohup-log.txt 2>&1 & + echo \$! > "\$PID_FILE" log INFO "Starting rulex Finished" } stop() { # Check if rulex process is running if pgrep -x "rulex" > /dev/null; then - pid=$(pgrep -x "rulex") - log INFO "Killing rulex process with PID $pid" - kill "$pid" + pid=\$(pgrep -x "rulex") + log INFO "Killing rulex process with PID \$pid" + kill "\$pid" else log INFO "rulex process is not running." fi @@ -66,14 +73,34 @@ restart() { status() { log INFO "Checking rulex status..." - pid=$(pgrep -x "rulex") - if [ -n "$pid" ]; then - log INFO "rulex is running with Pid:${pid}" + pid=\$(pgrep -x "rulex") + if [ -n "\$pid" ]; then + log INFO "rulex is running with Pid:\${pid}" else log INFO "rulex is not running." fi } +case "\$1" in + start) + start + ;; + restart) + stop + start + ;; + stop) + stop + ;; + status) + status + ;; + *) + log ERROR "Usage: \$0 {start|restart|stop|status}" + exit 1 + ;; +esac + EOL mkdir -p $WORKING_DIRECTORY @@ -107,6 +134,10 @@ __remove_files() { } uninstall(){ + if [ -e "$service_file" ]; then + $service_file stop + $service_file disable + fi __remove_files $service_file __remove_files "$WORKING_DIRECTORY/rulex" __remove_files "$WORKING_DIRECTORY/rulex.ini" @@ -117,42 +148,25 @@ uninstall(){ __remove_files "$WORKING_DIRECTORY/LICENSE" __remove_files "$WORKING_DIRECTORY/md5.sum" __remove_files "$WORKING_DIRECTORY/upload/" - __remove_files "$WORKING_DIRECTORY/"*.txt - __remove_files "$WORKING_DIRECTORY/"*.txt.gz + __remove_files "$WORKING_DIRECTORY/*.txt" + __remove_files "$WORKING_DIRECTORY/*.txt.gz" log INFO "Rulex has been uninstalled." } start() { - log INFO "Starting $SERVICE_NAME..." - nohup $EXECUTABLE_PATH run -config $CONFIG_PATH >output.log 2>&1 & - echo "$!" > "$PID_FILE" && log INFO "Service started." + $service_file start } -stop() { - log INFO "Stopping $SERVICE_NAME..." - rm -f "$PID_FILE" && log INFO "PID file removed." - pid=$(pgrep -x "$SERVICE_NAME") - if [ -n "$pid" ]; then - kill -15 "$pid" && log INFO "Process $pid (rulex) terminated." - pkill -f "$SERVICE_NAME" - else - log INFO "Process rulex not found." - fi +restart() { + $service_file restart } -restart(){ - stop - start +stop() { + $service_file stop } status() { - log INFO "Checking $SERVICE_NAME status..." - pid=$(pgrep -x "$SERVICE_NAME") - if [ -n "$pid" ]; then - log INFO "$SERVICE_NAME is running with Pid:${pid}" - else - log INFO "$SERVICE_NAME is not running." - fi + $service_file status } case "$1" in diff --git a/script/rulex-openwrt.sh b/script/rulex-openwrt.sh index b97f9a522..5655f402a 100644 --- a/script/rulex-openwrt.sh +++ b/script/rulex-openwrt.sh @@ -100,8 +100,10 @@ __remove_files() { } uninstall() { - "$service_file" stop - "$service_file" disable + if [ -e "$service_file" ]; then + $service_file stop + $service_file disable + fi __remove_files $service_file __remove_files "$WORKING_DIRECTORY/rulex" __remove_files "$WORKING_DIRECTORY/rulex.ini" @@ -112,8 +114,9 @@ uninstall() { __remove_files "$WORKING_DIRECTORY/LICENSE" __remove_files "$WORKING_DIRECTORY/md5.sum" __remove_files "$WORKING_DIRECTORY/upload/" - __remove_files "$WORKING_DIRECTORY/"*.txt - __remove_files "$WORKING_DIRECTORY/"*.txt.gz + __remove_files "$WORKING_DIRECTORY/*.txt" + __remove_files "$WORKING_DIRECTORY/run-nohup-log.txt" + __remove_files "$WORKING_DIRECTORY/*.txt.gz" log INFO "Rulex has been uninstalled." } diff --git a/typex/version.go b/typex/version.go index 4d9ce2c07..1c152938d 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-23 18:06:37", + ReleaseTime: "2023-11-23 22:39:29", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 2263e991b8428e8f5f19f8ab41b07dd5b4ebc93d Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 23 Nov 2023 22:45:59 +0800 Subject: [PATCH 054/138] fix: remove unused import --- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 1 - 1 file changed, 1 deletion(-) diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index a2392ad37..7b637afe8 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -21,7 +21,6 @@ import ( "os" "os/exec" "path/filepath" - "strings" ) /* From 1eca8ad8c8a28457f2061c3bc5e8d43b36cec6e3 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 24 Nov 2023 13:31:52 +0800 Subject: [PATCH 055/138] dev: test data recover --- component/interqueue/xqueue.go | 13 ++++++---- conf/rulex.ini | 4 ++-- script/rulex-daemon.sh | 43 ++++++++++++++++++++++++++++++---- script/rulex-openwrt.sh | 5 ++-- script/rulex-systemctl.sh | 3 ++- test/conf/rulex.ini | 4 ++-- typex/version.go | 2 +- 7 files changed, 57 insertions(+), 17 deletions(-) diff --git a/component/interqueue/xqueue.go b/component/interqueue/xqueue.go index f940971ea..4222b9483 100644 --- a/component/interqueue/xqueue.go +++ b/component/interqueue/xqueue.go @@ -73,8 +73,12 @@ func (q *DataCacheQueue) GetSize() int { * */ func (q *DataCacheQueue) Push(d QueueData) error { - if len(q.Queue)+1 > 52428800 { // 50Mb - msg := fmt.Sprintf("attached max queue size, max size is:%v, current size is: %v", q.GetSize(), len(q.Queue)+1) + // 动态扩容 + // if len(q.Queue)+1 > q.GetSize() { + // } + if len(q.Queue)+1 > q.GetSize() { + msg := fmt.Sprintf("attached max queue size, max size is:%v, current size is: %v", + q.GetSize(), len(q.Queue)+1) glogger.GLogger.Error(msg) return errors.New(msg) } else { @@ -92,8 +96,7 @@ func (q *DataCacheQueue) GetQueue() chan QueueData { return q.Queue } -// 此处内置的消息队列用了go的channel, 看似好像很简单,但是经过测试发现完全满足网关需求,甚至都性能过剩了 -// 因此大家看到这里务必担心, 我也知道有很精美的高级框架, 但是用简单的方法来实现功能不是更好吗? +// TODO: 下个版本更换为可扩容的Chan func StartDataCacheQueue() { go func(ctx context.Context, xQueue XQueue) { @@ -101,6 +104,8 @@ func StartDataCacheQueue() { select { case <-ctx.Done(): return + // 这个地方不能阻塞,需要借助一个外部queue + // push qd -> Queue case qd := <-xQueue.GetQueue(): { // diff --git a/conf/rulex.ini b/conf/rulex.ini index a5eb70b49..ccf3bcadb 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -32,9 +32,9 @@ log_level = info # log_path = rulexlog # -# Max data cache size, default is 50MB +# Max data cache size # -max_queue_size = 52428800 +max_queue_size = 20971520 # # Max store size, default is 20MB # diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index cba58ef11..ca523cd92 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -17,7 +17,7 @@ WORKING_DIRECTORY="/usr/local" WAIT_TIME_SECONDS=3 CHECK_INTERVAL_SECONDS=1 PID_FILE="/var/run/$SERVICE_NAME.pid" -SCRIPT_PATH="/etc/init.d/rulex.sh" +service_file="/etc/init.d/rulex.sh" PID_FILE="/var/run/rulex.pid" service_file="/etc/init.d/rulex.service" log() { @@ -109,6 +109,7 @@ EOL cp -rfp "$source_dir/rulex.ini" "$config_file" cp -rfp "$source_dir/license.lic" "$WORKING_DIRECTORY/" cp -rfp "$source_dir/license.key" "$WORKING_DIRECTORY/" + __add_to_rc_local chmod 777 $service_file if [ $? -eq 0 ]; then log INFO "Rulex service has been created and extracted." @@ -132,11 +133,44 @@ __remove_files() { log INFO "$file not found. No need to remove." fi } +__remove_from_rc_local() { + local rc_local_path="/etc/rc.local" + if [ ! -f "$rc_local_path" ]; then + log ERROR "Error: /etc/rc.local does not exist. Check your system configuration." + return 1 + fi + if ! grep -qF "$service_file start" "$rc_local_path"; then + log INFO "Script not found in /etc/rc.local. No changes made." + return 0 + fi + sed -i "\|$service_file start|d" "$rc_local_path" + log INFO "Script removed from /etc/rc.local." + return 0 +} + +__add_to_rc_local() { + local rc_local_path="/etc/rc.local" + if [ ! -f "$rc_local_path" ]; then + log INFO "Error: /etc/rc.local does not exist. Create the file manually or check your system configuration." + return 1 + fi + if grep -qF "$service_file start" "$rc_local_path"; then + log INFO "Script already present in /etc/rc.local. No changes made." + return 0 + fi + local last_line_number=$(awk '/^[^#[:space:]]/{n=$0} END{print NR}' "$rc_local_path") + if [ -n "$last_line_number" ]; then + sed -i "${last_line_number}i $service_file start" "$rc_local_path" + else + echo "$service_file start" >> "$rc_local_path" + fi + log INFO "Script added to /etc/rc.local." + return 0 +} uninstall(){ if [ -e "$service_file" ]; then $service_file stop - $service_file disable fi __remove_files $service_file __remove_files "$WORKING_DIRECTORY/rulex" @@ -148,8 +182,9 @@ uninstall(){ __remove_files "$WORKING_DIRECTORY/LICENSE" __remove_files "$WORKING_DIRECTORY/md5.sum" __remove_files "$WORKING_DIRECTORY/upload/" - __remove_files "$WORKING_DIRECTORY/*.txt" - __remove_files "$WORKING_DIRECTORY/*.txt.gz" + __remove_from_rc_local + rm -f "$WORKING_DIRECTORY/*.txt" + rm -f "$WORKING_DIRECTORY/*.txt.gz" log INFO "Rulex has been uninstalled." } diff --git a/script/rulex-openwrt.sh b/script/rulex-openwrt.sh index 5655f402a..578b88037 100644 --- a/script/rulex-openwrt.sh +++ b/script/rulex-openwrt.sh @@ -114,9 +114,8 @@ uninstall() { __remove_files "$WORKING_DIRECTORY/LICENSE" __remove_files "$WORKING_DIRECTORY/md5.sum" __remove_files "$WORKING_DIRECTORY/upload/" - __remove_files "$WORKING_DIRECTORY/*.txt" - __remove_files "$WORKING_DIRECTORY/run-nohup-log.txt" - __remove_files "$WORKING_DIRECTORY/*.txt.gz" + rm -f "$WORKING_DIRECTORY/*.txt" + rm -f "$WORKING_DIRECTORY/*.txt.gz" log INFO "Rulex has been uninstalled." } diff --git a/script/rulex-systemctl.sh b/script/rulex-systemctl.sh index 44c2e440e..2ce59ce99 100644 --- a/script/rulex-systemctl.sh +++ b/script/rulex-systemctl.sh @@ -105,7 +105,8 @@ uninstall(){ remove_files $working_directory/upload/ remove_files $working_directory/license.key remove_files $working_directory/license.lic - remove_files $working_directory/*.txt.gz + rm -f "$WORKING_DIRECTORY/*.txt" + rm -f "$WORKING_DIRECTORY/*.txt.gz" systemctl daemon-reload systemctl reset-failed echo "[√] Rulex has been uninstalled." diff --git a/test/conf/rulex.ini b/test/conf/rulex.ini index f3af4f3f3..e97dac83c 100644 --- a/test/conf/rulex.ini +++ b/test/conf/rulex.ini @@ -36,9 +36,9 @@ log_path = rulex-log.txt # lua_log_path = rulex-lua-log.txt # -# Max data cache size, default is 50MB +# Max data cache size # -max_queue_size = 52428800 +max_queue_size = 20971520 # # Max store size, default is 20MB # diff --git a/typex/version.go b/typex/version.go index 1c152938d..208f2789b 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-23 22:39:29", + ReleaseTime: "2023-11-24 10:55:37", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 445011386a613e693ffebef6d58182220422a777 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 24 Nov 2023 18:31:27 +0800 Subject: [PATCH 056/138] dev: enhance daemon --- main.go | 76 ++++++++--------- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 31 ++++++- script/rulex-daemon.sh | 97 +++++++++++++--------- script/rulex-openwrt.sh | 10 +-- typex/version.go | 2 +- 5 files changed, 130 insertions(+), 86 deletions(-) diff --git a/main.go b/main.go index 427d071cf..c2601e0c4 100644 --- a/main.go +++ b/main.go @@ -3,16 +3,17 @@ package main import ( "context" "fmt" - "github.com/hootrhino/rulex/engine" - "github.com/hootrhino/rulex/ossupport" - "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" - "github.com/urfave/cli/v2" "log" _ "net/http/pprof" "os" "runtime" "time" + + "github.com/hootrhino/rulex/engine" + "github.com/hootrhino/rulex/ossupport" + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" + "github.com/urfave/cli/v2" ) func init() { @@ -69,49 +70,46 @@ func main() { Hidden: true, Usage: "! JUST FOR Upgrade FirmWare", Flags: []cli.Flag{ - &cli.IntFlag{ - Name: "oldpid", + &cli.BoolFlag{ + Name: "upgrade", Usage: "! THIS PARAMENT IS JUST FOR Upgrade FirmWare", - Value: -1, + Value: false, }, }, Action: func(c *cli.Context) error { + if runtime.GOOS != "linux" { + fmt.Println("[RULEX UPGRADE] Only Support Linux") + return nil + } file, err := os.Create("./local-upgrade-log.txt") if err != nil { fmt.Println(err) - return err + return nil } defer file.Close() os.Stdout = file os.Stderr = file - OldPid := c.Int("oldpid") - fmt.Println("[RULEX UPGRADE] Updater Pid=", - os.Getpid(), "Gid=", os.Getegid(), " OldPid:", OldPid) - if OldPid < 0 { - fmt.Printf("[RULEX UPGRADE] Invalid OldPid:%d", OldPid) + if !c.Bool("upgrade") { + fmt.Println("[RULEX UPGRADE] Nothing todo") return nil } - // Try 5 times - killOld := true - fmt.Println("[RULEX UPGRADE] Try to kill Old Process:", OldPid) - if killOld { - // EEKITH3 Use SystemCtl manage RULEX - env := os.Getenv("ARCHSUPPORT") - if runtime.GOOS == "linux" { - fmt.Println("[RULEX UPGRADE] Ready to Upgrade on product:", env) - if err := ossupport.UnzipFirmware( - "/usr/local/upload/Firmware/Firmware.zip", - "/usr/local"); err != nil { - fmt.Println("[RULEX UPGRADE] Unzip error:", err) - return err - } - if err := ossupport.RestartRulex(); err != nil { - fmt.Println("[RULEX UPGRADE] Restart rulex error", err) - return err - } - fmt.Println("[RULEX UPGRADE] Restart rulex success, Upgrade Process Exited") - } + // unzip Firmware + if err := ossupport.UnzipFirmware( + "/usr/local/upload/Firmware/Firmware.zip", + "/usr/local"); err != nil { + fmt.Println("[RULEX UPGRADE] Unzip error:", err) + return nil + } + if err := ossupport.RestartRulex(); err != nil { + fmt.Println("[RULEX UPGRADE] Restart rulex error", err) + return nil } + // Remove old package + if err := os.Remove("/usr/local/upload/Firmware/Firmware.zip"); err != nil { + fmt.Println("[RULEX UPGRADE] Restart rulex error", err) + return nil + } + fmt.Println("[RULEX UPGRADE] Restart rulex success, Upgrade Process Exited") os.Exit(0) return nil }, @@ -129,10 +127,14 @@ func main() { }, }, Action: func(c *cli.Context) error { - file, err := os.Create("./local-recover-log.txt") + if runtime.GOOS != "linux" { + fmt.Println("[DATA RECOVER] Only Support Linux") + return nil + } + file, err := os.Create("./rulex-recover-log.txt") if err != nil { fmt.Println(err) - return err + return nil } defer file.Close() os.Stdout = file @@ -219,7 +221,7 @@ func main() { Action: func(*cli.Context) error { version := fmt.Sprintf("[%v-%v-%v]", runtime.GOOS, runtime.GOARCH, typex.DefaultVersion.Version) - fmt.Println("[*] Current Version: " + version) + fmt.Println("[*] Rulex Version: " + version) return nil }, }, diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index 7b637afe8..5766eae7b 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -58,12 +58,17 @@ func RestartRulex() error { * * 恢复上传的DB 1 停止RULEX -2 删除DB -3 复制DB过去 -4 重启 +2 删除老DB +3 复制新DB到路径 +3 删除PID,停止守护进程 +4 重启(脚本会新建PID) - path: /usr/local/rulex, args: recover=true * */ +func fileExists(filename string) bool { + _, err := os.Stat(filename) + return !os.IsNotExist(err) +} func StartRecoverProcess() { cmd := exec.Command("./rulex", "recover", "-recover=true") cmd.SysProcAttr = NewSysProcAttr() @@ -74,6 +79,15 @@ func StartRecoverProcess() { return } log.Printf("Start Recover Process Pid=%d, Cmd:%s\n", cmd.Process.Pid, cmd.String()) + fmt.Println("Remove Old Pid File") + pidFile := "/var/run/rulex.pid" + if fileExists(pidFile) { + if err := os.Remove(pidFile); err != nil { + fmt.Println("Remove Old Pid File error:", err) + return + } + } + fmt.Println("Remove Old Pid File Finished") log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } @@ -84,7 +98,7 @@ func StartRecoverProcess() { * */ func StartUpgradeProcess() { - cmd := exec.Command("./rulex", "upgrade", "-oldpid=", fmt.Sprintf("%d", os.Getpid())) + cmd := exec.Command("./rulex", "upgrade", "-upgrade=", "true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() err := cmd.Start() @@ -93,6 +107,15 @@ func StartUpgradeProcess() { return } log.Printf("Start Upgrade Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) + fmt.Println("Remove Old Pid File") + pidFile := "/var/run/rulex.pid" + if fileExists(pidFile) { + if err := os.Remove(pidFile); err != nil { + fmt.Println("Remove Old Pid File error:", err) + return + } + } + fmt.Println("Remove Old Pid File Finished") log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index ca523cd92..c808947bb 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -10,16 +10,14 @@ # Description: Rulex Service ### END INIT INFO -EXECUTABLE_PATH="/usr/local/rulex" -CONFIG_PATH="/usr/local/rulex.ini" SERVICE_NAME="rulex" WORKING_DIRECTORY="/usr/local" -WAIT_TIME_SECONDS=3 -CHECK_INTERVAL_SECONDS=1 +EXECUTABLE_PATH="$WORKING_DIRECTORY/$SERVICE_NAME" +CONFIG_PATH="$WORKING_DIRECTORY/$SERVICE_NAME.ini" + PID_FILE="/var/run/$SERVICE_NAME.pid" -service_file="/etc/init.d/rulex.sh" PID_FILE="/var/run/rulex.pid" -service_file="/etc/init.d/rulex.service" +SERVICE_FILE="/etc/init.d/rulex.service" log() { local level=$1 shift @@ -29,17 +27,15 @@ log() { install(){ local source_dir="$PWD" - local executable="/usr/local/rulex" - local config_file="/usr/local/rulex.ini" local db_file="/usr/local/rulex.db" -cat > "$service_file" << EOL +cat > "$SERVICE_FILE" << EOL #!/bin/sh # Create Time: $(date +'%Y-%m-%d %H:%M:%S') WORKING_DIRECTORY="/usr/local" PID_FILE="/var/run/rulex.pid" -executable="/usr/local/rulex" -config_file="/usr/local/rulex.ini" +EXECUTABLE_PATH="\$WORKING_DIRECTORY/rulex" +CONFIG_PATH="\$WORKING_DIRECTORY/rulex.ini" log() { local level=\$1 @@ -48,19 +44,23 @@ log() { } start() { - log INFO "Starting rulex..." + pid=\$(pgrep -x -n "rulex") + if [ -n "\$pid" ]; then + log INFO "rulex is running with Pid:\${pid}" + exit 0 + fi + log INFO "Starting rulex." cd \$WORKING_DIRECTORY - nohup \$executable run -config=\$config_file > run-nohup-log.txt 2>&1 & echo \$! > "\$PID_FILE" + daemon > rulex-daemon-log.txt 2>&1 & log INFO "Starting rulex Finished" } stop() { - # Check if rulex process is running - if pgrep -x "rulex" > /dev/null; then - pid=\$(pgrep -x "rulex") - log INFO "Killing rulex process with PID \$pid" + if pgrep -x -n "rulex" > /dev/null; then + pid=\$(pgrep -x -n "rulex") kill "\$pid" + log INFO "Killing rulex process with PID \$pid" else log INFO "rulex process is not running." fi @@ -72,8 +72,8 @@ restart() { } status() { - log INFO "Checking rulex status..." - pid=\$(pgrep -x "rulex") + log INFO "Checking rulex status." + pid=\$(pgrep -x -n "rulex") if [ -n "\$pid" ]; then log INFO "rulex is running with Pid:\${pid}" else @@ -81,6 +81,18 @@ status() { fi } +daemon(){ + while true; do + $EXECUTABLE_PATH run -config=\$CONFIG_PATH + wait \$! + sleep 5 + if [ ! -f "\$PID_FILE" ]; then + log INFO "Pid File Remove detected, RULEX Daemon Exit." + exit 0 + fi + done +} + case "\$1" in start) start @@ -105,12 +117,19 @@ EOL mkdir -p $WORKING_DIRECTORY chmod +x $source_dir/rulex - cp -rfp "$source_dir/rulex" "$executable" - cp -rfp "$source_dir/rulex.ini" "$config_file" + log INFO "Copy rulex to $WORKING_DIRECTORY" + cp -rfp "$source_dir/rulex" "$EXECUTABLE_PATH" + + log INFO "Copy rulex.ini to $WORKING_DIRECTORY" + cp -rfp "$source_dir/rulex.ini" "$CONFIG_PATH" + + log INFO "Copy license.lic to $WORKING_DIRECTORY" cp -rfp "$source_dir/license.lic" "$WORKING_DIRECTORY/" + + log INFO "Copy license.key to $WORKING_DIRECTORY" cp -rfp "$source_dir/license.key" "$WORKING_DIRECTORY/" __add_to_rc_local - chmod 777 $service_file + chmod 777 $SERVICE_FILE if [ $? -eq 0 ]; then log INFO "Rulex service has been created and extracted." else @@ -121,7 +140,7 @@ EOL __remove_files() { local file=$1 - log INFO "Removing $file..." + log INFO "Removing $file." if [ -e "$file" ]; then if [ -d "$file" ]; then rm -rf "$file" @@ -139,11 +158,11 @@ __remove_from_rc_local() { log ERROR "Error: /etc/rc.local does not exist. Check your system configuration." return 1 fi - if ! grep -qF "$service_file start" "$rc_local_path"; then + if ! grep -qF "$SERVICE_FILE start" "$rc_local_path"; then log INFO "Script not found in /etc/rc.local. No changes made." return 0 fi - sed -i "\|$service_file start|d" "$rc_local_path" + sed -i "\|$SERVICE_FILE start|d" "$rc_local_path" log INFO "Script removed from /etc/rc.local." return 0 } @@ -154,54 +173,54 @@ __add_to_rc_local() { log INFO "Error: /etc/rc.local does not exist. Create the file manually or check your system configuration." return 1 fi - if grep -qF "$service_file start" "$rc_local_path"; then + if grep -qF "$SERVICE_FILE start" "$rc_local_path"; then log INFO "Script already present in /etc/rc.local. No changes made." return 0 fi local last_line_number=$(awk '/^[^#[:space:]]/{n=$0} END{print NR}' "$rc_local_path") if [ -n "$last_line_number" ]; then - sed -i "${last_line_number}i $service_file start" "$rc_local_path" + sed -i "${last_line_number}i $SERVICE_FILE start" "$rc_local_path" else - echo "$service_file start" >> "$rc_local_path" + echo "$SERVICE_FILE start" >> "$rc_local_path" fi log INFO "Script added to /etc/rc.local." return 0 } uninstall(){ - if [ -e "$service_file" ]; then - $service_file stop + if [ -e "$SERVICE_FILE" ]; then + $SERVICE_FILE stop fi - __remove_files $service_file + __remove_files "$PID_FILE" + __remove_files "$SERVICE_FILE" __remove_files "$WORKING_DIRECTORY/rulex" __remove_files "$WORKING_DIRECTORY/rulex.ini" __remove_files "$WORKING_DIRECTORY/rulex.db" __remove_files "$WORKING_DIRECTORY/license.lic" __remove_files "$WORKING_DIRECTORY/license.key" __remove_files "$WORKING_DIRECTORY/RULEX_INTERNAL_DATACENTER.db" - __remove_files "$WORKING_DIRECTORY/LICENSE" - __remove_files "$WORKING_DIRECTORY/md5.sum" __remove_files "$WORKING_DIRECTORY/upload/" + __remove_files "$WORKING_DIRECTORY/rulex-nohup-log.txt" + __remove_files "$WORKING_DIRECTORY/rulexlog.txt" + __remove_files "$WORKING_DIRECTORY/rulex-recover-log.txt" __remove_from_rc_local - rm -f "$WORKING_DIRECTORY/*.txt" - rm -f "$WORKING_DIRECTORY/*.txt.gz" log INFO "Rulex has been uninstalled." } start() { - $service_file start + $SERVICE_FILE start } restart() { - $service_file restart + $SERVICE_FILE restart } stop() { - $service_file stop + $SERVICE_FILE stop } status() { - $service_file status + $SERVICE_FILE status } case "$1" in diff --git a/script/rulex-openwrt.sh b/script/rulex-openwrt.sh index 578b88037..5d7bee3c2 100644 --- a/script/rulex-openwrt.sh +++ b/script/rulex-openwrt.sh @@ -55,10 +55,10 @@ restart() { } status() { - log INFO "Checking rulex status..." - pid=$(pgrep -x "rulex") - if [ -n "$pid" ]; then - log INFO "rulex is running with Pid:${pid}" + log INFO "Checking rulex status." + pid=\$(pgrep -x -n "rulex") + if [ -n "\$pid" ]; then + log INFO "rulex is running with Pid:\${pid}" else log INFO "rulex is not running." fi @@ -132,7 +132,7 @@ stop() { } status() { - $service_file running + $service_file status } main() { diff --git a/typex/version.go b/typex/version.go index 208f2789b..877a83c5d 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-24 10:55:37", + ReleaseTime: "2023-11-24 17:46:14", } var Banner = ` ** Welcome to RULEX framework world <'_'> From bfa51fd751349aec61bc210ec5a3f3636a08b130 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 24 Nov 2023 19:17:30 +0800 Subject: [PATCH 057/138] fix: fix daemon failed --- main.go | 1 + ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 40 ++++++++++++---------- script/rulex-daemon.sh | 2 +- typex/version.go | 2 +- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/main.go b/main.go index c2601e0c4..4519c6d61 100644 --- a/main.go +++ b/main.go @@ -159,6 +159,7 @@ func main() { fmt.Println("[DATA RECOVER] Try to Restart rulex") if err := ossupport.RestartRulex(); err != nil { fmt.Println("[DATA RECOVER] Restart rulex error", err) + os.Exit(0) return nil } fmt.Println("[DATA RECOVER] Restart rulex success, Recover Process Exited") diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index 5766eae7b..b258a93f7 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -21,6 +21,7 @@ import ( "os" "os/exec" "path/filepath" + "time" ) /* @@ -65,11 +66,29 @@ func RestartRulex() error { - path: /usr/local/rulex, args: recover=true * */ -func fileExists(filename string) bool { +func FileExists(filename string) bool { _, err := os.Stat(filename) return !os.IsNotExist(err) } + +/* +* +* 数据备份 +* + */ func StartRecoverProcess() { + // rm pid file + fmt.Println("Remove Old Pid File") + pidFile := "/var/run/rulex.pid" + if FileExists(pidFile) { + if err := os.Remove(pidFile); err != nil { + log.Println("Remove Old Pid File error:", err) + return + } + } + time.Sleep(3 * time.Second) // Wait Daemon Exit + log.Println("Remove Old Pid File Finished") + // Cmd cmd := exec.Command("./rulex", "recover", "-recover=true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() @@ -78,16 +97,8 @@ func StartRecoverProcess() { log.Println("Start Recover Process Failed:", err) return } + log.Printf("Start Recover Process Pid=%d, Cmd:%s\n", cmd.Process.Pid, cmd.String()) - fmt.Println("Remove Old Pid File") - pidFile := "/var/run/rulex.pid" - if fileExists(pidFile) { - if err := os.Remove(pidFile); err != nil { - fmt.Println("Remove Old Pid File error:", err) - return - } - } - fmt.Println("Remove Old Pid File Finished") log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } @@ -107,15 +118,6 @@ func StartUpgradeProcess() { return } log.Printf("Start Upgrade Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) - fmt.Println("Remove Old Pid File") - pidFile := "/var/run/rulex.pid" - if fileExists(pidFile) { - if err := os.Remove(pidFile); err != nil { - fmt.Println("Remove Old Pid File error:", err) - return - } - } - fmt.Println("Remove Old Pid File Finished") log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index c808947bb..e7357539c 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -85,7 +85,7 @@ daemon(){ while true; do $EXECUTABLE_PATH run -config=\$CONFIG_PATH wait \$! - sleep 5 + sleep 3 if [ ! -f "\$PID_FILE" ]; then log INFO "Pid File Remove detected, RULEX Daemon Exit." exit 0 diff --git a/typex/version.go b/typex/version.go index 877a83c5d..7720b003e 100644 --- a/typex/version.go +++ b/typex/version.go @@ -12,7 +12,7 @@ type Version struct { var DefaultVersion = Version{ Version: `v0.6.4`, - ReleaseTime: "2023-11-24 17:46:14", + ReleaseTime: "2023-11-24 18:32:27", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 542a985b5a22b07815bfbc9e88c80ba2aa527453 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 25 Nov 2023 17:50:08 +0800 Subject: [PATCH 058/138] dev: fix daemon failed --- gen_info.sh | 2 + main.go | 14 ++++++ plugin/rulex_api_server/apis/system_api.go | 36 +------------- .../service/hw_intrerface_service.go | 40 ++++++++-------- script/rulex-daemon.sh | 48 +++++++++++-------- typex/version.go | 4 +- 6 files changed, 68 insertions(+), 76 deletions(-) diff --git a/gen_info.sh b/gen_info.sh index 17c959394..d2b57f592 100644 --- a/gen_info.sh +++ b/gen_info.sh @@ -15,10 +15,12 @@ type Version struct { Version string ReleaseTime string Arch string + Product string Dist string } var DefaultVersion = Version{ + Product: "COMMON", Version: \`${VERSION}\`, ReleaseTime: "$(echo $(date "+%Y-%m-%d %H:%M:%S"))", } diff --git a/main.go b/main.go index 4519c6d61..47180d086 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,7 @@ import ( ) func init() { + go func() { for { select { @@ -28,6 +29,19 @@ func init() { } } }() + env := os.Getenv("ARCHSUPPORT") + if env == "EEKITT507" { + typex.DefaultVersion.Product = env + } + if env == "EEKITH3" { + typex.DefaultVersion.Product = env + } + if env == "WKYS805" { + typex.DefaultVersion.Product = env + } + if env == "RPI4B" { + typex.DefaultVersion.Product = env + } dist, err := utils.GetOSDistribution() if err != nil { panic(err) diff --git a/plugin/rulex_api_server/apis/system_api.go b/plugin/rulex_api_server/apis/system_api.go index 732e53d6b..82d50047f 100644 --- a/plugin/rulex_api_server/apis/system_api.go +++ b/plugin/rulex_api_server/apis/system_api.go @@ -116,6 +116,7 @@ func System(c *gin.Context, ruleEngine typex.RuleX) { "cpuPercent": calculateCpuPercent(cpuPercent), "osArch": ruleEngine.Version().Arch, "osDist": ruleEngine.Version().Dist, + "product": typex.DefaultVersion.Product, "startedAt": __StartedAt, "osUpTime": func() string { result, err := ossupport.GetUptime() @@ -270,40 +271,7 @@ func GetUarts(c *gin.Context, ruleEngine typex.RuleX) { * */ func GetUartList(c *gin.Context, ruleEngine typex.RuleX) { - ports, _ := serial.GetPortsList() - List := []map[string]interface{}{} - for _, port := range ports { - // 明确知道有这么多端口,啰嗦代码是为了标记以免以后忘记 - if port == "/dev/ttyS0" { - continue - } - if port == "/dev/ttyS3" { - continue - } - if port == "/dev/ttyUSB0" { - continue - } - if port == "/dev/ttyUSB1" { - continue - } - if port == "/dev/ttyUSB2" { - continue - } - - List = append(List, map[string]interface{}{ - "port": port, - "alias": func(port string) string { - if port == "/dev/ttyS1" { - return "RS4851(A1B1)" - } - if port == "/dev/ttyS2" { - return "RS4851(A2B2)" - } - return port - }(port)}) - - } - c.JSON(common.HTTP_OK, common.OkWithData(List)) + c.JSON(common.HTTP_OK, common.OkWithData(service.GetOsPort())) } /* diff --git a/plugin/rulex_api_server/service/hw_intrerface_service.go b/plugin/rulex_api_server/service/hw_intrerface_service.go index 2e1f2336d..8c65d8003 100644 --- a/plugin/rulex_api_server/service/hw_intrerface_service.go +++ b/plugin/rulex_api_server/service/hw_intrerface_service.go @@ -22,6 +22,7 @@ import ( "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/ossupport" "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/typex" "go.bug.st/serial" ) @@ -94,7 +95,7 @@ func GetHwPortConfig(uuid string) (model.MHwPort, error) { * */ func InitHwPortConfig() error { - for _, portName := range getOsPort() { + for _, portName := range GetOsPort() { Port := model.MHwPort{ UUID: portName, Name: portName, @@ -130,7 +131,7 @@ func InitHwPortConfig() error { * 获取系统串口 * */ -func getOsPort() []string { +func GetOsPort() []string { var ports []string if runtime.GOOS == "windows" { ports, _ = serial.GetPortsList() @@ -139,24 +140,23 @@ func getOsPort() []string { } List := []string{} for _, port := range ports { - // 明确知道有这么多端口是被占用的,啰嗦代码是为了标记以免以后忘记 - if port == "COM0" { - continue - } - if port == "/dev/ttyS0" { - continue - } - if port == "/dev/ttyS3" { - continue - } - if port == "/dev/ttyUSB0" { - continue - } - if port == "/dev/ttyUSB1" { - continue - } - if port == "/dev/ttyUSB2" { - continue + if typex.DefaultVersion.Product == "EEKIIH3" { + // H3的下列串口被网卡占用 + if port == "/dev/ttyS0" { + continue + } + if port == "/dev/ttyS3" { + continue + } + if port == "/dev/ttyUSB0" { + continue + } + if port == "/dev/ttyUSB1" { + continue + } + if port == "/dev/ttyUSB2" { + continue + } } List = append(List, port) } diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index e7357539c..7d53bb169 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -16,15 +16,14 @@ EXECUTABLE_PATH="$WORKING_DIRECTORY/$SERVICE_NAME" CONFIG_PATH="$WORKING_DIRECTORY/$SERVICE_NAME.ini" PID_FILE="/var/run/$SERVICE_NAME.pid" -PID_FILE="/var/run/rulex.pid" -SERVICE_FILE="/etc/init.d/rulex.service" +SERVICE_FILE="/etc/init.d/$SERVICE_NAME.service" + log() { local level=$1 shift echo "[$level] $(date +'%Y-%m-%d %H:%M:%S') - $@" } - install(){ local source_dir="$PWD" local db_file="/usr/local/rulex.db" @@ -44,30 +43,34 @@ log() { } start() { - pid=\$(pgrep -x -n "rulex") + pid=\$(pgrep -x -n -f "/usr/local/rulex run -config=/usr/local/rulex.ini") if [ -n "\$pid" ]; then log INFO "rulex is running with Pid:\${pid}" exit 0 fi log INFO "Starting rulex." - cd \$WORKING_DIRECTORY - echo \$! > "\$PID_FILE" - daemon > rulex-daemon-log.txt 2>&1 & - log INFO "Starting rulex Finished" + $EXECUTABLE_PATH run -config=$CONFIG_PATH & + echo "\$!" > "\$PID_FILE" + log INFO "rulex started with PID \$(cat "\$PID_FILE")." + daemon } stop() { - if pgrep -x -n "rulex" > /dev/null; then - pid=\$(pgrep -x -n "rulex") + if [ -f "$PID_FILE" ]; then + pid=\$(cat "$PID_FILE") + log INFO "Stopping rulex process with PID \$pid." kill "\$pid" - log INFO "Killing rulex process with PID \$pid" + wait "\$pid" + rm "$PID_FILE" + log INFO "rulex process with PID \$pid stopped." else - log INFO "rulex process is not running." + log INFO "PID file $PID_FILE not found. No rulex process to stop." fi } restart() { stop + sleep 1 start } @@ -81,15 +84,18 @@ status() { fi } -daemon(){ +daemon() { while true; do - $EXECUTABLE_PATH run -config=\$CONFIG_PATH - wait \$! - sleep 3 - if [ ! -f "\$PID_FILE" ]; then - log INFO "Pid File Remove detected, RULEX Daemon Exit." + if [ ! -f "$PID_FILE" ]; then + log INFO "PID file $PID_FILE not found. Exiting." exit 0 fi + pid=\$(cat "$PID_FILE") + if ! pgrep -x "rulex" > /dev/null; then + log INFO "Detected that rulex process is not running. Restarting..." + $EXECUTABLE_PATH run -config=$CONFIG_PATH & + fi + sleep 5 done } @@ -98,8 +104,7 @@ case "\$1" in start ;; restart) - stop - start + restart ;; stop) stop @@ -200,9 +205,10 @@ uninstall(){ __remove_files "$WORKING_DIRECTORY/license.key" __remove_files "$WORKING_DIRECTORY/RULEX_INTERNAL_DATACENTER.db" __remove_files "$WORKING_DIRECTORY/upload/" - __remove_files "$WORKING_DIRECTORY/rulex-nohup-log.txt" + __remove_files "$WORKING_DIRECTORY/rulex-daemon-log.txt" __remove_files "$WORKING_DIRECTORY/rulexlog.txt" __remove_files "$WORKING_DIRECTORY/rulex-recover-log.txt" + __remove_files "$WORKING_DIRECTORY/rulex-upgrade-log.txt" __remove_from_rc_local log INFO "Rulex has been uninstalled." } diff --git a/typex/version.go b/typex/version.go index 7720b003e..1cabbbf27 100644 --- a/typex/version.go +++ b/typex/version.go @@ -7,12 +7,14 @@ type Version struct { Version string ReleaseTime string Arch string + Product string Dist string } var DefaultVersion = Version{ + Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-24 18:32:27", + ReleaseTime: "2023-11-25 16:03:59", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 0a02a4419b6237f44cd3f3964f8a9fb79375a455 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 26 Nov 2023 18:15:06 +0800 Subject: [PATCH 059/138] fix: fix recover loop failed --- main.go | 5 ++--- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 7 +++++-- script/rulex-daemon.sh | 16 +++++++++++++--- typex/version.go | 2 +- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/main.go b/main.go index 47180d086..4fb2d5470 100644 --- a/main.go +++ b/main.go @@ -173,10 +173,9 @@ func main() { fmt.Println("[DATA RECOVER] Try to Restart rulex") if err := ossupport.RestartRulex(); err != nil { fmt.Println("[DATA RECOVER] Restart rulex error", err) - os.Exit(0) - return nil + } else { + fmt.Println("[DATA RECOVER] Restart rulex success, Recover Process Exited") } - fmt.Println("[DATA RECOVER] Restart rulex success, Recover Process Exited") os.Exit(0) return nil }, diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index b258a93f7..9f0f46e39 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -48,9 +48,12 @@ func StopRulex() error { */ func RestartRulex() error { cmd := exec.Command("/etc/init.d/rulex.service", "restart") - out, err := cmd.CombinedOutput() + cmd.SysProcAttr = NewSysProcAttr() + cmd.Env = os.Environ() + err := cmd.Start() if err != nil { - return fmt.Errorf("%s,%s", err, string(out)) + log.Println("Restart Rulex Failed:", err) + return err } return nil } diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index 7d53bb169..77d0f5da5 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -49,7 +49,7 @@ start() { exit 0 fi log INFO "Starting rulex." - $EXECUTABLE_PATH run -config=$CONFIG_PATH & + $EXECUTABLE_PATH run -config=$CONFIG_PATH > rulex-daemon-log.txt& echo "\$!" > "\$PID_FILE" log INFO "rulex started with PID \$(cat "\$PID_FILE")." daemon @@ -84,16 +84,26 @@ status() { fi } + daemon() { + sleep 1 + local old_pid=\$(cat "$PID_FILE") while true; do if [ ! -f "$PID_FILE" ]; then log INFO "PID file $PID_FILE not found. Exiting." exit 0 fi - pid=\$(cat "$PID_FILE") + new_pid=\$(cat "$PID_FILE") + if [ "\$old_pid" != "\$new_pid" ]; then + log INFO "$PID_FILE value changed. Exiting." + exit 0 + fi if ! pgrep -x "rulex" > /dev/null; then log INFO "Detected that rulex process is not running. Restarting..." - $EXECUTABLE_PATH run -config=$CONFIG_PATH & + $EXECUTABLE_PATH run -config=$CONFIG_PATH > rulex-daemon-log.txt & + sleep 5 + old_pid=\$(cat "$PID_FILE") + continue fi sleep 5 done diff --git a/typex/version.go b/typex/version.go index 1cabbbf27..153426996 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,7 +14,7 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-25 16:03:59", + ReleaseTime: "2023-11-26 17:55:43", } var Banner = ` ** Welcome to RULEX framework world <'_'> From ae60035ecd54c26ad8841929c3c0155323ba71ed Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 26 Nov 2023 20:26:34 +0800 Subject: [PATCH 060/138] dev: add upgrade lock --- main.go | 10 +++++++ script/rulex-daemon.sh | 61 ++++++++++++++++++------------------------ 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/main.go b/main.go index 4fb2d5470..87f368992 100644 --- a/main.go +++ b/main.go @@ -171,11 +171,21 @@ func main() { } fmt.Println("[DATA RECOVER] Move New Db File Finished") fmt.Println("[DATA RECOVER] Try to Restart rulex") + // upgrade lock + if err := os.WriteFile("/var/run/rulex-upgrade.lock", []byte{48}, 0755); err != nil { + fmt.Println("[DATA RECOVER] Write Recover Lock File error:", err) + return nil + } if err := ossupport.RestartRulex(); err != nil { fmt.Println("[DATA RECOVER] Restart rulex error", err) } else { fmt.Println("[DATA RECOVER] Restart rulex success, Recover Process Exited") } + // upgrade lock + if err := os.Remove("/var/run/rulex-upgrade.lock"); err != nil { + fmt.Println("[DATA RECOVER] Remove Recover Lock File error:", err) + return nil + } os.Exit(0) return nil }, diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index 77d0f5da5..b521b6430 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -18,6 +18,9 @@ CONFIG_PATH="$WORKING_DIRECTORY/$SERVICE_NAME.ini" PID_FILE="/var/run/$SERVICE_NAME.pid" SERVICE_FILE="/etc/init.d/$SERVICE_NAME.service" +STOP_SIGNAL="/var/run/rulex-stop.sinal" +UPGRADE_SIGNAL="/var/run/rulex-upgrade.lock" + log() { local level=$1 shift @@ -43,28 +46,23 @@ log() { } start() { - pid=\$(pgrep -x -n -f "/usr/local/rulex run -config=/usr/local/rulex.ini") + rm -f $STOP_SIGNAL + pid=\$(pgrep -x -n -f "$EXECUTABLE_PATH run -config=$CONFIG_PATH") if [ -n "\$pid" ]; then log INFO "rulex is running with Pid:\${pid}" exit 0 fi - log INFO "Starting rulex." - $EXECUTABLE_PATH run -config=$CONFIG_PATH > rulex-daemon-log.txt& - echo "\$!" > "\$PID_FILE" - log INFO "rulex started with PID \$(cat "\$PID_FILE")." - daemon + daemon& } stop() { - if [ -f "$PID_FILE" ]; then - pid=\$(cat "$PID_FILE") - log INFO "Stopping rulex process with PID \$pid." - kill "\$pid" - wait "\$pid" - rm "$PID_FILE" - log INFO "rulex process with PID \$pid stopped." + echo "1" > $STOP_SIGNAL + if pgrep -x "rulex" > /dev/null; then + log INFO "rulex process is running. Killing it..." + pkill -x "rulex" + log INFO "rulex process has been killed." else - log INFO "PID file $PID_FILE not found. No rulex process to stop." + log WARNING "rulex process is not running." fi } @@ -84,28 +82,22 @@ status() { fi } - daemon() { - sleep 1 - local old_pid=\$(cat "$PID_FILE") while true; do - if [ ! -f "$PID_FILE" ]; then - log INFO "PID file $PID_FILE not found. Exiting." - exit 0 - fi - new_pid=\$(cat "$PID_FILE") - if [ "\$old_pid" != "\$new_pid" ]; then - log INFO "$PID_FILE value changed. Exiting." - exit 0 - fi if ! pgrep -x "rulex" > /dev/null; then - log INFO "Detected that rulex process is not running. Restarting..." - $EXECUTABLE_PATH run -config=$CONFIG_PATH > rulex-daemon-log.txt & - sleep 5 - old_pid=\$(cat "$PID_FILE") - continue + if [ -e "$UPGRADE_SIGNAL" ]; then + log INFO "File $UPGRADE_SIGNAL exists. May upgrade now." + elif [ -e "$STOP_SIGNAL" ]; then + log INFO "$STOP_SIGNAL file found. Exiting." + exit 0 + else + log WARNING "Detected that rulex process is interrupted. Restarting..." + $EXECUTABLE_PATH run -config=$CONFIG_PATH > rulex-daemon-log.txt + wait $! + log WARNING "Detected that rulex process is interrupted" + fi fi - sleep 5 + sleep 4 done } @@ -194,7 +186,7 @@ __add_to_rc_local() { fi local last_line_number=$(awk '/^[^#[:space:]]/{n=$0} END{print NR}' "$rc_local_path") if [ -n "$last_line_number" ]; then - sed -i "${last_line_number}i $SERVICE_FILE start" "$rc_local_path" + sed -i "${last_line_number}i $SERVICE_FILE start || true" "$rc_local_path" else echo "$SERVICE_FILE start" >> "$rc_local_path" fi @@ -206,7 +198,6 @@ uninstall(){ if [ -e "$SERVICE_FILE" ]; then $SERVICE_FILE stop fi - __remove_files "$PID_FILE" __remove_files "$SERVICE_FILE" __remove_files "$WORKING_DIRECTORY/rulex" __remove_files "$WORKING_DIRECTORY/rulex.ini" @@ -215,8 +206,8 @@ uninstall(){ __remove_files "$WORKING_DIRECTORY/license.key" __remove_files "$WORKING_DIRECTORY/RULEX_INTERNAL_DATACENTER.db" __remove_files "$WORKING_DIRECTORY/upload/" - __remove_files "$WORKING_DIRECTORY/rulex-daemon-log.txt" __remove_files "$WORKING_DIRECTORY/rulexlog.txt" + __remove_files "$WORKING_DIRECTORY/rulex-daemon-log.txt" __remove_files "$WORKING_DIRECTORY/rulex-recover-log.txt" __remove_files "$WORKING_DIRECTORY/rulex-upgrade-log.txt" __remove_from_rc_local From 0cc0c3111805f2aa4d2a5319beab8f201185d7b5 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 26 Nov 2023 20:34:59 +0800 Subject: [PATCH 061/138] dev: exit 0 --- script/rulex-daemon.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index b521b6430..580bd47e8 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -53,6 +53,7 @@ start() { exit 0 fi daemon& + exit 0 } stop() { From 58e7c7934466109f4f9f6368545e5d6baeed736c Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 27 Nov 2023 18:26:09 +0800 Subject: [PATCH 062/138] fix: fix daemon --- main.go | 25 ++++-- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 18 ---- script/rulex-daemon.sh | 77 ++++++------------ script/rulex-systemctl.sh | 40 +++------ test/data/daemon.sh | 95 ++++++++++++++++++++++ typex/version.go | 2 +- 6 files changed, 150 insertions(+), 107 deletions(-) create mode 100644 test/data/daemon.sh diff --git a/main.go b/main.go index 87f368992..f4b6fbd26 100644 --- a/main.go +++ b/main.go @@ -91,6 +91,18 @@ func main() { }, }, Action: func(c *cli.Context) error { + // upgrade lock + if err := os.WriteFile("/var/run/rulex-upgrade.lock", []byte{48}, 0755); err != nil { + fmt.Println("[DATA RECOVER] Write Recover Lock File error:", err) + return nil + } + defer func() { + // upgrade lock + if err := os.Remove("/var/run/rulex-upgrade.lock"); err != nil { + fmt.Println("[DATA RECOVER] Remove Recover Lock File error:", err) + return + } + }() if runtime.GOOS != "linux" { fmt.Println("[RULEX UPGRADE] Only Support Linux") return nil @@ -176,16 +188,19 @@ func main() { fmt.Println("[DATA RECOVER] Write Recover Lock File error:", err) return nil } + defer func() { + // upgrade lock + if err := os.Remove("/var/run/rulex-upgrade.lock"); err != nil { + fmt.Println("[DATA RECOVER] Remove Recover Lock File error:", err) + return + } + }() if err := ossupport.RestartRulex(); err != nil { fmt.Println("[DATA RECOVER] Restart rulex error", err) } else { fmt.Println("[DATA RECOVER] Restart rulex success, Recover Process Exited") } - // upgrade lock - if err := os.Remove("/var/run/rulex-upgrade.lock"); err != nil { - fmt.Println("[DATA RECOVER] Remove Recover Lock File error:", err) - return nil - } + os.Exit(0) return nil }, diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index 9f0f46e39..eafd1a81b 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -21,7 +21,6 @@ import ( "os" "os/exec" "path/filepath" - "time" ) /* @@ -80,18 +79,6 @@ func FileExists(filename string) bool { * */ func StartRecoverProcess() { - // rm pid file - fmt.Println("Remove Old Pid File") - pidFile := "/var/run/rulex.pid" - if FileExists(pidFile) { - if err := os.Remove(pidFile); err != nil { - log.Println("Remove Old Pid File error:", err) - return - } - } - time.Sleep(3 * time.Second) // Wait Daemon Exit - log.Println("Remove Old Pid File Finished") - // Cmd cmd := exec.Command("./rulex", "recover", "-recover=true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() @@ -100,9 +87,6 @@ func StartRecoverProcess() { log.Println("Start Recover Process Failed:", err) return } - - log.Printf("Start Recover Process Pid=%d, Cmd:%s\n", cmd.Process.Pid, cmd.String()) - log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } @@ -120,8 +104,6 @@ func StartUpgradeProcess() { log.Println("Start Upgrade Process Failed:", err) return } - log.Printf("Start Upgrade Process Pid=%d, Cmd:%s", cmd.Process.Pid, cmd.String()) - log.Println("Old Process Exited:", os.Getpid()) os.Exit(0) } diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index 580bd47e8..5143292a2 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -1,21 +1,10 @@ #!/bin/bash -### BEGIN INIT INFO -# Provides: rulex -# Required-Start: $network $local_fs $remote_fs -# Required-Stop: $network $local_fs $remote_fs -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: Rulex Service -# Description: Rulex Service -### END INIT INFO - SERVICE_NAME="rulex" WORKING_DIRECTORY="/usr/local" EXECUTABLE_PATH="$WORKING_DIRECTORY/$SERVICE_NAME" CONFIG_PATH="$WORKING_DIRECTORY/$SERVICE_NAME.ini" -PID_FILE="/var/run/$SERVICE_NAME.pid" SERVICE_FILE="/etc/init.d/$SERVICE_NAME.service" STOP_SIGNAL="/var/run/rulex-stop.sinal" @@ -32,10 +21,20 @@ install(){ local db_file="/usr/local/rulex.db" cat > "$SERVICE_FILE" << EOL #!/bin/sh -# Create Time: $(date +'%Y-%m-%d %H:%M:%S') +### BEGIN INIT INFO +# Provides: rulex +# Required-Start: \$network \$local_fs \$remote_fs +# Required-Stop: \$network \$local_fs \$remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Rulex Service +# Description: Rulex Service +### END INIT INFO + + +# Create Time: $(date +'%Y-%m-%d %H:%M:%S') WORKING_DIRECTORY="/usr/local" -PID_FILE="/var/run/rulex.pid" EXECUTABLE_PATH="\$WORKING_DIRECTORY/rulex" CONFIG_PATH="\$WORKING_DIRECTORY/rulex.ini" @@ -52,8 +51,8 @@ start() { log INFO "rulex is running with Pid:\${pid}" exit 0 fi - daemon& - exit 0 + nohup $EXECUTABLE_PATH run -config=$CONFIG_PATH & + daemon } stop() { @@ -85,17 +84,23 @@ status() { daemon() { while true; do + if pgrep -x "rulex" > /dev/null; then + log INFO "rulex process exists" + sleep 3 + continue + fi if ! pgrep -x "rulex" > /dev/null; then if [ -e "$UPGRADE_SIGNAL" ]; then log INFO "File $UPGRADE_SIGNAL exists. May upgrade now." + sleep 2 + continue elif [ -e "$STOP_SIGNAL" ]; then log INFO "$STOP_SIGNAL file found. Exiting." exit 0 else log WARNING "Detected that rulex process is interrupted. Restarting..." - $EXECUTABLE_PATH run -config=$CONFIG_PATH > rulex-daemon-log.txt - wait $! - log WARNING "Detected that rulex process is interrupted" + nohup $EXECUTABLE_PATH run -config=$CONFIG_PATH & + log WARNING "Detected that rulex process has Restarted." fi fi sleep 4 @@ -136,7 +141,6 @@ EOL log INFO "Copy license.key to $WORKING_DIRECTORY" cp -rfp "$source_dir/license.key" "$WORKING_DIRECTORY/" - __add_to_rc_local chmod 777 $SERVICE_FILE if [ $? -eq 0 ]; then log INFO "Rulex service has been created and extracted." @@ -160,40 +164,6 @@ __remove_files() { log INFO "$file not found. No need to remove." fi } -__remove_from_rc_local() { - local rc_local_path="/etc/rc.local" - if [ ! -f "$rc_local_path" ]; then - log ERROR "Error: /etc/rc.local does not exist. Check your system configuration." - return 1 - fi - if ! grep -qF "$SERVICE_FILE start" "$rc_local_path"; then - log INFO "Script not found in /etc/rc.local. No changes made." - return 0 - fi - sed -i "\|$SERVICE_FILE start|d" "$rc_local_path" - log INFO "Script removed from /etc/rc.local." - return 0 -} - -__add_to_rc_local() { - local rc_local_path="/etc/rc.local" - if [ ! -f "$rc_local_path" ]; then - log INFO "Error: /etc/rc.local does not exist. Create the file manually or check your system configuration." - return 1 - fi - if grep -qF "$SERVICE_FILE start" "$rc_local_path"; then - log INFO "Script already present in /etc/rc.local. No changes made." - return 0 - fi - local last_line_number=$(awk '/^[^#[:space:]]/{n=$0} END{print NR}' "$rc_local_path") - if [ -n "$last_line_number" ]; then - sed -i "${last_line_number}i $SERVICE_FILE start || true" "$rc_local_path" - else - echo "$SERVICE_FILE start" >> "$rc_local_path" - fi - log INFO "Script added to /etc/rc.local." - return 0 -} uninstall(){ if [ -e "$SERVICE_FILE" ]; then @@ -211,7 +181,6 @@ uninstall(){ __remove_files "$WORKING_DIRECTORY/rulex-daemon-log.txt" __remove_files "$WORKING_DIRECTORY/rulex-recover-log.txt" __remove_files "$WORKING_DIRECTORY/rulex-upgrade-log.txt" - __remove_from_rc_local log INFO "Rulex has been uninstalled." } diff --git a/script/rulex-systemctl.sh b/script/rulex-systemctl.sh index 2ce59ce99..2cebed77b 100644 --- a/script/rulex-systemctl.sh +++ b/script/rulex-systemctl.sh @@ -22,7 +22,7 @@ install(){ local source_dir="$PWD" local service_file="/etc/systemd/system/rulex.service" local executable="/usr/local/rulex" - local working_directory="/usr/local/" + local WORKING_DIRECTORY="/usr/local/" local config_file="/usr/local/rulex.ini" local db_file="/usr/local/rulex.db" cat > "$service_file" << EOL @@ -32,8 +32,9 @@ After=network.target [Service] Environment="ARCHSUPPORT=EEKITH3" -WorkingDirectory=$working_directory +WorkingDirectory=$WORKING_DIRECTORY ExecStart=$executable run -config=$config_file -db=$db_file +ConditionPathExists=!/var/run/rulex-upgrade.lock Restart=always User=root Group=root @@ -43,9 +44,9 @@ RestartSec=5 WantedBy=multi-user.target EOL chmod +x $source_dir/rulex - echo "[.] Copy $source_dir/rulex to $working_directory." + echo "[.] Copy $source_dir/rulex to $WORKING_DIRECTORY." cp "$source_dir/rulex" "$executable" - echo "[.] Copy $source_dir/rulex.ini to $working_directory." + echo "[.] Copy $source_dir/rulex.ini to $WORKING_DIRECTORY." cp "$source_dir/rulex.ini" "$config_file" echo "[.] Copy $source_dir/license.key to /usr/local/license.key." cp "$source_dir/license.key" "/usr/local/license.key" @@ -94,40 +95,21 @@ remove_files() { } uninstall(){ - local working_directory="/usr/local" systemctl stop rulex systemctl disable rulex remove_files /etc/systemd/system/rulex.service - remove_files $working_directory/rulex - remove_files $working_directory/rulex.ini - remove_files $working_directory/rulex.db - remove_files $working_directory/*.txt - remove_files $working_directory/upload/ - remove_files $working_directory/license.key - remove_files $working_directory/license.lic + remove_files $WORKING_DIRECTORY/rulex + remove_files $WORKING_DIRECTORY/rulex.ini + remove_files $WORKING_DIRECTORY/rulex.db + remove_files $WORKING_DIRECTORY/upload/ + remove_files $WORKING_DIRECTORY/license.key + remove_files $WORKING_DIRECTORY/license.lic rm -f "$WORKING_DIRECTORY/*.txt" rm -f "$WORKING_DIRECTORY/*.txt.gz" systemctl daemon-reload systemctl reset-failed echo "[√] Rulex has been uninstalled." } - -# create a default user -create_user(){ - response=$(curl -X POST -H "Content-Type: application/json" -d '{ - "role": "admin", - "username": "admin", - "password": "admin", - "description": "system admin" - }' http://127.0.0.1:2580/api/v1/users -w "%{http_code}") - - if [ "$response" = "201" ]; then - echo "[√] User created" - else - echo "[x] User creation failed" - fi - -} # # # diff --git a/test/data/daemon.sh b/test/data/daemon.sh new file mode 100644 index 000000000..13e9bb1bd --- /dev/null +++ b/test/data/daemon.sh @@ -0,0 +1,95 @@ +#!/bin/sh +# Create Time: 2023-11-27 14:59:06 + +WORKING_DIRECTORY="/usr/local" +PID_FILE="/var/run/rulex.pid" +EXECUTABLE_PATH="$WORKING_DIRECTORY/rulex" +CONFIG_PATH="$WORKING_DIRECTORY/rulex.ini" + +log() { + local level=$1 + shift + echo "[$level] $(date +'%Y-%m-%d %H:%M:%S') - $@" +} + +start() { + rm -f /var/run/rulex-stop.sinal + pid=$(pgrep -x -n -f "/usr/local/rulex run -config=/usr/local/rulex.ini") + if [ -n "$pid" ]; then + log INFO "rulex is running with Pid:${pid}" + exit 0 + fi + daemon & + exit 0 +} + +stop() { + echo "1" > /var/run/rulex-stop.sinal + if pgrep -x "rulex" > /dev/null; then + log INFO "rulex process is running. Killing it..." + pkill -x "rulex" + log INFO "rulex process has been killed." + else + log WARNING "rulex process is not running." + fi +} + +restart() { + stop + sleep 1 + start +} + +status() { + log INFO "Checking rulex status." + pid=$(pgrep -x -n "rulex") + if [ -n "$pid" ]; then + log INFO "rulex is running with Pid:${pid}" + else + log INFO "rulex is not running." + fi +} + +daemon() { + while true; do + if pgrep -x "rulex" > /dev/null; then + sleep 3 + continue + fi + if ! pgrep -x "rulex" > /dev/null; then + if [ -e "/var/run/rulex-upgrade.lock" ]; then + log INFO "File /var/run/rulex-upgrade.lock exists. May upgrade now." + sleep 2 + continue + elif [ -e "/var/run/rulex-stop.sinal" ]; then + log INFO "/var/run/rulex-stop.sinal file found. Exiting." + exit 0 + else + log WARNING "Detected that rulex process is interrupted. Restarting..." + /usr/local/rulex run -config=/usr/local/rulex.ini + log WARNING "Detected that rulex process has Restarted." + fi + fi + sleep 4 + done +} + +case "$1" in + start) + start + ;; + restart) + restart + ;; + stop) + stop + ;; + status) + status + ;; + *) + log ERROR "Usage: $0 {start|restart|stop|status}" + exit 1 + ;; +esac + diff --git a/typex/version.go b/typex/version.go index 153426996..6cb069b04 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,7 +14,7 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-26 17:55:43", + ReleaseTime: "2023-11-27 15:34:51", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 36ec27d31f57c64e58242e2332edd55e6c19a32d Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 27 Nov 2023 23:14:45 +0800 Subject: [PATCH 063/138] dev: add daemon for common linux --- main.go | 103 +++++++++++++++++++++-------------------- script/rulex-daemon.sh | 29 ++++++------ typex/version.go | 2 +- utils/io_util.go | 13 ++++++ 4 files changed, 84 insertions(+), 63 deletions(-) diff --git a/main.go b/main.go index f4b6fbd26..ec22c8121 100644 --- a/main.go +++ b/main.go @@ -73,7 +73,7 @@ func main() { }, }, Action: func(c *cli.Context) error { - fmt.Println(typex.Banner) + utils.CLog(typex.Banner) engine.RunRulex(c.String("config")) fmt.Printf("[RULEX UPGRADE] Run rulex successfully.") return nil @@ -91,51 +91,54 @@ func main() { }, }, Action: func(c *cli.Context) error { + file, err := os.Create("./local-upgrade-log.txt") + if err != nil { + utils.CLog(err.Error()) + return nil + } + defer file.Close() + os.Stdout = file + os.Stderr = file // upgrade lock - if err := os.WriteFile("/var/run/rulex-upgrade.lock", []byte{48}, 0755); err != nil { - fmt.Println("[DATA RECOVER] Write Recover Lock File error:", err) + lockFile := "/var/run/rulex-upgrade.lock" + if err := os.WriteFile(lockFile, []byte{48} /*48 -> 0*/, 0755); err != nil { + utils.CLog("[DATA RECOVER] Write Recover Lock File error:%s", err.Error()) return nil } defer func() { // upgrade lock - if err := os.Remove("/var/run/rulex-upgrade.lock"); err != nil { - fmt.Println("[DATA RECOVER] Remove Recover Lock File error:", err) + if err := os.Remove(lockFile); err != nil { + utils.CLog("[DATA RECOVER] Remove Recover Lock File error:%s", err.Error()) return } + utils.CLog("[DATA RECOVER] Remove Recover Lock File Finished") }() if runtime.GOOS != "linux" { - fmt.Println("[RULEX UPGRADE] Only Support Linux") - return nil - } - file, err := os.Create("./local-upgrade-log.txt") - if err != nil { - fmt.Println(err) + utils.CLog("[RULEX UPGRADE] Only Support Linux") return nil } - defer file.Close() - os.Stdout = file - os.Stderr = file + if !c.Bool("upgrade") { - fmt.Println("[RULEX UPGRADE] Nothing todo") + utils.CLog("[RULEX UPGRADE] Nothing todo") return nil } // unzip Firmware if err := ossupport.UnzipFirmware( "/usr/local/upload/Firmware/Firmware.zip", "/usr/local"); err != nil { - fmt.Println("[RULEX UPGRADE] Unzip error:", err) + utils.CLog("[RULEX UPGRADE] Unzip error:%s", err.Error()) return nil } if err := ossupport.RestartRulex(); err != nil { - fmt.Println("[RULEX UPGRADE] Restart rulex error", err) + utils.CLog("[RULEX UPGRADE] Restart rulex error:%s", err.Error()) return nil } // Remove old package if err := os.Remove("/usr/local/upload/Firmware/Firmware.zip"); err != nil { - fmt.Println("[RULEX UPGRADE] Restart rulex error", err) + utils.CLog("[RULEX UPGRADE] Restart rulex error:%s", err.Error()) return nil } - fmt.Println("[RULEX UPGRADE] Restart rulex success, Upgrade Process Exited") + utils.CLog("[RULEX UPGRADE] Restart rulex success, Upgrade Process Exited") os.Exit(0) return nil }, @@ -153,54 +156,56 @@ func main() { }, }, Action: func(c *cli.Context) error { - if runtime.GOOS != "linux" { - fmt.Println("[DATA RECOVER] Only Support Linux") - return nil - } file, err := os.Create("./rulex-recover-log.txt") if err != nil { - fmt.Println(err) + utils.CLog(err.Error()) return nil } defer file.Close() os.Stdout = file os.Stderr = file + lockFile := "/var/run/rulex-upgrade.lock" + // upgrade lock + if err := os.WriteFile(lockFile, []byte{48}, 0755); err != nil { + utils.CLog("[DATA RECOVER] Write Recover Lock File error:%s", err.Error()) + return nil + } + defer func() { + // upgrade lock + if err := os.Remove(lockFile); err != nil { + utils.CLog("[DATA RECOVER] Remove Recover Lock File error:%s", err.Error()) + return + } + utils.CLog("[DATA RECOVER] Remove Recover Lock File Finished") + }() + if runtime.GOOS != "linux" { + utils.CLog("[DATA RECOVER] Only Support Linux") + return nil + } + if !c.Bool("recover") { - fmt.Println("[DATA RECOVER] Nothing todo") + utils.CLog("[DATA RECOVER] Nothing todo") return nil } - fmt.Println("[DATA RECOVER] Remove Old Db File") + utils.CLog("[DATA RECOVER] Remove Old Db File") if err := os.Remove("./rulex.db"); err != nil { - fmt.Println("[DATA RECOVER] Remove Old Db File error:", err) + utils.CLog("[DATA RECOVER] Remove Old Db File error:%s", err.Error()) return nil } - fmt.Println("[DATA RECOVER] Remove Old Db File Finished") - fmt.Println("[DATA RECOVER] Move New Db File") + utils.CLog("[DATA RECOVER] Remove Old Db File Finished") + utils.CLog("[DATA RECOVER] Move New Db File") recoveryDb := "./upload/Backup/recovery.db" if err := ossupport.MoveFile(recoveryDb, "./rulex.db"); err != nil { - fmt.Println("[DATA RECOVER] Move New Db File error", err) + utils.CLog("[DATA RECOVER] Move New Db File error:%s", err.Error()) return nil } - fmt.Println("[DATA RECOVER] Move New Db File Finished") - fmt.Println("[DATA RECOVER] Try to Restart rulex") - // upgrade lock - if err := os.WriteFile("/var/run/rulex-upgrade.lock", []byte{48}, 0755); err != nil { - fmt.Println("[DATA RECOVER] Write Recover Lock File error:", err) - return nil - } - defer func() { - // upgrade lock - if err := os.Remove("/var/run/rulex-upgrade.lock"); err != nil { - fmt.Println("[DATA RECOVER] Remove Recover Lock File error:", err) - return - } - }() + utils.CLog("[DATA RECOVER] Move New Db File Finished") + utils.CLog("[DATA RECOVER] Try to Restart rulex") if err := ossupport.RestartRulex(); err != nil { - fmt.Println("[DATA RECOVER] Restart rulex error", err) + utils.CLog("[DATA RECOVER] Restart rulex error:%s", err.Error()) } else { - fmt.Println("[DATA RECOVER] Restart rulex success, Recover Process Exited") + utils.CLog("[DATA RECOVER] Restart rulex success, Recover Process Exited") } - os.Exit(0) return nil }, @@ -242,7 +247,7 @@ func main() { return err } // commercial version will implement it - fmt.Printf("[LICENCE ACTIVE]: Admin(%s,%s), mac addr:[%s] try to request license from %s\n", + utils.CLog("[LICENCE ACTIVE]: Admin(%s,%s), mac addr:[%s] try to request license from %s\n", username, password, macAddr, host) return nil }, @@ -260,7 +265,7 @@ func main() { Action: func(*cli.Context) error { version := fmt.Sprintf("[%v-%v-%v]", runtime.GOOS, runtime.GOARCH, typex.DefaultVersion.Version) - fmt.Println("[*] Rulex Version: " + version) + utils.CLog("[*] Rulex Version: " + version) return nil }, }, diff --git a/script/rulex-daemon.sh b/script/rulex-daemon.sh index 5143292a2..fc27b4849 100644 --- a/script/rulex-daemon.sh +++ b/script/rulex-daemon.sh @@ -10,6 +10,9 @@ SERVICE_FILE="/etc/init.d/$SERVICE_NAME.service" STOP_SIGNAL="/var/run/rulex-stop.sinal" UPGRADE_SIGNAL="/var/run/rulex-upgrade.lock" +SOURCE_DIR="$PWD" + + log() { local level=$1 shift @@ -17,8 +20,6 @@ log() { } install(){ - local source_dir="$PWD" - local db_file="/usr/local/rulex.db" cat > "$SERVICE_FILE" << EOL #!/bin/sh @@ -32,11 +33,11 @@ cat > "$SERVICE_FILE" << EOL # Description: Rulex Service ### END INIT INFO - +# # Create Time: $(date +'%Y-%m-%d %H:%M:%S') -WORKING_DIRECTORY="/usr/local" -EXECUTABLE_PATH="\$WORKING_DIRECTORY/rulex" -CONFIG_PATH="\$WORKING_DIRECTORY/rulex.ini" +# +EXECUTABLE_PATH="$WORKING_DIRECTORY/rulex" +CONFIG_PATH="$WORKING_DIRECTORY/rulex.ini" log() { local level=\$1 @@ -45,13 +46,14 @@ log() { } start() { + rm -f $UPGRADE_SIGNAL rm -f $STOP_SIGNAL pid=\$(pgrep -x -n -f "$EXECUTABLE_PATH run -config=$CONFIG_PATH") if [ -n "\$pid" ]; then log INFO "rulex is running with Pid:\${pid}" exit 0 fi - nohup $EXECUTABLE_PATH run -config=$CONFIG_PATH & + cd $WORKING_DIRECTORY daemon } @@ -99,7 +101,8 @@ daemon() { exit 0 else log WARNING "Detected that rulex process is interrupted. Restarting..." - nohup $EXECUTABLE_PATH run -config=$CONFIG_PATH & + cd $WORKING_DIRECTORY + $EXECUTABLE_PATH run -config=$CONFIG_PATH log WARNING "Detected that rulex process has Restarted." fi fi @@ -129,18 +132,18 @@ esac EOL mkdir -p $WORKING_DIRECTORY - chmod +x $source_dir/rulex + chmod +x $SOURCE_DIR/rulex log INFO "Copy rulex to $WORKING_DIRECTORY" - cp -rfp "$source_dir/rulex" "$EXECUTABLE_PATH" + cp -rfp "$SOURCE_DIR/rulex" "$EXECUTABLE_PATH" log INFO "Copy rulex.ini to $WORKING_DIRECTORY" - cp -rfp "$source_dir/rulex.ini" "$CONFIG_PATH" + cp -rfp "$SOURCE_DIR/rulex.ini" "$CONFIG_PATH" log INFO "Copy license.lic to $WORKING_DIRECTORY" - cp -rfp "$source_dir/license.lic" "$WORKING_DIRECTORY/" + cp -rfp "$SOURCE_DIR/license.lic" "$WORKING_DIRECTORY/" log INFO "Copy license.key to $WORKING_DIRECTORY" - cp -rfp "$source_dir/license.key" "$WORKING_DIRECTORY/" + cp -rfp "$SOURCE_DIR/license.key" "$WORKING_DIRECTORY/" chmod 777 $SERVICE_FILE if [ $? -eq 0 ]; then log INFO "Rulex service has been created and extracted." diff --git a/typex/version.go b/typex/version.go index 6cb069b04..2b5d59be9 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,7 +14,7 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-27 15:34:51", + ReleaseTime: "2023-11-27 21:34:32", } var Banner = ` ** Welcome to RULEX framework world <'_'> diff --git a/utils/io_util.go b/utils/io_util.go index 604925dbc..7ef9d65d4 100644 --- a/utils/io_util.go +++ b/utils/io_util.go @@ -3,6 +3,7 @@ package utils import ( "context" "errors" + "fmt" "io" "time" ) @@ -147,3 +148,15 @@ func Paginate(pageNum int, pageSize int, sliceLength int) (int, int) { return start, end } + +/* +* +* 自定义日志 +* + */ +func CLog(format string, v ...interface{}) { + timestamp := time.Now().UTC().Format("2006/01/02 15:04:05.000000") + logMsg := fmt.Sprintf(format, v...) + logLine := fmt.Sprintf("[%s] %s\n", timestamp, logMsg) + fmt.Print(logLine) +} From f8c8b1ad3315a4853f73afddb41b50a213fe60b4 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 28 Nov 2023 11:11:04 +0800 Subject: [PATCH 064/138] dev: update some magic value --- main.go | 27 ++++++++++------------- ossupport/linux_const_value.go | 40 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 ossupport/linux_const_value.go diff --git a/main.go b/main.go index ec22c8121..5069037a0 100644 --- a/main.go +++ b/main.go @@ -59,7 +59,7 @@ func main() { Commands: []*cli.Command{ { Name: "run", - Usage: "Start rulex, Must with config: -config path/rulex.ini", + Usage: "Start rulex, Must with config: -config=path/rulex.ini", Flags: []cli.Flag{ &cli.StringFlag{ Name: "db", @@ -91,7 +91,7 @@ func main() { }, }, Action: func(c *cli.Context) error { - file, err := os.Create("./local-upgrade-log.txt") + file, err := os.Create(ossupport.UpgradeLogPath) if err != nil { utils.CLog(err.Error()) return nil @@ -100,14 +100,13 @@ func main() { os.Stdout = file os.Stderr = file // upgrade lock - lockFile := "/var/run/rulex-upgrade.lock" - if err := os.WriteFile(lockFile, []byte{48} /*48 -> 0*/, 0755); err != nil { + if err := os.WriteFile(ossupport.UpgradeLockPath, []byte{48} /*48 -> 0*/, 0755); err != nil { utils.CLog("[DATA RECOVER] Write Recover Lock File error:%s", err.Error()) return nil } defer func() { // upgrade lock - if err := os.Remove(lockFile); err != nil { + if err := os.Remove(ossupport.UpgradeLockPath); err != nil { utils.CLog("[DATA RECOVER] Remove Recover Lock File error:%s", err.Error()) return } @@ -124,8 +123,7 @@ func main() { } // unzip Firmware if err := ossupport.UnzipFirmware( - "/usr/local/upload/Firmware/Firmware.zip", - "/usr/local"); err != nil { + ossupport.FirmwarePath, ossupport.MainWorkDir); err != nil { utils.CLog("[RULEX UPGRADE] Unzip error:%s", err.Error()) return nil } @@ -134,7 +132,7 @@ func main() { return nil } // Remove old package - if err := os.Remove("/usr/local/upload/Firmware/Firmware.zip"); err != nil { + if err := os.Remove(ossupport.FirmwarePath); err != nil { utils.CLog("[RULEX UPGRADE] Restart rulex error:%s", err.Error()) return nil } @@ -156,7 +154,7 @@ func main() { }, }, Action: func(c *cli.Context) error { - file, err := os.Create("./rulex-recover-log.txt") + file, err := os.Create(ossupport.RecoverLogPath) if err != nil { utils.CLog(err.Error()) return nil @@ -164,15 +162,14 @@ func main() { defer file.Close() os.Stdout = file os.Stderr = file - lockFile := "/var/run/rulex-upgrade.lock" // upgrade lock - if err := os.WriteFile(lockFile, []byte{48}, 0755); err != nil { + if err := os.WriteFile(ossupport.UpgradeLockPath, []byte{48}, 0755); err != nil { utils.CLog("[DATA RECOVER] Write Recover Lock File error:%s", err.Error()) return nil } defer func() { // upgrade lock - if err := os.Remove(lockFile); err != nil { + if err := os.Remove(ossupport.UpgradeLockPath); err != nil { utils.CLog("[DATA RECOVER] Remove Recover Lock File error:%s", err.Error()) return } @@ -188,14 +185,14 @@ func main() { return nil } utils.CLog("[DATA RECOVER] Remove Old Db File") - if err := os.Remove("./rulex.db"); err != nil { + if err := os.Remove(ossupport.RunDbPath); err != nil { utils.CLog("[DATA RECOVER] Remove Old Db File error:%s", err.Error()) return nil } utils.CLog("[DATA RECOVER] Remove Old Db File Finished") utils.CLog("[DATA RECOVER] Move New Db File") - recoveryDb := "./upload/Backup/recovery.db" - if err := ossupport.MoveFile(recoveryDb, "./rulex.db"); err != nil { + if err := ossupport.MoveFile(ossupport.RecoveryDbPath, + ossupport.RunDbPath); err != nil { utils.CLog("[DATA RECOVER] Move New Db File error:%s", err.Error()) return nil } diff --git a/ossupport/linux_const_value.go b/ossupport/linux_const_value.go new file mode 100644 index 000000000..16f557359 --- /dev/null +++ b/ossupport/linux_const_value.go @@ -0,0 +1,40 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package ossupport + +/* +* +* Linux系统下的一些和应用交互的系统级路径 +* + */ +const ( + // Rulex 工作目录 + MainWorkDir = "/usr/local" + // RULEX 的配置数据库 + RunDbPath = "/usr/local/rulex.db" + // 固件保存路径 + FirmwarePath = "/usr/local/upload/Firmware/Firmware.zip" + // 升级锁 + UpgradeLockPath = "/var/run/rulex-upgrade.lock" + // 升级日志 + UpgradeLogPath = "/var/run/local-upgrade-log.txt" + // 数据恢复日志 + RecoverLogPath = "/var/run/local-recover-log.txt" + // 备份锁 + BackupLockPath = "/var/run/rulex-upgrade.lock" + // 备份数据库 + RecoveryDbPath = "/usr/local/upload/Backup/recovery.db" +) From 2ba485a41ae1e264cd654f4ae6a3a026930d89cd Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 28 Nov 2023 11:18:42 +0800 Subject: [PATCH 065/138] dev: add doc --- plugin/rulex_api_server/service/hw_intrerface_service.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/rulex_api_server/service/hw_intrerface_service.go b/plugin/rulex_api_server/service/hw_intrerface_service.go index 8c65d8003..edf6dc9bf 100644 --- a/plugin/rulex_api_server/service/hw_intrerface_service.go +++ b/plugin/rulex_api_server/service/hw_intrerface_service.go @@ -128,7 +128,7 @@ func InitHwPortConfig() error { /* * -* 获取系统串口 +* 获取系统串口, 这个接口比较特殊,当运行在特殊硬件上的时候,某些系统占用的直接不显示 * */ func GetOsPort() []string { @@ -148,13 +148,13 @@ func GetOsPort() []string { if port == "/dev/ttyS3" { continue } - if port == "/dev/ttyUSB0" { + if port == "/dev/ttyUSB0" { // 4G continue } - if port == "/dev/ttyUSB1" { + if port == "/dev/ttyUSB1" { // Lora continue } - if port == "/dev/ttyUSB2" { + if port == "/dev/ttyUSB2" { // 外部扩展卡 continue } } From 9629158cfe1e890336edf06d88994f0e7cb0f86e Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 28 Nov 2023 15:06:55 +0800 Subject: [PATCH 066/138] dev: add lua http api --- component/appstack/appstack_lua_runtime.go | 4 + engine/rule_lua_runtime.go | 3 + rulexlib/http_api_lib.go | 89 ++++++++++++++++++++++ test/apps/http_get_demo.lua | 20 +++++ test/apps/http_post_demo.lua | 43 +++++++++++ typex/version.go | 2 +- 6 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 rulexlib/http_api_lib.go create mode 100644 test/apps/http_get_demo.lua create mode 100644 test/apps/http_post_demo.lua diff --git a/component/appstack/appstack_lua_runtime.go b/component/appstack/appstack_lua_runtime.go index 2f47fa1fb..0253d766b 100644 --- a/component/appstack/appstack_lua_runtime.go +++ b/component/appstack/appstack_lua_runtime.go @@ -215,4 +215,8 @@ func LoadAppLib(app *Application, e typex.RuleX) { addAppLib(app, e, "jq", "Execute", rulexlib.JqSelect(e)) // Ping addAppLib(app, e, "network", "Ping", rulexlib.PingIp(e)) + // http + addAppLib(app, e, "http", "Get", rulexlib.HttpGet(e)) + addAppLib(app, e, "http", "Post", rulexlib.HttpPost(e)) + } diff --git a/engine/rule_lua_runtime.go b/engine/rule_lua_runtime.go index 9fb3ca3e1..31d941da8 100644 --- a/engine/rule_lua_runtime.go +++ b/engine/rule_lua_runtime.go @@ -156,6 +156,9 @@ func LoadBuildInLuaLib(e typex.RuleX, r *typex.Rule) { r.AddLib(e, "datacenter", "DBQuery", rulexlib.LocalDBQuery(e)) // r.AddLib(e, "network", "Ping", rulexlib.PingIp(e)) + // Http + r.AddLib(e, "http", "Get", rulexlib.HttpGet(e)) + r.AddLib(e, "http", "Post", rulexlib.HttpPost(e)) } diff --git a/rulexlib/http_api_lib.go b/rulexlib/http_api_lib.go new file mode 100644 index 000000000..ca6ca9918 --- /dev/null +++ b/rulexlib/http_api_lib.go @@ -0,0 +1,89 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package rulexlib + +import ( + "io" + "net/http" + "strings" + "time" + + lua "github.com/hootrhino/gopher-lua" + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/typex" +) + +/* +* +* HTTP GET +* + */ +func HttpGet(rx typex.RuleX) func(*lua.LState) int { + return func(l *lua.LState) int { + url := l.ToString(2) + l.Push(lua.LString(__HttpGet(url))) + return 1 + } +} +func HttpPost(rx typex.RuleX) func(*lua.LState) int { + return func(l *lua.LState) int { + url := l.ToString(2) + body := l.ToString(3) + l.Push(lua.LString(__HttpPost(url, body))) + return 1 + } +} + +/* +* +* GET +* + */ +func __HttpGet(url string) string { + client := http.Client{ + Timeout: 5 * time.Second, + } + resp, err := client.Get(url) + if err != nil { + return "" + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return "" + } + return string(body) +} + +/* +* +* POST + */ +func __HttpPost(url string, body string) string { + resp, err := http.Post(url, "application/json", strings.NewReader(body)) + if err != nil { + glogger.GLogger.Error(err) + return "" + } + defer resp.Body.Close() + + responseBody, err := io.ReadAll(resp.Body) + if err != nil { + glogger.GLogger.Error(err) + return "" + } + return string(responseBody) +} diff --git a/test/apps/http_get_demo.lua b/test/apps/http_get_demo.lua new file mode 100644 index 000000000..0ec953978 --- /dev/null +++ b/test/apps/http_get_demo.lua @@ -0,0 +1,20 @@ +-- Copyright (C) 2023 wwhai +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU Affero 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 Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + +function Main(arg) + local Value = http:Get("http://127.0.0.1:2580/api/v1/os/system") + stdlib:Debug("Http Get:" .. Value) + return 0 +end diff --git a/test/apps/http_post_demo.lua b/test/apps/http_post_demo.lua new file mode 100644 index 000000000..4a90944db --- /dev/null +++ b/test/apps/http_post_demo.lua @@ -0,0 +1,43 @@ +-- Copyright (C) 2023 wwhai +-- +-- This program is free software= you can redistribute it and/or modify +-- it under the terms of the GNU Affero 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 Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + +function Main(arg) + local dataTable = { + device_id = 1, + recv_time = "2023-11-28T11=11=36+08=00", + bat_voltage = 0, + longitude = 0, + latitude = 0, + air_height = 0, + water_temp = 19.3171, + salinity = 754.523, + dissolved_oxygen = 0, + ph_value = 5.94821, + wind_speed = 1.02, + wind_direction = 12, + air_temp = 21.1, + air_pressure = 102.3, + air_humidity = 69.1, + noise = 42.9, + wave_height = 0, + mean_wave_period = 0, + peak_wave_period = 0, + mean_wave_direction = 0 + } + local JsonString = json:T2J(dataTable) + local Value = http:Post("http://127.0.0.1:6003/api", JsonString) + stdlib:Debug("Http Post:" .. Value) + return 0 +end diff --git a/typex/version.go b/typex/version.go index 2b5d59be9..28aa9c4e9 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,7 +14,7 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-27 21:34:32", + ReleaseTime: "2023-11-28 14:34:32", } var Banner = ` ** Welcome to RULEX framework world <'_'> From 00e1c740370d1ab98612b4fddabddeedca36ac63 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 28 Nov 2023 18:02:19 +0800 Subject: [PATCH 067/138] dev: rename func --- plugin/rulex_api_server/apis/rhinoh3_firmware_api.go | 2 +- plugin/rulex_api_server/apis/system_firmware_api.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go b/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go index db27898c9..0d4c685c3 100644 --- a/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go +++ b/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go @@ -63,6 +63,6 @@ func RecoverNew(c *gin.Context, ruleEngine typex.RuleX) { * */ func GetUpGradeLog(c *gin.Context, ruleEngine typex.RuleX) { - byteS, _ := os.ReadFile("local-upgrade-log.txt") + byteS, _ := os.ReadFile(ossupport.UpgradeLogPath) c.JSON(common.HTTP_OK, common.OkWithData(string(byteS))) } diff --git a/plugin/rulex_api_server/apis/system_firmware_api.go b/plugin/rulex_api_server/apis/system_firmware_api.go index 936ef80c2..f6ad10d04 100644 --- a/plugin/rulex_api_server/apis/system_firmware_api.go +++ b/plugin/rulex_api_server/apis/system_firmware_api.go @@ -55,7 +55,7 @@ func UploadFirmWare(c *gin.Context, ruleEngine typex.RuleX) { return } - c.JSON(common.HTTP_OK, common.OkWithData(saveDir+fileName)) + c.JSON(common.HTTP_OK, common.Ok()) } /* From 3039ba43edc238268d0b7c48b0f0120e173cfd8f Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 28 Nov 2023 18:24:04 +0800 Subject: [PATCH 068/138] dev: add more log --- main.go | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/main.go b/main.go index 5069037a0..7d7039e28 100644 --- a/main.go +++ b/main.go @@ -100,43 +100,48 @@ func main() { os.Stdout = file os.Stderr = file // upgrade lock - if err := os.WriteFile(ossupport.UpgradeLockPath, []byte{48} /*48 -> 0*/, 0755); err != nil { - utils.CLog("[DATA RECOVER] Write Recover Lock File error:%s", err.Error()) + if err := os.WriteFile(ossupport.UpgradeLockPath, []byte{48}, 0755); err != nil { + utils.CLog("[RULEX UPGRADE] Write Upgrade Lock File error:%s", err.Error()) return nil } defer func() { // upgrade lock if err := os.Remove(ossupport.UpgradeLockPath); err != nil { - utils.CLog("[DATA RECOVER] Remove Recover Lock File error:%s", err.Error()) + utils.CLog("[RULEX UPGRADE] Remove Upgrade Lock File error:%s", err.Error()) return } - utils.CLog("[DATA RECOVER] Remove Recover Lock File Finished") + utils.CLog("[RULEX UPGRADE] Remove Upgrade Lock File Finished") }() if runtime.GOOS != "linux" { utils.CLog("[RULEX UPGRADE] Only Support Linux") return nil } - if !c.Bool("upgrade") { utils.CLog("[RULEX UPGRADE] Nothing todo") return nil } // unzip Firmware + utils.CLog("[RULEX UPGRADE] Unzip Firmware") if err := ossupport.UnzipFirmware( ossupport.FirmwarePath, ossupport.MainWorkDir); err != nil { utils.CLog("[RULEX UPGRADE] Unzip error:%s", err.Error()) return nil } - if err := ossupport.RestartRulex(); err != nil { - utils.CLog("[RULEX UPGRADE] Restart rulex error:%s", err.Error()) - return nil - } + utils.CLog("[RULEX UPGRADE] Unzip Firmware finished") // Remove old package + utils.CLog("[RULEX UPGRADE] Remove Firmware") if err := os.Remove(ossupport.FirmwarePath); err != nil { + utils.CLog("[RULEX UPGRADE] Remove Firmware error:%s", err.Error()) + return nil + } + utils.CLog("[RULEX UPGRADE] Remove Firmware finished") + // + utils.CLog("[RULEX UPGRADE] Restart rulex") + if err := ossupport.RestartRulex(); err != nil { utils.CLog("[RULEX UPGRADE] Restart rulex error:%s", err.Error()) return nil } - utils.CLog("[RULEX UPGRADE] Restart rulex success, Upgrade Process Exited") + utils.CLog("[RULEX UPGRADE] Restart rulex finished, Upgrade Process Exited") os.Exit(0) return nil }, From dd6b3bda9c300f569fdbce7146f40b1246bc4de1 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 28 Nov 2023 19:02:59 +0800 Subject: [PATCH 069/138] fix: fix upgrade failed --- gen_info.sh | 2 +- ossupport/linux_const_value.go | 8 ++++---- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 2 +- typex/version.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gen_info.sh b/gen_info.sh index d2b57f592..f9e26797e 100644 --- a/gen_info.sh +++ b/gen_info.sh @@ -1,6 +1,6 @@ #! /bin/bash VERSION="$(git describe --tags $(git rev-list --tags --max-count=1))" -HASH=$(git rev-list --tags --max-count=1) +HASH=$(git rev-parse HEAD) ####################################################################### ## Gen Version diff --git a/ossupport/linux_const_value.go b/ossupport/linux_const_value.go index 16f557359..05312fb59 100644 --- a/ossupport/linux_const_value.go +++ b/ossupport/linux_const_value.go @@ -27,14 +27,14 @@ const ( RunDbPath = "/usr/local/rulex.db" // 固件保存路径 FirmwarePath = "/usr/local/upload/Firmware/Firmware.zip" - // 升级锁 - UpgradeLockPath = "/var/run/rulex-upgrade.lock" // 升级日志 - UpgradeLogPath = "/var/run/local-upgrade-log.txt" + UpgradeLogPath = "/usr/local/local-upgrade-log.txt" // 数据恢复日志 - RecoverLogPath = "/var/run/local-recover-log.txt" + RecoverLogPath = "/usr/local/local-recover-log.txt" // 备份锁 BackupLockPath = "/var/run/rulex-upgrade.lock" + // 升级锁 + UpgradeLockPath = BackupLockPath // 备份数据库 RecoveryDbPath = "/usr/local/upload/Backup/recovery.db" ) diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index eafd1a81b..31c02d6dc 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -96,7 +96,7 @@ func StartRecoverProcess() { * */ func StartUpgradeProcess() { - cmd := exec.Command("./rulex", "upgrade", "-upgrade=", "true") + cmd := exec.Command("./rulex", "upgrade", "-upgrade=true") cmd.SysProcAttr = NewSysProcAttr() cmd.Env = os.Environ() err := cmd.Start() diff --git a/typex/version.go b/typex/version.go index 28aa9c4e9..a9a9429c8 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-28 14:34:32", + ReleaseTime: "2023-11-28 18:53:13", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-d4274c17c76b9c4 +** Version: v0.6.4-3039ba43edc2382 ** Document: https://hootrhino.github.io ` From 6629000867dea6393459907d53198e652c079f2d Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 28 Nov 2023 22:45:30 +0800 Subject: [PATCH 070/138] dev: add BinToFloat32 Demo --- rulexlib/binary_lib.go | 16 ++++++++++++---- test/apps/binary_hex_to_float32.lua | 20 ++++++++++++++++++++ typex/version.go | 4 ++-- 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 test/apps/binary_hex_to_float32.lua diff --git a/rulexlib/binary_lib.go b/rulexlib/binary_lib.go index 91169e60b..1c8c49a72 100644 --- a/rulexlib/binary_lib.go +++ b/rulexlib/binary_lib.go @@ -515,16 +515,24 @@ func HexToNumber(s string) (int64, error) { func BinToFloat32(rx typex.RuleX) func(*lua.LState) int { return func(l *lua.LState) int { bin := l.ToString(2) - bits := binary.BigEndian.Uint32([]byte(bin)) - l.Push(lua.LNumber(math.Float32frombits(bits))) + dBytes, err := hex.DecodeString(bin) + if err != nil { + l.Push(lua.LNil) + return 1 + } + l.Push(lua.LNumber(math.Float32frombits(binary.BigEndian.Uint32(dBytes)))) return 1 } } func BinToFloat64(rx typex.RuleX) func(*lua.LState) int { return func(l *lua.LState) int { bin := l.ToString(2) - bits := binary.BigEndian.Uint64([]byte(bin)) - l.Push(lua.LNumber(math.Float64frombits(bits))) + dBytes, err := hex.DecodeString(bin) + if err != nil { + l.Push(lua.LNil) + return 1 + } + l.Push(lua.LNumber(math.Float64frombits(binary.BigEndian.Uint64(dBytes)))) return 1 } } diff --git a/test/apps/binary_hex_to_float32.lua b/test/apps/binary_hex_to_float32.lua new file mode 100644 index 000000000..f9c9b9696 --- /dev/null +++ b/test/apps/binary_hex_to_float32.lua @@ -0,0 +1,20 @@ +-- Copyright (C) 2023 wwhai +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU Affero 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 Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + +function Main(arg) + stdlib:Debug("BinToFloat32 : " .. binary:Bin2F32("41FE9F7F")) + -- 31.827878952026367 + return 0 +end diff --git a/typex/version.go b/typex/version.go index a9a9429c8..2cdb34db4 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-28 18:53:13", + ReleaseTime: "2023-11-28 21:09:51", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-3039ba43edc2382 +** Version: v0.6.4-dd6b3bda9c300f5 ** Document: https://hootrhino.github.io ` From f33094a0255d9477758d14976e2b107890f3e2d6 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 29 Nov 2023 14:27:16 +0800 Subject: [PATCH 071/138] dev: add modbus parse demo; fix openwrt sctipt --- script/rulex-openwrt.sh | 1 + test/lua/parse_485_float_value.lua | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/lua/parse_485_float_value.lua diff --git a/script/rulex-openwrt.sh b/script/rulex-openwrt.sh index 5d7bee3c2..43046b67a 100644 --- a/script/rulex-openwrt.sh +++ b/script/rulex-openwrt.sh @@ -38,6 +38,7 @@ USE_PROCD=1 start() { procd_open_instance + cd $WORKING_DIRECTORY procd_set_param command "$executable run -config=$config_file -db=$db_file" procd_set_param respawn 0 procd_set_param stdout 1 diff --git a/test/lua/parse_485_float_value.lua b/test/lua/parse_485_float_value.lua new file mode 100644 index 000000000..f6665a272 --- /dev/null +++ b/test/lua/parse_485_float_value.lua @@ -0,0 +1,24 @@ +Actions = { + function(args) + local dataT, err = json:J2T(args) + if (err ~= nil) then + stdlib:Throw('parse json error:' .. err) + return true, args + end + for key, value in pairs(dataT) do + stdlib:Debug(key .. " :: " .. value['value']) + local MatchHexS = hex:MatchHex("humi:[0,3];temp:[4,7];pres:[8,11]", value['value']) + local ts = time:Time() + local Json = json:T2J( + { + tag = key, + ts = ts, + hum = math:TFloat(binary:Bin2F32(MatchHexS['humi'])), + temp = math:TFloat(binary:Bin2F32(MatchHexS['temp'])), + pres = math:TFloat(binary:Bin2F32(MatchHexS['pres'])), + }) + stdlib:Debug(Json) + end + return true, args + end +} From dbc50676b396b052686f15960669fc030164b581 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 29 Nov 2023 15:42:09 +0800 Subject: [PATCH 072/138] dev: enhance compatible for h3 --- ossupport/rhinoh3_ubuntu18_firmware_ctl.go | 2 +- .../apis/rhinoh3_firmware_api.go | 2 +- .../service/hw_intrerface_service.go | 41 ++++++++++++------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go index 31c02d6dc..f70ad0e73 100644 --- a/ossupport/rhinoh3_ubuntu18_firmware_ctl.go +++ b/ossupport/rhinoh3_ubuntu18_firmware_ctl.go @@ -42,7 +42,7 @@ func StopRulex() error { /* * -* 重启 +* 重启, 依赖于守护进程脚本, 因此这个不是通用的 * */ func RestartRulex() error { diff --git a/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go b/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go index 0d4c685c3..afd985312 100644 --- a/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go +++ b/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go @@ -50,7 +50,7 @@ func Reboot(c *gin.Context, ruleEngine typex.RuleX) { /* * -* 回复出厂 +* 回复出厂, 直接删除配置即可,但是现阶段暂时不实现 * */ func RecoverNew(c *gin.Context, ruleEngine typex.RuleX) { diff --git a/plugin/rulex_api_server/service/hw_intrerface_service.go b/plugin/rulex_api_server/service/hw_intrerface_service.go index edf6dc9bf..2b6293da8 100644 --- a/plugin/rulex_api_server/service/hw_intrerface_service.go +++ b/plugin/rulex_api_server/service/hw_intrerface_service.go @@ -23,6 +23,7 @@ import ( "github.com/hootrhino/rulex/ossupport" "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" "go.bug.st/serial" ) @@ -96,6 +97,7 @@ func GetHwPortConfig(uuid string) (model.MHwPort, error) { */ func InitHwPortConfig() error { for _, portName := range GetOsPort() { + Port := model.MHwPort{ UUID: portName, Name: portName, @@ -106,6 +108,17 @@ func InitHwPortConfig() error { }(), Description: portName, } + // 兼容代码,识别H3网关的参数 + if typex.DefaultVersion.Product == "EEKIIH3" { + if portName == "/dev/ttyS1" { + Port.Alias = "RS485接口1(A1B1)" + Port.Name = "RS4851(A1B1)" + } + if portName == "/dev/ttyS2" { + Port.Alias = "RS485接口2(A2B2)" + Port.Name = "RS4852(A2B2)" + } + } uartCfg := UartConfigDto{ Timeout: 3000, Uart: portName, @@ -129,7 +142,7 @@ func InitHwPortConfig() error { /* * * 获取系统串口, 这个接口比较特殊,当运行在特殊硬件上的时候,某些系统占用的直接不显示 -* +* 这个接口需要兼容各类特殊硬件 */ func GetOsPort() []string { var ports []string @@ -141,20 +154,18 @@ func GetOsPort() []string { List := []string{} for _, port := range ports { if typex.DefaultVersion.Product == "EEKIIH3" { - // H3的下列串口被网卡占用 - if port == "/dev/ttyS0" { - continue - } - if port == "/dev/ttyS3" { - continue - } - if port == "/dev/ttyUSB0" { // 4G - continue - } - if port == "/dev/ttyUSB1" { // Lora - continue - } - if port == "/dev/ttyUSB2" { // 外部扩展卡 + // H3的下列串口被系统占用 + if utils.SContains([]string{ + "/dev/ttyS0", + "/dev/ttyS3", + "/dev/ttyS4", // Linux System + "/dev/ttyS5", // Linux System + "/dev/ttyS6", // Linux System + "/dev/ttyS7", // Linux System + "/dev/ttyUSB0", // 4G + "/dev/ttyUSB1", // 4G + "/dev/ttyUSB2", // 4G + }, port) { continue } } From df84c3fc0900d7f3e0e2c17be7db78f123c09b07 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 29 Nov 2023 22:04:49 +0800 Subject: [PATCH 073/138] dev: optimize LocalDb Query --- component/datacenter/datacenter_localdb.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/component/datacenter/datacenter_localdb.go b/component/datacenter/datacenter_localdb.go index e5ac7f0ef..158278b43 100644 --- a/component/datacenter/datacenter_localdb.go +++ b/component/datacenter/datacenter_localdb.go @@ -87,6 +87,5 @@ func (ldb *LocalDb) Query(goodsId, query string) ([]map[string]any, error) { result := []map[string]any{} return result, ldb.Sqlite.db.Raw(query).Scan(&result).Error } - - return []map[string]any{}, ldb.Sqlite.db.Raw(query).Error + return []map[string]any{}, ldb.Sqlite.db.Exec(query).Error } From 66fb869800cc3800288f8c228fd8708b6ff3fcac Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 30 Nov 2023 16:49:57 +0800 Subject: [PATCH 074/138] dev: add Bin2F32Little function --- component/appstack/appstack_lua_runtime.go | 4 ++++ engine/rule_lua_runtime.go | 4 ++++ rulexlib/binary_lib.go | 24 ++++++++++++++++++++++ test/apps/binary_hex_to_float32.lua | 5 +++-- typex/version.go | 4 ++-- 5 files changed, 37 insertions(+), 4 deletions(-) diff --git a/component/appstack/appstack_lua_runtime.go b/component/appstack/appstack_lua_runtime.go index 0253d766b..f0e51e1b4 100644 --- a/component/appstack/appstack_lua_runtime.go +++ b/component/appstack/appstack_lua_runtime.go @@ -104,6 +104,10 @@ func LoadAppLib(app *Application, e typex.RuleX) { // 浮点数处理 addAppLib(app, e, "binary", "Bin2F32", rulexlib.BinToFloat32(e)) addAppLib(app, e, "binary", "Bin2F64", rulexlib.BinToFloat64(e)) + addAppLib(app, e, "binary", "Bin2F32Big", rulexlib.BinToFloat32(e)) + addAppLib(app, e, "binary", "Bin2F64Big", rulexlib.BinToFloat64(e)) + addAppLib(app, e, "binary", "Bin2F32Little", rulexlib.BinToFloat32Little(e)) + addAppLib(app, e, "binary", "Bin2F64Little", rulexlib.BinToFloat64Little(e)) } { addAppLib(app, e, "hex", "HToN", rulexlib.HToN(e)) diff --git a/engine/rule_lua_runtime.go b/engine/rule_lua_runtime.go index 31d941da8..ab182e9ac 100644 --- a/engine/rule_lua_runtime.go +++ b/engine/rule_lua_runtime.go @@ -63,6 +63,10 @@ func LoadBuildInLuaLib(e typex.RuleX, r *typex.Rule) { r.AddLib(e, "binary", "BS2B", rulexlib.BitStringToBytes(e)) r.AddLib(e, "binary", "Bin2F32", rulexlib.BinToFloat32(e)) r.AddLib(e, "binary", "Bin2F64", rulexlib.BinToFloat64(e)) + r.AddLib(e, "binary", "Bin2F32Big", rulexlib.BinToFloat32(e)) + r.AddLib(e, "binary", "Bin2F64Big", rulexlib.BinToFloat64(e)) + r.AddLib(e, "binary", "Bin2F32Little", rulexlib.BinToFloat32Little(e)) + r.AddLib(e, "binary", "Bin2F64Little", rulexlib.BinToFloat64Little(e)) } { // URL处理 diff --git a/rulexlib/binary_lib.go b/rulexlib/binary_lib.go index 1c8c49a72..39116b328 100644 --- a/rulexlib/binary_lib.go +++ b/rulexlib/binary_lib.go @@ -536,6 +536,30 @@ func BinToFloat64(rx typex.RuleX) func(*lua.LState) int { return 1 } } +func BinToFloat32Little(rx typex.RuleX) func(*lua.LState) int { + return func(l *lua.LState) int { + bin := l.ToString(2) + dBytes, err := hex.DecodeString(bin) + if err != nil { + l.Push(lua.LNil) + return 1 + } + l.Push(lua.LNumber(math.Float32frombits(binary.LittleEndian.Uint32(dBytes)))) + return 1 + } +} +func BinToFloat64Little(rx typex.RuleX) func(*lua.LState) int { + return func(l *lua.LState) int { + bin := l.ToString(2) + dBytes, err := hex.DecodeString(bin) + if err != nil { + l.Push(lua.LNil) + return 1 + } + l.Push(lua.LNumber(math.Float64frombits(binary.LittleEndian.Uint64(dBytes)))) + return 1 + } +} /* * diff --git a/test/apps/binary_hex_to_float32.lua b/test/apps/binary_hex_to_float32.lua index f9c9b9696..10cb96418 100644 --- a/test/apps/binary_hex_to_float32.lua +++ b/test/apps/binary_hex_to_float32.lua @@ -14,7 +14,8 @@ -- along with this program. If not, see . function Main(arg) - stdlib:Debug("BinToFloat32 : " .. binary:Bin2F32("41FE9F7F")) - -- 31.827878952026367 + stdlib:Debug("Bin2F32Big 410e6667: " .. binary:Bin2F32Big("410e6667")) + -- 8.9 + stdlib:Debug("Bin2F32Little 410e6667: " .. binary:Bin2F32Little("410e6667")) return 0 end diff --git a/typex/version.go b/typex/version.go index 2cdb34db4..1309cde57 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-28 21:09:51", + ReleaseTime: "2023-11-30 14:21:01", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-dd6b3bda9c300f5 +** Version: v0.6.4-df84c3fc0900d7f ** Document: https://hootrhino.github.io ` From 625836d3b9e7d4a048d38494eb5f905b09ceb6a6 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 1 Dec 2023 18:35:00 +0800 Subject: [PATCH 075/138] dev: add InternalEventBus; enhance lua --- component/appstack/appstack_runtime.go | 10 +- component/intereventbus/intereventbus.go | 78 ++++++++++++++++ component/interpipeline/xpipline.go | 46 +++++++++- .../{lua_validator.go => rule_lua_runtime.go} | 45 +++++---- engine/engine.go | 42 +++++---- source/internal_event_source.go | 91 +++++++++++++++++++ source/internal_event_source.md | 38 ++++++++ source/uudp_source.go | 1 + typex/constant.go | 39 ++------ typex/version.go | 4 +- 10 files changed, 313 insertions(+), 81 deletions(-) create mode 100644 component/intereventbus/intereventbus.go rename core/{lua_validator.go => rule_lua_runtime.go} (81%) create mode 100644 source/internal_event_source.go create mode 100644 source/internal_event_source.md diff --git a/component/appstack/appstack_runtime.go b/component/appstack/appstack_runtime.go index 76b97adb9..bde1c32b5 100644 --- a/component/appstack/appstack_runtime.go +++ b/component/appstack/appstack_runtime.go @@ -92,8 +92,8 @@ func StartApp(uuid string) error { glogger.GLogger.Debugf("Ready to run app:%s", app.UUID) app.AppState = 1 err := app.VM().CallByParam(lua.P{ - Fn: app.GetMainFunc(), - NRet: 1, + Fn: app.GetMainFunc(), + NRet: 1, // Protect: true, // If ``Protect`` is false, // GopherLua will panic instead of returning an ``error`` value. Handler: &lua.LFunction{ @@ -119,11 +119,11 @@ func StartApp(uuid string) error { if err != nil { time.Sleep(5 * time.Second) if app.KilledBy == "RULEX" { - glogger.GLogger.Infof("App %s Killed By RULEX, No need to rescue", app.UUID) + glogger.GLogger.Errorf("App %s Killed By RULEX, No need to rescue", app.UUID) return } if app.KilledBy == "NORMAL" { - glogger.GLogger.Infof("App %s NORMAL Exited, No need to rescue", app.UUID) + glogger.GLogger.Errorf("App %s NORMAL Exited, No need to rescue", app.UUID) return } glogger.GLogger.Warnf("App %s Exited With error: %s, May be accident, Try to survive", @@ -131,7 +131,7 @@ func StartApp(uuid string) error { // TODO 到底要不要设置一个尝试重启的阈值? // if tryTimes >= Max -> return if app.AutoStart { - glogger.GLogger.Infof("App %s Try to restart", app.UUID) + glogger.GLogger.Warnf("App %s Try to restart", app.UUID) go StartApp(uuid) return } diff --git a/component/intereventbus/intereventbus.go b/component/intereventbus/intereventbus.go new file mode 100644 index 000000000..38a73a807 --- /dev/null +++ b/component/intereventbus/intereventbus.go @@ -0,0 +1,78 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package intereventbus + +import ( + "context" + + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/typex" +) + +var __DefaultInternalEventSource *InternalEventBus + +// --------------------------------------------------------- +// Type +// --------------------------------------------------------- +type BaseEvent struct { + Type string + Event string + Ts uint64 + Info interface{} +} + +type InternalEventBus struct { + Queue chan BaseEvent + Rulex typex.RuleX +} + +func (q *InternalEventBus) GetSize() int { + return cap(q.Queue) +} + +/* +* + - 内部事件,例如资源挂了或者设备离线、超时等等,该资源是单例模式, + 维护一个channel来接收各种事件,将收到的消息吐到InterQueue即可 + +* +*/ +func InitInternalEventSource(r typex.RuleX) *InternalEventBus { + __DefaultInternalEventSource = new(InternalEventBus) + __DefaultInternalEventSource.Rulex = r + return __DefaultInternalEventSource +} + +/* +* +* 监控chan +* + */ +func StartInternalEventQueue() { + go func(ctx context.Context, InternalEventBus InternalEventBus) { + for { + select { + case <-ctx.Done(): + return + case Event := <-__DefaultInternalEventSource.Queue: + { + glogger.GLogger.Debug("Event:", Event) + + } + } + } + }(typex.GCTX, *__DefaultInternalEventSource) +} diff --git a/component/interpipeline/xpipline.go b/component/interpipeline/xpipline.go index 1b01e4777..d1eafec40 100644 --- a/component/interpipeline/xpipline.go +++ b/component/interpipeline/xpipline.go @@ -66,7 +66,14 @@ func Execute(vm *lua.LState, k string, args ...lua.LValue) (interface{}, error) return nil, errors.New("target:" + k + " is not a lua function") } -// callLuaFunc +/* +* +* + + callLuaFunc + +* +*/ func callLuaFunc(vm *lua.LState, callable *lua.LFunction, args ...lua.LValue) ([]lua.LValue, error) { if callable == nil { return nil, errors.New("callable function is not exists") @@ -79,9 +86,40 @@ func callLuaFunc(vm *lua.LState, callable *lua.LFunction, args ...lua.LValue) ([ if err != nil { return nil, err } - vm.Pop(-1) - vm.Pop(-2) - vm.Pop(-3) + //vm.Pop(-1) + //vm.Pop(-2) + //vm.Pop(-3) // 这是我很早以前写的代码, + // // 但是今天突然发现看不懂为啥这里要Pop栈? + // 2023 12-01 删除 + // return data, true|false return []lua.LValue{vm.Get(-2), vm.Get(-1)}, nil } + +// #include +// #include +// #include + +// int main() { +// lua_State *L = luaL_newstate(); +// luaL_openlibs(L); +// if (luaL_dofile(L, "example.lua") != LUA_OK) { +// fprintf(stderr, "Error running Lua script: %s\n", lua_tostring(L, -1)); +// lua_close(L); +// return 1; +// } +// lua_getglobal(L, "my_lua_function"); +// lua_pushinteger(L, 10); +// lua_pushinteger(L, 20); +// if (lua_pcall(L, 2, 2, 0) != LUA_OK) { +// fprintf(stderr, "Error calling Lua function: %s\n", lua_tostring(L, -1)); +// lua_close(L); +// return 1; +// } +// int result1 = lua_tointeger(L, -2); +// int result2 = lua_tointeger(L, -1); +// printf("Result 1: %d\n", result1); +// printf("Result 2: %d\n", result2); +// lua_close(L); +// return 0; +// } diff --git a/core/lua_validator.go b/core/rule_lua_runtime.go similarity index 81% rename from core/lua_validator.go rename to core/rule_lua_runtime.go index acc87aa61..2d00863ba 100644 --- a/core/lua_validator.go +++ b/core/rule_lua_runtime.go @@ -20,7 +20,6 @@ import ( lua "github.com/hootrhino/gopher-lua" "github.com/hootrhino/rulex/component/interpipeline" - "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" ) @@ -51,27 +50,33 @@ func ExecuteActions(rule *typex.Rule, arg lua.LValue) (lua.LValue, error) { luaOriginTable := rule.LuaVM.GetGlobal(ACTIONS_KEY) if luaOriginTable != nil && luaOriginTable.Type() == lua.LTTable { // 断言成包含回调的 table - funcsTable := luaOriginTable.(*lua.LTable) - funcs := make(map[string]*lua.LFunction, funcsTable.Len()) - var err error = nil - funcsTable.ForEach(func(idx, f lua.LValue) { - if f.Type() == lua.LTFunction { - funcs[idx.String()] = f.(*lua.LFunction) - } else { - err = errors.New(f.String() + " not a lua function") - return + switch funcsTable := luaOriginTable.(type) { + case *lua.LTable: + { + funcs := make(map[string]*lua.LFunction, funcsTable.Len()) + var err error = nil + funcsTable.ForEach(func(idx, f lua.LValue) { + if f.Type() == lua.LTFunction { + funcs[idx.String()] = f.(*lua.LFunction) + } else { + err = errors.New(f.String() + " not a lua function") + return + } + }) + if err != nil { + return nil, err + } + // Rule may stop + if rule.Status != typex.RULE_STOP { + return interpipeline.RunPipline(rule.LuaVM, funcs, arg) + } + return lua.LNil, nil + } + default: + { + return nil, errors.New("'Actions' is not functions type Table") } - }) - if err != nil { - return nil, err - } - if rule.Status != typex.RULE_STOP { - return interpipeline.RunPipline(rule.LuaVM, funcs, arg) } - // if stopped, log warning information - glogger.GLogger.Warn("Rule has stopped:" + rule.UUID) - return lua.LNil, nil - } return nil, errors.New("'Actions' not a lua table or not exist") diff --git a/engine/engine.go b/engine/engine.go index cfd0c9ea9..77f02af78 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -212,17 +212,17 @@ func (e *RuleEngine) RunSourceCallbacks(in *typex.InEnd, callbackArgs string) { for _, rule := range in.BindRules { if rule.Status == typex.RULE_RUNNING { if rule.Type == "lua" { - _, err := core.ExecuteActions(&rule, lua.LString(callbackArgs)) - if err != nil { - glogger.GLogger.Error("RunLuaCallbacks error:", err) - _, err := core.ExecuteFailed(rule.LuaVM, lua.LString(err.Error())) - if err != nil { - glogger.GLogger.Error(err) + _, errA := core.ExecuteActions(&rule, lua.LString(callbackArgs)) + if errA != nil { + glogger.GLogger.Error("RunLuaCallbacks error:", errA) + _, err0 := core.ExecuteFailed(rule.LuaVM, lua.LString(errA.Error())) + if err0 != nil { + glogger.GLogger.Error(err0) } } else { - _, err := core.ExecuteSuccess(rule.LuaVM) - if err != nil { - glogger.GLogger.Error(err) + _, errS := core.ExecuteSuccess(rule.LuaVM) + if errS != nil { + glogger.GLogger.Error(errS) return // lua 是规则链,有短路原则,中途出错会中断 } } @@ -240,17 +240,17 @@ func (e *RuleEngine) RunDeviceCallbacks(Device *typex.Device, callbackArgs strin for _, rule := range Device.BindRules { if rule.Status == typex.RULE_RUNNING { if rule.Type == "lua" { - _, err := core.ExecuteActions(&rule, lua.LString(callbackArgs)) - if err != nil { - glogger.GLogger.Error("RunLuaCallbacks error:", err) - _, err := core.ExecuteFailed(rule.LuaVM, lua.LString(err.Error())) - if err != nil { - glogger.GLogger.Error(err) + _, errA := core.ExecuteActions(&rule, lua.LString(callbackArgs)) + if errA != nil { + glogger.GLogger.Error("RunLuaCallbacks error:", errA) + _, err1 := core.ExecuteFailed(rule.LuaVM, lua.LString(errA.Error())) + if err1 != nil { + glogger.GLogger.Error(err1) } } else { - _, err := core.ExecuteSuccess(rule.LuaVM) - if err != nil { - glogger.GLogger.Error(err) + _, err2 := core.ExecuteSuccess(rule.LuaVM) + if err2 != nil { + glogger.GLogger.Error(err2) return } } @@ -582,6 +582,12 @@ func (e *RuleEngine) InitSourceTypeManager() error { NewSource: source.NewIoTHubSource, }, ) + e.SourceTypeManager.Register(typex.INTERNAL_EVENT, + &typex.XConfig{ + Engine: e, + NewSource: source.NewInternalEventSource, + }, + ) return nil } diff --git a/source/internal_event_source.go b/source/internal_event_source.go new file mode 100644 index 000000000..8b97b541c --- /dev/null +++ b/source/internal_event_source.go @@ -0,0 +1,91 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package source + +import ( + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" +) + +type __InternalEventSourceConfig struct { +} +type InternalEventSource struct { + typex.XStatus + mainConfig __InternalEventSourceConfig +} + +func NewInternalEventSource(r typex.RuleX) typex.XSource { + s := InternalEventSource{} + s.RuleEngine = r + return &s +} + +func (u *InternalEventSource) Start(cctx typex.CCTX) error { + u.Ctx = cctx.Ctx + u.CancelCTX = cctx.CancelCTX + + return nil + +} + +func (u *InternalEventSource) Details() *typex.InEnd { + return u.RuleEngine.GetInEnd(u.PointId) +} + +func (u *InternalEventSource) Test(inEndId string) bool { + return true +} + +func (u *InternalEventSource) Init(inEndId string, configMap map[string]interface{}) error { + u.PointId = inEndId + if err := utils.BindSourceConfig(configMap, &u.mainConfig); err != nil { + return err + } + return nil +} + +func (u *InternalEventSource) DataModels() []typex.XDataModel { + return u.XDataModels +} + +func (u *InternalEventSource) Status() typex.SourceState { + return typex.SOURCE_UP +} + +func (u *InternalEventSource) Stop() { + if u.CancelCTX != nil { + u.CancelCTX() + } + +} +func (*InternalEventSource) Driver() typex.XExternalDriver { + return nil +} + +// 拓扑 +func (*InternalEventSource) Topology() []typex.TopologyPoint { + return []typex.TopologyPoint{} +} + +// 来自外面的数据 +func (*InternalEventSource) DownStream([]byte) (int, error) { + return 0, nil +} + +// 上行数据 +func (*InternalEventSource) UpStream([]byte) (int, error) { + return 0, nil +} diff --git a/source/internal_event_source.md b/source/internal_event_source.md new file mode 100644 index 000000000..db37c26d4 --- /dev/null +++ b/source/internal_event_source.md @@ -0,0 +1,38 @@ +# 内部消息源 +可以使用这个数据源来监控系统内部的消息,比如设备离线,资源连接失败等。 + +## 消息类型 +- SOURCE: 北向事件 +- DEVICE: 设备事件 +- TARGET: 南向事件 +- SYSTEM: 系统内部事件 +- HARDWARE: 硬件事件 + +## 示例 +### 设备上线: +```json +{ + "type" :"DEVICE", + "event":"event.connected", + "ts":121312431432, + "device_info":{ + "uuid":"UUID1234567", + "name":"温湿度计" + } +} + +``` + +### 设备离线: +```json +{ + "type" :"DEVICE", + "event":"event.disconnected", + "ts":121312431432, + "device_info":{ + "uuid":"UUID1234567", + "name":"温湿度计" + } +} + +``` \ No newline at end of file diff --git a/source/uudp_source.go b/source/uudp_source.go index 63ccadfef..28632a572 100644 --- a/source/uudp_source.go +++ b/source/uudp_source.go @@ -23,6 +23,7 @@ func NewUdpInEndSource(e typex.RuleX) typex.XSource { u.RuleEngine = e return &u } + func (u *udpSource) Start(cctx typex.CCTX) error { u.Ctx = cctx.Ctx u.CancelCTX = cctx.CancelCTX diff --git a/typex/constant.go b/typex/constant.go index 43ea8426a..b1fd60532 100644 --- a/typex/constant.go +++ b/typex/constant.go @@ -47,37 +47,14 @@ func (i InEndType) String() string { } const ( - MQTT InEndType = "MQTT" - HTTP InEndType = "HTTP" - COAP InEndType = "COAP" - GRPC InEndType = "GRPC" - UART_MODULE InEndType = "UART_MODULE" - // - // MODBUS_MASTER - // - MODBUS_MASTER InEndType = "MODBUS_MASTER" - // - // MODBUS_SLAVER - // - MODBUS_SLAVER InEndType = "MODBUS_SLAVER" - // - // From snmp server provider - // - SNMP_SERVER InEndType = "SNMP_SERVER" - // - // NATS.IO SERVER - // - NATS_SERVER InEndType = "NATS_SERVER" - // - // 西门子S7客户端 - // - SIEMENS_S7 InEndType = "SIEMENS_S7" - // - // RULEX UDP 自定义简单协议 - // - RULEX_UDP InEndType = "RULEX_UDP" - // 通用IotHUB + MQTT InEndType = "MQTT" + HTTP InEndType = "HTTP" + COAP InEndType = "COAP" + GRPC InEndType = "GRPC" + NATS_SERVER InEndType = "NATS_SERVER" + RULEX_UDP InEndType = "RULEX_UDP" GENERIC_IOT_HUB InEndType = "GENERIC_IOT_HUB" + INTERNAL_EVENT InEndType = "INTERNAL_EVENT" // 内部消息 ) // TargetType @@ -102,9 +79,7 @@ const ( PGSQL_TARGET TargetType = "PGSQL" NATS_TARGET TargetType = "NATS" HTTP_TARGET TargetType = "HTTP" - // // TDENGINE - // TDENGINE_TARGET TargetType = "TDENGINE" // GRPC GRPC_CODEC_TARGET TargetType = "GRPC_CODEC_TARGET" diff --git a/typex/version.go b/typex/version.go index 1309cde57..975f63bfd 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-11-30 14:21:01", + ReleaseTime: "2023-12-01 18:34:26", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-df84c3fc0900d7f +** Version: v0.6.4-66fb869800cc380 ** Document: https://hootrhino.github.io ` From cff7dab8876f129d6b44ca1fd5e4c69999f0bcf9 Mon Sep 17 00:00:00 2001 From: Jane Date: Sun, 3 Dec 2023 14:52:06 +0800 Subject: [PATCH 076/138] ci: update swag version & remove unused module & ignore go.sum (#212) --- .gitignore | 1 + go.mod | 28 +- go.sum | 1645 ---------------------------------------------------- main.go | 1 + 4 files changed, 15 insertions(+), 1660 deletions(-) delete mode 100644 go.sum diff --git a/.gitignore b/.gitignore index 7098302fc..15a2f6603 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ plugin/rulex_api_server/www/index.html plugin/rulex_api_server/server/www/index.html test/script/_temp/* upload/* +go.sum \ No newline at end of file diff --git a/go.mod b/go.mod index f8acd1d04..81a5f8762 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,7 @@ require ( github.com/suapapa/go_eddystone v1.3.1 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 - github.com/swaggo/swag v1.8.12 + github.com/swaggo/swag v1.16.2 github.com/tbrandon/mbserver v0.0.0-20211210035124-daf3c8c4269f github.com/thinkgos/go-iecp5 v1.2.1 github.com/urfave/cli/v2 v2.25.5 @@ -58,8 +58,8 @@ require ( go.bug.st/serial v1.5.0 go.mongodb.org/mongo-driver v1.11.6 go.uber.org/zap v1.15.0 - golang.org/x/crypto v0.14.0 - golang.org/x/sys v0.13.0 + golang.org/x/crypto v0.15.0 + golang.org/x/sys v0.14.0 google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 gopkg.in/ini.v1 v1.67.0 @@ -70,22 +70,20 @@ require ( require ( github.com/KyleBanks/depth v1.2.1 // indirect - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.6 // indirect - github.com/go-openapi/spec v0.20.4 // indirect - github.com/go-openapi/swag v0.19.15 // indirect + github.com/go-openapi/jsonpointer v0.20.0 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/spec v0.20.9 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/juju/errors v0.0.0-20170703010042-c7d06af17c68 // indirect - github.com/mailru/easyjson v0.7.6 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/richardlehane/mscfb v1.0.4 // indirect github.com/richardlehane/msoleps v1.0.3 // indirect - github.com/stretchr/testify v1.8.4 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect - golang.org/x/tools v0.7.0 // indirect + golang.org/x/tools v0.15.0 // indirect ) require ( @@ -160,9 +158,9 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.5.0 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a // indirect google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect diff --git a/go.sum b/go.sum deleted file mode 100644 index eac761085..000000000 --- a/go.sum +++ /dev/null @@ -1,1645 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= -cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU= -cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= -cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= -cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= -cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= -cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= -cloud.google.com/go/accesscontextmanager v1.4.0/go.mod h1:/Kjh7BBu/Gh83sv+K60vN9QE5NJcd80sU33vIe2IFPE= -cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw= -cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY= -cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI= -cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4= -cloud.google.com/go/apigateway v1.3.0/go.mod h1:89Z8Bhpmxu6AmUxuVRg/ECRGReEdiP3vQtk4Z1J9rJk= -cloud.google.com/go/apigateway v1.4.0/go.mod h1:pHVY9MKGaH9PQ3pJ4YLzoj6U5FUDeDFBllIz7WmzJoc= -cloud.google.com/go/apigeeconnect v1.3.0/go.mod h1:G/AwXFAKo0gIXkPTVfZDd2qA1TxBXJ3MgMRBQkIi9jc= -cloud.google.com/go/apigeeconnect v1.4.0/go.mod h1:kV4NwOKqjvt2JYR0AoIWo2QGfoRtn/pkS3QlHp0Ni04= -cloud.google.com/go/appengine v1.4.0/go.mod h1:CS2NhuBuDXM9f+qscZ6V86m1MIIqPj3WC/UoEuR1Sno= -cloud.google.com/go/appengine v1.5.0/go.mod h1:TfasSozdkFI0zeoxW3PTBLiNqRmzraodCWatWI9Dmak= -cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4= -cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0= -cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ= -cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk= -cloud.google.com/go/artifactregistry v1.8.0/go.mod h1:w3GQXkJX8hiKN0v+at4b0qotwijQbYUqF2GWkZzAhC0= -cloud.google.com/go/artifactregistry v1.9.0/go.mod h1:2K2RqvA2CYvAeARHRkLDhMDJ3OXy26h3XW+3/Jh2uYc= -cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o= -cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s= -cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0= -cloud.google.com/go/asset v1.9.0/go.mod h1:83MOE6jEJBMqFKadM9NLRcs80Gdw76qGuHn8m3h8oHQ= -cloud.google.com/go/asset v1.10.0/go.mod h1:pLz7uokL80qKhzKr4xXGvBQXnzHn5evJAEAtZiIb0wY= -cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY= -cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw= -cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI= -cloud.google.com/go/assuredworkloads v1.8.0/go.mod h1:AsX2cqyNCOvEQC8RMPnoc0yEarXQk6WEKkxYfL6kGIo= -cloud.google.com/go/assuredworkloads v1.9.0/go.mod h1:kFuI1P78bplYtT77Tb1hi0FMxM0vVpRC7VVoJC3ZoT0= -cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0= -cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8= -cloud.google.com/go/automl v1.7.0/go.mod h1:RL9MYCCsJEOmt0Wf3z9uzG0a7adTT1fe+aObgSpkCt8= -cloud.google.com/go/automl v1.8.0/go.mod h1:xWx7G/aPEe/NP+qzYXktoBSDfjO+vnKMGgsApGJJquM= -cloud.google.com/go/baremetalsolution v0.3.0/go.mod h1:XOrocE+pvK1xFfleEnShBlNAXf+j5blPPxrhjKgnIFc= -cloud.google.com/go/baremetalsolution v0.4.0/go.mod h1:BymplhAadOO/eBa7KewQ0Ppg4A4Wplbn+PsFKRLo0uI= -cloud.google.com/go/batch v0.3.0/go.mod h1:TR18ZoAekj1GuirsUsR1ZTKN3FC/4UDnScjT8NXImFE= -cloud.google.com/go/batch v0.4.0/go.mod h1:WZkHnP43R/QCGQsZ+0JyG4i79ranE2u8xvjq/9+STPE= -cloud.google.com/go/beyondcorp v0.2.0/go.mod h1:TB7Bd+EEtcw9PCPQhCJtJGjk/7TC6ckmnSFS+xwTfm4= -cloud.google.com/go/beyondcorp v0.3.0/go.mod h1:E5U5lcrcXMsCuoDNyGrpyTm/hn7ne941Jz2vmksAxW8= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= -cloud.google.com/go/bigquery v1.43.0/go.mod h1:ZMQcXHsl+xmU1z36G2jNGZmKp9zNY5BUua5wDgmNCfw= -cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= -cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= -cloud.google.com/go/billing v1.6.0/go.mod h1:WoXzguj+BeHXPbKfNWkqVtDdzORazmCjraY+vrxcyvI= -cloud.google.com/go/billing v1.7.0/go.mod h1:q457N3Hbj9lYwwRbnlD7vUpyjq6u5U1RAOArInEiD5Y= -cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= -cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI= -cloud.google.com/go/binaryauthorization v1.3.0/go.mod h1:lRZbKgjDIIQvzYQS1p99A7/U1JqvqeZg0wiI5tp6tg0= -cloud.google.com/go/binaryauthorization v1.4.0/go.mod h1:tsSPQrBd77VLplV70GUhBf/Zm3FsKmgSqgm4UmiDItk= -cloud.google.com/go/certificatemanager v1.3.0/go.mod h1:n6twGDvcUBFu9uBgt4eYvvf3sQ6My8jADcOVwHmzadg= -cloud.google.com/go/certificatemanager v1.4.0/go.mod h1:vowpercVFyqs8ABSmrdV+GiFf2H/ch3KyudYQEMM590= -cloud.google.com/go/channel v1.8.0/go.mod h1:W5SwCXDJsq/rg3tn3oG0LOxpAo6IMxNa09ngphpSlnk= -cloud.google.com/go/channel v1.9.0/go.mod h1:jcu05W0my9Vx4mt3/rEHpfxc9eKi9XwsdDL8yBMbKUk= -cloud.google.com/go/cloudbuild v1.3.0/go.mod h1:WequR4ULxlqvMsjDEEEFnOG5ZSRSgWOywXYDb1vPE6U= -cloud.google.com/go/cloudbuild v1.4.0/go.mod h1:5Qwa40LHiOXmz3386FrjrYM93rM/hdRr7b53sySrTqA= -cloud.google.com/go/clouddms v1.3.0/go.mod h1:oK6XsCDdW4Ib3jCCBugx+gVjevp2TMXFtgxvPSee3OM= -cloud.google.com/go/clouddms v1.4.0/go.mod h1:Eh7sUGCC+aKry14O1NRljhjyrr0NFC0G2cjwX0cByRk= -cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY= -cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI= -cloud.google.com/go/cloudtasks v1.7.0/go.mod h1:ImsfdYWwlWNJbdgPIIGJWC+gemEGTBK/SunNQQNCAb4= -cloud.google.com/go/cloudtasks v1.8.0/go.mod h1:gQXUIwCSOI4yPVK7DgTVFiiP0ZW/eQkydWzwVMdHxrI= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM= -cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= -cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= -cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= -cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= -cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU= -cloud.google.com/go/compute v1.12.0/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x/6PIIOocU= -cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= -cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= -cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= -cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= -cloud.google.com/go/container v1.6.0/go.mod h1:Xazp7GjJSeUYo688S+6J5V+n/t+G5sKBTFkKNudGRxg= -cloud.google.com/go/container v1.7.0/go.mod h1:Dp5AHtmothHGX3DwwIHPgq45Y8KmNsgN3amoYfxVkLo= -cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I= -cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4= -cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0= -cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs= -cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc= -cloud.google.com/go/datacatalog v1.7.0/go.mod h1:9mEl4AuDYWw81UGc41HonIHH7/sn52H0/tc8f8ZbZIE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= -cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM= -cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ= -cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo= -cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE= -cloud.google.com/go/dataform v0.5.0/go.mod h1:GFUYRe8IBa2hcomWplodVmUx/iTL0FrsauObOM3Ipr0= -cloud.google.com/go/datafusion v1.4.0/go.mod h1:1Zb6VN+W6ALo85cXnM1IKiPw+yQMKMhB9TsTSRDo/38= -cloud.google.com/go/datafusion v1.5.0/go.mod h1:Kz+l1FGHB0J+4XF2fud96WMmRiq/wj8N9u007vyXZ2w= -cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I= -cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ= -cloud.google.com/go/dataplex v1.3.0/go.mod h1:hQuRtDg+fCiFgC8j0zV222HvzFQdRd+SVX8gdmFcZzA= -cloud.google.com/go/dataplex v1.4.0/go.mod h1:X51GfLXEMVJ6UN47ESVqvlsRplbLhcsAt0kZCCKsU0A= -cloud.google.com/go/dataproc v1.7.0/go.mod h1:CKAlMjII9H90RXaMpSxQ8EU6dQx6iAYNPcYPOkSbi8s= -cloud.google.com/go/dataproc v1.8.0/go.mod h1:5OW+zNAH0pMpw14JVrPONsxMQYMBqJuzORhIBfBn9uI= -cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo= -cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo= -cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ= -cloud.google.com/go/datastream v1.4.0/go.mod h1:h9dpzScPhDTs5noEMQVWP8Wx8AFBRyS0s8KWPx/9r0g= -cloud.google.com/go/datastream v1.5.0/go.mod h1:6TZMMNPwjUqZHBKPQ1wwXpb0d5VDVPl2/XoS5yi88q4= -cloud.google.com/go/deploy v1.4.0/go.mod h1:5Xghikd4VrmMLNaF6FiRFDlHb59VM59YoDQnOUdsH/c= -cloud.google.com/go/deploy v1.5.0/go.mod h1:ffgdD0B89tToyW/U/D2eL0jN2+IEV/3EMuXHA0l4r+s= -cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4= -cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0= -cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8= -cloud.google.com/go/dialogflow v1.18.0/go.mod h1:trO7Zu5YdyEuR+BhSNOqJezyFQ3aUzz0njv7sMx/iek= -cloud.google.com/go/dialogflow v1.19.0/go.mod h1:JVmlG1TwykZDtxtTXujec4tQ+D8SBFMoosgy+6Gn0s0= -cloud.google.com/go/dlp v1.6.0/go.mod h1:9eyB2xIhpU0sVwUixfBubDoRwP+GjeUoxxeueZmqvmM= -cloud.google.com/go/dlp v1.7.0/go.mod h1:68ak9vCiMBjbasxeVD17hVPxDEck+ExiHavX8kiHG+Q= -cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU= -cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU= -cloud.google.com/go/documentai v1.9.0/go.mod h1:FS5485S8R00U10GhgBC0aNGrJxBP8ZVpEeJ7PQDZd6k= -cloud.google.com/go/documentai v1.10.0/go.mod h1:vod47hKQIPeCfN2QS/jULIvQTugbmdc0ZvxxfQY1bg4= -cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y= -cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= -cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= -cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= -cloud.google.com/go/essentialcontacts v1.3.0/go.mod h1:r+OnHa5jfj90qIfZDO/VztSFqbQan7HV75p8sA+mdGI= -cloud.google.com/go/essentialcontacts v1.4.0/go.mod h1:8tRldvHYsmnBCHdFpvU+GL75oWiBKl80BiqlFh9tp+8= -cloud.google.com/go/eventarc v1.7.0/go.mod h1:6ctpF3zTnaQCxUjHUdcfgcA1A2T309+omHZth7gDfmc= -cloud.google.com/go/eventarc v1.8.0/go.mod h1:imbzxkyAU4ubfsaKYdQg04WS1NvncblHEup4kvF+4gw= -cloud.google.com/go/filestore v1.3.0/go.mod h1:+qbvHGvXU1HaKX2nD0WEPo92TP/8AQuCVEBXNY9z0+w= -cloud.google.com/go/filestore v1.4.0/go.mod h1:PaG5oDfo9r224f8OYXURtAsY+Fbyq/bLYoINEK8XQAI= -cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= -cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= -cloud.google.com/go/functions v1.8.0/go.mod h1:RTZ4/HsQjIqIYP9a9YPbU+QFoQsAlYgrwOXJWHn1POY= -cloud.google.com/go/functions v1.9.0/go.mod h1:Y+Dz8yGguzO3PpIjhLTbnqV1CWmgQ5UwtlpzoyquQ08= -cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= -cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA= -cloud.google.com/go/gaming v1.7.0/go.mod h1:LrB8U7MHdGgFG851iHAfqUdLcKBdQ55hzXy9xBJz0+w= -cloud.google.com/go/gaming v1.8.0/go.mod h1:xAqjS8b7jAVW0KFYeRUxngo9My3f33kFmua++Pi+ggM= -cloud.google.com/go/gkebackup v0.2.0/go.mod h1:XKvv/4LfG829/B8B7xRkk8zRrOEbKtEam6yNfuQNH60= -cloud.google.com/go/gkebackup v0.3.0/go.mod h1:n/E671i1aOQvUxT541aTkCwExO/bTer2HDlj4TsBRAo= -cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o= -cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A= -cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0= -cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0= -cloud.google.com/go/gkemulticloud v0.3.0/go.mod h1:7orzy7O0S+5kq95e4Hpn7RysVA7dPs8W/GgfUtsPbrA= -cloud.google.com/go/gkemulticloud v0.4.0/go.mod h1:E9gxVBnseLWCk24ch+P9+B2CoDFJZTyIgLKSalC7tuI= -cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc= -cloud.google.com/go/gsuiteaddons v1.3.0/go.mod h1:EUNK/J1lZEZO8yPtykKxLXI6JSVN2rg9bN8SXOa0bgM= -cloud.google.com/go/gsuiteaddons v1.4.0/go.mod h1:rZK5I8hht7u7HxFQcFei0+AtfS9uSushomRlg+3ua1o= -cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= -cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc= -cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= -cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= -cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= -cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= -cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= -cloud.google.com/go/ids v1.2.0/go.mod h1:5WXvp4n25S0rA/mQWAg1YEEBBq6/s+7ml1RDCW1IrcY= -cloud.google.com/go/iot v1.3.0/go.mod h1:r7RGh2B61+B8oz0AGE+J72AhA0G7tdXItODWsaA2oLs= -cloud.google.com/go/iot v1.4.0/go.mod h1:dIDxPOn0UvNDUMD8Ger7FIaTuvMkj+aGk94RPP0iV+g= -cloud.google.com/go/kms v1.5.0/go.mod h1:QJS2YY0eJGBg3mnDfuaCyLauWwBJiHRboYxJ++1xJNg= -cloud.google.com/go/kms v1.6.0/go.mod h1:Jjy850yySiasBUDi6KFUwUv2n1+o7QZFyuUJg6OgjA0= -cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic= -cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI= -cloud.google.com/go/language v1.7.0/go.mod h1:DJ6dYN/W+SQOjF8e1hLQXMF21AkH2w9wiPzPCJa2MIE= -cloud.google.com/go/language v1.8.0/go.mod h1:qYPVHf7SPoNNiCL2Dr0FfEFNil1qi3pQEyygwpgVKB8= -cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8= -cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08= -cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= -cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= -cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4= -cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w= -cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE= -cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM= -cloud.google.com/go/memcache v1.6.0/go.mod h1:XS5xB0eQZdHtTuTF9Hf8eJkKtR3pVRCcvJwtm68T3rA= -cloud.google.com/go/memcache v1.7.0/go.mod h1:ywMKfjWhNtkQTxrWxCkCFkoPjLHPW6A7WOTVI8xy3LY= -cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY= -cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s= -cloud.google.com/go/metastore v1.7.0/go.mod h1:s45D0B4IlsINu87/AsWiEVYbLaIMeUSoxlKKDqBGFS8= -cloud.google.com/go/metastore v1.8.0/go.mod h1:zHiMc4ZUpBiM7twCIFQmJ9JMEkDSyZS9U12uf7wHqSI= -cloud.google.com/go/monitoring v1.7.0/go.mod h1:HpYse6kkGo//7p6sT0wsIC6IBDET0RhIsnmlA53dvEk= -cloud.google.com/go/monitoring v1.8.0/go.mod h1:E7PtoMJ1kQXWxPjB6mv2fhC5/15jInuulFdYYtlcvT4= -cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA= -cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o= -cloud.google.com/go/networkconnectivity v1.6.0/go.mod h1:OJOoEXW+0LAxHh89nXd64uGG+FbQoeH8DtxCHVOMlaM= -cloud.google.com/go/networkconnectivity v1.7.0/go.mod h1:RMuSbkdbPwNMQjB5HBWD5MpTBnNm39iAVpC3TmsExt8= -cloud.google.com/go/networkmanagement v1.4.0/go.mod h1:Q9mdLLRn60AsOrPc8rs8iNV6OHXaGcDdsIQe1ohekq8= -cloud.google.com/go/networkmanagement v1.5.0/go.mod h1:ZnOeZ/evzUdUsnvRt792H0uYEnHQEMaz+REhhzJRcf4= -cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ= -cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU= -cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY= -cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34= -cloud.google.com/go/notebooks v1.4.0/go.mod h1:4QPMngcwmgb6uw7Po99B2xv5ufVoIQ7nOGDyL4P8AgA= -cloud.google.com/go/notebooks v1.5.0/go.mod h1:q8mwhnP9aR8Hpfnrc5iN5IBhrXUy8S2vuYs+kBJ/gu0= -cloud.google.com/go/optimization v1.1.0/go.mod h1:5po+wfvX5AQlPznyVEZjGJTMr4+CAkJf2XSTQOOl9l4= -cloud.google.com/go/optimization v1.2.0/go.mod h1:Lr7SOHdRDENsh+WXVmQhQTrzdu9ybg0NecjHidBq6xs= -cloud.google.com/go/orchestration v1.3.0/go.mod h1:Sj5tq/JpWiB//X/q3Ngwdl5K7B7Y0KZ7bfv0wL6fqVA= -cloud.google.com/go/orchestration v1.4.0/go.mod h1:6W5NLFWs2TlniBphAViZEVhrXRSMgUGDfW7vrWKvsBk= -cloud.google.com/go/orgpolicy v1.4.0/go.mod h1:xrSLIV4RePWmP9P3tBl8S93lTmlAxjm06NSm2UTmKvE= -cloud.google.com/go/orgpolicy v1.5.0/go.mod h1:hZEc5q3wzwXJaKrsx5+Ewg0u1LxJ51nNFlext7Tanwc= -cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs= -cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg= -cloud.google.com/go/osconfig v1.9.0/go.mod h1:Yx+IeIZJ3bdWmzbQU4fxNl8xsZ4amB+dygAwFPlvnNo= -cloud.google.com/go/osconfig v1.10.0/go.mod h1:uMhCzqC5I8zfD9zDEAfvgVhDS8oIjySWh+l4WK6GnWw= -cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E= -cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU= -cloud.google.com/go/oslogin v1.6.0/go.mod h1:zOJ1O3+dTU8WPlGEkFSh7qeHPPSoxrcMbbK1Nm2iX70= -cloud.google.com/go/oslogin v1.7.0/go.mod h1:e04SN0xO1UNJ1M5GP0vzVBFicIe4O53FOfcixIqTyXo= -cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0= -cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA= -cloud.google.com/go/policytroubleshooter v1.3.0/go.mod h1:qy0+VwANja+kKrjlQuOzmlvscn4RNsAc0e15GGqfMxg= -cloud.google.com/go/policytroubleshooter v1.4.0/go.mod h1:DZT4BcRw3QoO8ota9xw/LKtPa8lKeCByYeKTIf/vxdE= -cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0= -cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4= -cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o= -cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk= -cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo= -cloud.google.com/go/recaptchaenterprise/v2 v2.4.0/go.mod h1:Am3LHfOuBstrLrNCBrlI5sbwx9LBg3te2N6hGvHn2mE= -cloud.google.com/go/recaptchaenterprise/v2 v2.5.0/go.mod h1:O8LzcHXN3rz0j+LBC91jrwI3R+1ZSZEWrfL7XHgNo9U= -cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg= -cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4= -cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg= -cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c= -cloud.google.com/go/recommender v1.7.0/go.mod h1:XLHs/W+T8olwlGOgfQenXBTbIseGclClff6lhFVe9Bs= -cloud.google.com/go/recommender v1.8.0/go.mod h1:PkjXrTT05BFKwxaUxQmtIlrtj0kph108r02ZZQ5FE70= -cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y= -cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A= -cloud.google.com/go/redis v1.9.0/go.mod h1:HMYQuajvb2D0LvMgZmLDZW8V5aOC/WxstZHiy4g8OiA= -cloud.google.com/go/redis v1.10.0/go.mod h1:ThJf3mMBQtW18JzGgh41/Wld6vnDDc/F/F35UolRZPM= -cloud.google.com/go/resourcemanager v1.3.0/go.mod h1:bAtrTjZQFJkiWTPDb1WBjzvc6/kifjj4QBYuKCCoqKA= -cloud.google.com/go/resourcemanager v1.4.0/go.mod h1:MwxuzkumyTX7/a3n37gmsT3py7LIXwrShilPh3P1tR0= -cloud.google.com/go/resourcesettings v1.3.0/go.mod h1:lzew8VfESA5DQ8gdlHwMrqZs1S9V87v3oCnKCWoOuQU= -cloud.google.com/go/resourcesettings v1.4.0/go.mod h1:ldiH9IJpcrlC3VSuCGvjR5of/ezRrOxFtpJoJo5SmXg= -cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4= -cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY= -cloud.google.com/go/retail v1.10.0/go.mod h1:2gDk9HsL4HMS4oZwz6daui2/jmKvqShXKQuB2RZ+cCc= -cloud.google.com/go/retail v1.11.0/go.mod h1:MBLk1NaWPmh6iVFSz9MeKG/Psyd7TAgm6y/9L2B4x9Y= -cloud.google.com/go/run v0.2.0/go.mod h1:CNtKsTA1sDcnqqIFR3Pb5Tq0usWxJJvsWOCPldRU3Do= -cloud.google.com/go/run v0.3.0/go.mod h1:TuyY1+taHxTjrD0ZFk2iAR+xyOXEA0ztb7U3UNA0zBo= -cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s= -cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI= -cloud.google.com/go/scheduler v1.6.0/go.mod h1:SgeKVM7MIwPn3BqtcBntpLyrIJftQISRrYB5ZtT+KOk= -cloud.google.com/go/scheduler v1.7.0/go.mod h1:jyCiBqWW956uBjjPMMuX09n3x37mtyPJegEWKxRsn44= -cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA= -cloud.google.com/go/secretmanager v1.8.0/go.mod h1:hnVgi/bN5MYHd3Gt0SPuTPPp5ENina1/LxM+2W9U9J4= -cloud.google.com/go/secretmanager v1.9.0/go.mod h1:b71qH2l1yHmWQHt9LC80akm86mX8AL6X1MA01dW8ht4= -cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4= -cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0= -cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU= -cloud.google.com/go/security v1.9.0/go.mod h1:6Ta1bO8LXI89nZnmnsZGp9lVoVWXqsVbIq/t9dzI+2Q= -cloud.google.com/go/security v1.10.0/go.mod h1:QtOMZByJVlibUT2h9afNDWRZ1G96gVywH8T5GUSb9IA= -cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU= -cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc= -cloud.google.com/go/securitycenter v1.15.0/go.mod h1:PeKJ0t8MoFmmXLXWm41JidyzI3PJjd8sXWaVqg43WWk= -cloud.google.com/go/securitycenter v1.16.0/go.mod h1:Q9GMaLQFUD+5ZTabrbujNWLtSLZIZF7SAR0wWECrjdk= -cloud.google.com/go/servicecontrol v1.4.0/go.mod h1:o0hUSJ1TXJAmi/7fLJAedOovnujSEvjKCAFNXPQ1RaU= -cloud.google.com/go/servicecontrol v1.5.0/go.mod h1:qM0CnXHhyqKVuiZnGKrIurvVImCs8gmqWsDoqe9sU1s= -cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs= -cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg= -cloud.google.com/go/servicedirectory v1.6.0/go.mod h1:pUlbnWsLH9c13yGkxCmfumWEPjsRs1RlmJ4pqiNjVL4= -cloud.google.com/go/servicedirectory v1.7.0/go.mod h1:5p/U5oyvgYGYejufvxhgwjL8UVXjkuw7q5XcG10wx1U= -cloud.google.com/go/servicemanagement v1.4.0/go.mod h1:d8t8MDbezI7Z2R1O/wu8oTggo3BI2GKYbdG4y/SJTco= -cloud.google.com/go/servicemanagement v1.5.0/go.mod h1:XGaCRe57kfqu4+lRxaFEAuqmjzF0r+gWHjWqKqBvKFo= -cloud.google.com/go/serviceusage v1.3.0/go.mod h1:Hya1cozXM4SeSKTAgGXgj97GlqUvF5JaoXacR1JTP/E= -cloud.google.com/go/serviceusage v1.4.0/go.mod h1:SB4yxXSaYVuUBYUml6qklyONXNLt83U0Rb+CXyhjEeU= -cloud.google.com/go/shell v1.3.0/go.mod h1:VZ9HmRjZBsjLGXusm7K5Q5lzzByZmJHf1d0IWHEN5X4= -cloud.google.com/go/shell v1.4.0/go.mod h1:HDxPzZf3GkDdhExzD/gs8Grqk+dmYcEjGShZgYa9URw= -cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= -cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= -cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= -cloud.google.com/go/speech v1.9.0/go.mod h1:xQ0jTcmnRFFM2RfX/U+rk6FQNUF6DQlydUSyoooSpco= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= -cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= -cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= -cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= -cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= -cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g= -cloud.google.com/go/talent v1.3.0/go.mod h1:CmcxwJ/PKfRgd1pBjQgU6W3YBwiewmUzQYH5HHmSCmM= -cloud.google.com/go/talent v1.4.0/go.mod h1:ezFtAgVuRf8jRsvyE6EwmbTK5LKciD4KVnHuDEFmOOA= -cloud.google.com/go/texttospeech v1.4.0/go.mod h1:FX8HQHA6sEpJ7rCMSfXuzBcysDAuWusNNNvN9FELDd8= -cloud.google.com/go/texttospeech v1.5.0/go.mod h1:oKPLhR4n4ZdQqWKURdwxMy0uiTS1xU161C8W57Wkea4= -cloud.google.com/go/tpu v1.3.0/go.mod h1:aJIManG0o20tfDQlRIej44FcwGGl/cD0oiRyMKG19IQ= -cloud.google.com/go/tpu v1.4.0/go.mod h1:mjZaX8p0VBgllCzF6wcU2ovUXN9TONFLd7iz227X2Xg= -cloud.google.com/go/trace v1.3.0/go.mod h1:FFUE83d9Ca57C+K8rDl/Ih8LwOzWIV1krKgxg6N0G28= -cloud.google.com/go/trace v1.4.0/go.mod h1:UG0v8UBqzusp+z63o7FK74SdFE+AXpCLdFb1rshXG+Y= -cloud.google.com/go/translate v1.3.0/go.mod h1:gzMUwRjvOqj5i69y/LYLd8RrNQk+hOmIXTi9+nb3Djs= -cloud.google.com/go/translate v1.4.0/go.mod h1:06Dn/ppvLD6WvA5Rhdp029IX2Mi3Mn7fpMRLPvXT5Wg= -cloud.google.com/go/video v1.8.0/go.mod h1:sTzKFc0bUSByE8Yoh8X0mn8bMymItVGPfTuUBUyRgxk= -cloud.google.com/go/video v1.9.0/go.mod h1:0RhNKFRF5v92f8dQt0yhaHrEuH95m068JYOvLZYnJSw= -cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU= -cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4= -cloud.google.com/go/videointelligence v1.8.0/go.mod h1:dIcCn4gVDdS7yte/w+koiXn5dWVplOZkE+xwG9FgK+M= -cloud.google.com/go/videointelligence v1.9.0/go.mod h1:29lVRMPDYHikk3v8EdPSaL8Ku+eMzDljjuvRs105XoU= -cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0= -cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo= -cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo= -cloud.google.com/go/vision/v2 v2.4.0/go.mod h1:VtI579ll9RpVTrdKdkMzckdnwMyX2JILb+MhPqRbPsY= -cloud.google.com/go/vision/v2 v2.5.0/go.mod h1:MmaezXOOE+IWa+cS7OhRRLK2cNv1ZL98zhqFFZaaH2E= -cloud.google.com/go/vmmigration v1.2.0/go.mod h1:IRf0o7myyWFSmVR1ItrBSFLFD/rJkfDCUTO4vLlJvsE= -cloud.google.com/go/vmmigration v1.3.0/go.mod h1:oGJ6ZgGPQOFdjHuocGcLqX4lc98YQ7Ygq8YQwHh9A7g= -cloud.google.com/go/vpcaccess v1.4.0/go.mod h1:aQHVbTWDYUR1EbTApSVvMq1EnT57ppDmQzZ3imqIk4w= -cloud.google.com/go/vpcaccess v1.5.0/go.mod h1:drmg4HLk9NkZpGfCmZ3Tz0Bwnm2+DKqViEpeEpOq0m8= -cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE= -cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= -cloud.google.com/go/webrisk v1.6.0/go.mod h1:65sW9V9rOosnc9ZY7A7jsy1zoHS5W9IAXv6dGqhMQMc= -cloud.google.com/go/webrisk v1.7.0/go.mod h1:mVMHgEYH0r337nmt1JyLthzMr6YxwN1aAIEc2fTcq7A= -cloud.google.com/go/websecurityscanner v1.3.0/go.mod h1:uImdKm2wyeXQevQJXeh8Uun/Ym1VqworNDlBXQevGMo= -cloud.google.com/go/websecurityscanner v1.4.0/go.mod h1:ebit/Fp0a+FWu5j4JOmJEV8S8CzdTkAS77oDsiSqYWQ= -cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= -cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M= -cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BeatTime/bacnet v0.2.1 h1:Bs9DzPWilcvwOPvwXuyn/tYjDuln9Mng1d+Z6wRZDGs= -github.com/BeatTime/bacnet v0.2.1/go.mod h1:hDPKj40Is3JbYPoSgL6giQXslpQwxou64R2SixNPAos= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/DrmagicE/gmqtt v0.5.0 h1:CDg1bNmkXhKHwQoRMpKamqz0vWU40BguL/vg5sD4y7s= -github.com/DrmagicE/gmqtt v0.5.0/go.mod h1:iOdhUTFLsVbZMTX/p5uxcyQswYkBqQ4r8PZtd1C3Vs4= -github.com/Kowiste/ProfinetServer v0.0.0-20200929093941-9c422ae1f008 h1:61oQ1jLOU2K00wKzMu4OmT5vHQyB8yI4m2JZy/gonGU= -github.com/Kowiste/ProfinetServer v0.0.0-20200929093941-9c422ae1f008/go.mod h1:ZoTCmOIdEiUhWdG0j9OkdwJrqjtAabzcNLlbr0r8hMo= -github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= -github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/adrianmo/go-nmea v1.8.0 h1:KE6xDTMQNoKoyCb7IQRXGOIbn4WJlUKwIuRD4LbpKlM= -github.com/adrianmo/go-nmea v1.8.0/go.mod h1:u8bPnpKt/D/5rll/5l9f6iDfeq5WZW0+/SXdkwix6Tg= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/blastrain/vitess-sqlparser v0.0.0-20201030050434-a139afbb1aba h1:hBK2BWzm0OzYZrZy9yzvZZw59C5Do4/miZ8FhEwd5P8= -github.com/blastrain/vitess-sqlparser v0.0.0-20201030050434-a139afbb1aba/go.mod h1:FGQp+RNQwVmLzDq6HBrYCww9qJQyNwH9Qji/quTQII4= -github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= -github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= -github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= -github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= -github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/goselect v0.1.2 h1:2DNy14+JPjRBgPzAd1thbQp4BSIihxcBf0IXhQXDRa0= -github.com/creack/goselect v0.1.2/go.mod h1:a/NhLweNvqIYMuxcMOuWY516Cimucms3DglDzQP3hKY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dsnet/golib/memfile v0.0.0-20190531212259-571cdbcff553/go.mod h1:tXGNW9q3RwvWt1VV2qrRKlSSz0npnh12yftCSCy2T64= -github.com/dsnet/golib/memfile v0.0.0-20200723050859-c110804dfa93/go.mod h1:tXGNW9q3RwvWt1VV2qrRKlSSz0npnh12yftCSCy2T64= -github.com/dsnet/golib/memfile v1.0.0 h1:J9pUspY2bDCbF9o+YGwcf3uG6MdyITfh/Fk3/CaEiFs= -github.com/dsnet/golib/memfile v1.0.0/go.mod h1:tXGNW9q3RwvWt1VV2qrRKlSSz0npnh12yftCSCy2T64= -github.com/eclipse/paho.mqtt.golang v1.4.2 h1:66wOzfUHSSI1zamx7jR6yMEI5EuHnT1G6rNA5PM12m4= -github.com/eclipse/paho.mqtt.golang v1.4.2/go.mod h1:JGt0RsEwEX+Xa/agj90YJ9d9DH2b7upDZMK9HRbFvCA= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= -github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= -github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= -github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= -github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U= -github.com/gin-contrib/static v0.0.1/go.mod h1:CSxeF+wep05e0kCOsqWdAWbSszmc31zTIbD8TvWl7Hs= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= -github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-acme/lego v2.7.2+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= -github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-ocf/go-coap/v2 v2.0.4-0.20200728125043-f38b86f047a7/go.mod h1:X9wVKcaOSx7wBxKcvrWgMQq1R2DNeA7NBLW2osIb8TM= -github.com/go-ocf/kit v0.0.0-20200728130040-4aebdb6982bc/go.mod h1:TIsoMT/iB7t9P6ahkcOnsmvS83SIJsv9qXRfz/yLf6M= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= -github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= -github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= -github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/goburrow/modbus v0.1.0 h1:DejRZY73nEM6+bt5JSP6IsFolJ9dVcqxsYbpLbeW/ro= -github.com/goburrow/modbus v0.1.0/go.mod h1:Kx552D5rLIS8E7TyUwQ/UdHEqvX5T8tyiGBTlzMcZBg= -github.com/goburrow/serial v0.1.0 h1:v2T1SQa/dlUqQiYIT8+Cu7YolfqAi3K96UmhwYyuSrA= -github.com/goburrow/serial v0.1.0/go.mod h1:sAiqG0nRVswsm1C97xsttiYCzSLBmUZ/VSlVLZJ8haA= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= -github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= -github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= -github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= -github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= -github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= -github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= -github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= -github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= -github.com/gopcua/opcua v0.3.15 h1:l0hS2gUTSfN5n604lbf90TyRuHjgEO/T/sq5DVWn8sE= -github.com/gopcua/opcua v0.3.15/go.mod h1:DVDwHvR5lYgO9T4nTn+QxzGl6VQMywgaRgmOH1skBps= -github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gosnmp/gosnmp v1.35.0 h1:EuWWNPxTCdAUx2/NbQcSa3WdNxjzpy4Phv57b4MWpJM= -github.com/gosnmp/gosnmp v1.35.0/go.mod h1:2AvKZ3n9aEl5TJEo/fFmf/FGO4Nj4cVeEc5yuk88CYc= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 h1:0IKlLyQ3Hs9nDaiK5cSHAGmcQEIC8l2Ts1u6x5Dfrqg= -github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= -github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= -github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= -github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= -github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= -github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= -github.com/hootrhino/go-ais v1.0.0 h1:7SSOn3XCB4I4o7SAJ8RvJ4jhqI9w3rVU379jgINCuhA= -github.com/hootrhino/go-ais v1.0.0/go.mod h1:QsnHNr4Xcj6xEfa32MmUmhAc1i0BtJZzi4rSZKftw1M= -github.com/hootrhino/gopher-lua v1.0.0 h1:6kYVenNQYvWdqf4sd2KXOr4XUPKyDZqrxW0PNIM061E= -github.com/hootrhino/gopher-lua v1.0.0/go.mod h1:tY0TknOctxfkzkx60g+po3hj7K1R+YdwLYqT4OqAINc= -github.com/hootrhino/wmi v0.0.0-20230603082700-cfa077a8cf01 h1:oPtZwF/Th9FuFZH4bv0otm6de/5ewcqfaf6pVI/Xfwc= -github.com/hootrhino/wmi v0.0.0-20230603082700-cfa077a8cf01/go.mod h1:RmN9Gg8TiRseWz6DqrfekUqlRWzUtLJonWUwyfTdcu0= -github.com/iancoleman/strcase v0.1.2/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU= -github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4= -github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= -github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg= -github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= -github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= -github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= -github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/juju/errors v0.0.0-20170703010042-c7d06af17c68 h1:d2hBkTvi7B89+OXY8+bBBshPlc+7JYacGrG/dFak8SQ= -github.com/juju/errors v0.0.0-20170703010042-c7d06af17c68/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= -github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8 h1:UUHMLvzt/31azWTN/ifGWef4WUqvXk0iRqdhdy/2uzI= -github.com/juju/loggo v0.0.0-20190526231331-6e530bcce5d8/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= -github.com/juju/testing v0.0.0-20191001232224-ce9dec17d28b h1:Rrp0ByJXEjhREMPGTt3aWYjoIsUGCbt21ekbeJcTWv0= -github.com/juju/testing v0.0.0-20191001232224-ce9dec17d28b/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= -github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= -github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lestrrat-go/iter v0.0.0-20200422075355-fc1769541911/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= -github.com/lestrrat-go/jwx v1.0.2/go.mod h1:TPF17WiSFegZo+c20fdpw49QD+/7n4/IsGvEmCSWwT0= -github.com/lestrrat-go/pdebug v0.0.0-20200204225717-4d6bd78da58d/go.mod h1:B06CSso/AWxiPejj+fheUINGeBKeeEZNt8w+EoU7+L8= -github.com/lithammer/shortuuid/v4 v4.0.0 h1:QRbbVkfgNippHOS8PXDkti4NaWeyYfcBTHtw7k08o4c= -github.com/lithammer/shortuuid/v4 v4.0.0/go.mod h1:Zs8puNcrvf2rV9rTH51ZLLcj7ZXqQI3lv67aw4KiB1Y= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a h1:N9zuLhTvBSRt0gWSiJswwQ2HqDmtX/ZCDJURnKUt1Ik= -github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/makiuchi-d/gozxing v0.1.1 h1:xxqijhoedi+/lZlhINteGbywIrewVdVv2wl9r5O9S1I= -github.com/makiuchi-d/gozxing v0.1.1/go.mod h1:eRIHbOjX7QWxLIDJoQuMLhuXg9LAuw6znsUtRkNw9DU= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= -github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= -github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= -github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mochi-co/mqtt/v2 v2.2.12 h1:g7JlVF3UNtkpoXOF5f3+I8gWTqByya+QhNEqZxUEjZg= -github.com/mochi-co/mqtt/v2 v2.2.12/go.mod h1:MDMTThFgWj/LjJ6wc51bP5l4xnJG/ahpc9tR9vZVf8Q= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= -github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= -github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1 h1:BuVRHr4HHJbk1DHyWkArJ7E8J/VA8ncCr/VLnQFazBo= -github.com/muka/go-bluetooth v0.0.0-20221213043340-85dc80edc4e1/go.mod h1:dMCjicU6vRBk34dqOmIZm0aod6gUwZXOXzBROqGous0= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt/v2 v2.4.1 h1:Y35W1dgbbz2SQUYDPCaclXcuqleVmpbRa7646Jf2EX4= -github.com/nats-io/nats-server/v2 v2.9.17 h1:gFpUQ3hqIDJrnqog+Bl5vaXg+RhhYEZIElasEuRn2tw= -github.com/nats-io/nats-server/v2 v2.9.17/go.mod h1:eQysm3xDZmIjfkjr7DuD9DjRFpnxQc2vKVxtEg0Dp6s= -github.com/nats-io/nats.go v1.26.0 h1:fWJTYPnZ8DzxIaqIHOAMfColuznchnd5Ab5dbJpgPIE= -github.com/nats-io/nats.go v1.26.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= -github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA= -github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= -github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/panjf2000/ants/v2 v2.4.3/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A= -github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= -github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/patrikeh/go-deep v0.0.0-20230427173908-a2775168ab3d h1:uklDHZ8eaoO7TzqTu1bk/ijlkfadd8ogGfit4oIeSik= -github.com/patrikeh/go-deep v0.0.0-20230427173908-a2775168ab3d/go.mod h1:W7GtTeZHpwautuPVtKBFp1+df69GkwlOGD2cwvYeYIE= -github.com/paypal/gatt v0.0.0-20151011220935-4ae819d591cf/go.mod h1:+AwQL2mK3Pd3S+TUwg0tYQjid0q1txyNUJuuSmz8Kdk= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= -github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= -github.com/pion/dtls/v2 v2.0.1-0.20200503085337-8e86b3a7d585/go.mod h1:/GahSOC8ZY/+17zkaGJIG4OUkSGAcZu/N/g3roBOCkM= -github.com/pion/dtls/v2 v2.0.10-0.20210502094952-3dc563b9aede/go.mod h1:86wv5dgx2J/z871nUR+5fTTY9tISLUlo+C5Gm86r1Hs= -github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= -github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE= -github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= -github.com/pion/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZIWJ6q9A= -github.com/pion/transport/v2 v2.2.1 h1:7qYnCBlpgSJNYMbLCKuSY9KbQdBFoETvPNETv0y4N7c= -github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= -github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= -github.com/plgd-dev/go-coap/v2 v2.6.0 h1:T8tefZK4jag1ssr6gAGU+922QhVcrjk207aPhdg7i3o= -github.com/plgd-dev/go-coap/v2 v2.6.0/go.mod h1:wm9fcL58Ky442Krix74S9Y54rCo36u59xFcYKRQaSBg= -github.com/plgd-dev/kit v0.0.0-20200819113605-d5fcf3e94f63/go.mod h1:Yl9zisyXfPdtP9hTWlJqjJYXmgU/jtSDKttz9/CeD90= -github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 h1:TC1HJ/UbyflJFPvaOdGmNZ5TeFGex1/dyr9urNGLy7M= -github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90/go.mod h1:Z7oKFLSGQjdi8eInxwFCs0tSApuEM1o0qNck+sJYp4M= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.4.0 h1:YVIb/fVcOTMSqtqZWSKnHpSLBxu8DKgxq8z6RuBZwqI= -github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= -github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM= -github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk= -github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= -github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM= -github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg= -github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= -github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/robinson/gos7 v0.0.0-20230421131203-d20ac6ca08cd h1:UhVHgo6tdrKiuVqxTd63ja0B9YihC7D3z8hfEye6Vqo= -github.com/robinson/gos7 v0.0.0-20230421131203-d20ac6ca08cd/go.mod h1:/gqBMUg6JbR1JKVqIK4ZKCtWDUq/cfrh+hVH8Ak/35A= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= -github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= -github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil/v3 v3.23.5 h1:5SgDCeQ0KW0S4N0znjeM/eFHXXOKyv2dVNgRq/c9P6Y= -github.com/shirou/gopsutil/v3 v3.23.5/go.mod h1:Ng3Maa27Q2KARVJ0SPZF5NdrQSC3XHKP8IIWrHgMeLY= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= -github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= -github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/suapapa/go_eddystone v1.3.1 h1:mfW3eNoRPpaZ0iARRZtEyudFfNFtytqeCexwXg1wIKE= -github.com/suapapa/go_eddystone v1.3.1/go.mod h1:bXC11TfJOS+3g3q/Uzd7FKd5g62STQEfeEIhcKe4Qy8= -github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= -github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= -github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= -github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= -github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w= -github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07 h1:UyzmZLoiDWMRywV4DUYb9Fbt8uiOSooupjTq10vpvnU= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/tbrandon/mbserver v0.0.0-20211210035124-daf3c8c4269f h1:RSsPHbWJpo/IaGb+7S7hNIQtuLfli2kIi97clK7BW/o= -github.com/tbrandon/mbserver v0.0.0-20211210035124-daf3c8c4269f/go.mod h1:qUzPVlSj2UgxJkVbH0ZwuuiR46U8RBMDT5KLY78Ifpw= -github.com/thinkgos/go-iecp5 v1.2.1 h1:p5l8FGNtMpOQ2BMCmUHT+3eSG/Ley6Uv6xFt5j8MNFI= -github.com/thinkgos/go-iecp5 v1.2.1/go.mod h1:jUgKVFgiyamwD0/eWgx3wbGcVojeiTouvJsLe6CyKmM= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= -github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= -github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= -github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc= -github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.12.0/go.mod h1:229t1eWu9UXTPmoUkbpN/fctKPBY4IJoFXQnxHGXy6E= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/wwhai/gomodbus v0.2.4 h1:PHSzIv7YtVJh8yCAD1BPerLbHZut7QluDiKi+1gDhus= -github.com/wwhai/gomodbus v0.2.4/go.mod h1:+ke0zV8eHAvlDSRooGJshCOB+dSEQBfOWfTBadrdi9A= -github.com/wwhai/goserial v0.2.0 h1:kl+rJXGsSM9HMIwmZTVEyBXiJpp/gjIzQzrY/gQSnYI= -github.com/wwhai/goserial v0.2.0/go.mod h1:Uj8aER/uh/cDyzxzkV3KGl6GzcJCmC6hkBlJtgp5PTU= -github.com/wwhai/ntp v0.3.0 h1:pH3R36pFdoF3srjvqT3J0C4NOb/Tt++hYFmEMT9giiA= -github.com/wwhai/ntp v0.3.0/go.mod h1:WCmadLV7QTOxPOyXlBVNttH3OcLU0xp0GqBLtl9G22U= -github.com/wwhai/tarmserial v1.0.0 h1:vxm3PZncXfYr4I/N3yAK2ouFMdLRFxLcHHvVEh0gf0Q= -github.com/wwhai/tarmserial v1.0.0/go.mod h1:bim1tzdGKaJlYrSE38JRRxC1Pqz55oYSZJH3TlmYR+I= -github.com/wwhai/tinycache v0.0.0-20191004192108-46f407853014 h1:ILKCpEBNUfC1iwUqCmVB/E2Mk9dLkspPcF2+eYJIi+M= -github.com/wwhai/tinycache v0.0.0-20191004192108-46f407853014/go.mod h1:YSnIPMAVDKDpSAMV+ju1PoTC3LN83+ZP0UnK8bIswjQ= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= -github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= -github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= -github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= -github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c= -github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI= -github.com/xuri/excelize/v2 v2.7.1 h1:gm8q0UCAyaTt3MEF5wWMjVdmthm2EHAWesGSKS9tdVI= -github.com/xuri/excelize/v2 v2.7.1/go.mod h1:qc0+2j4TvAUrBw36ATtcTeC1VCM0fFdAXZOmcF4nTpY= -github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M= -github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -go.bug.st/serial v1.5.0 h1:ThuUkHpOEmCVXxGEfpoExjQCS2WBVV4ZcUKVYInM9T4= -go.bug.st/serial v1.5.0/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.mongodb.org/mongo-driver v1.11.6 h1:XM7G6PjiGAO5betLF13BIa5TlLUUE3uJ/2Ox3Lz1K+o= -go.mongodb.org/mongo-driver v1.11.6/go.mod h1:G9TgswdsWjX4tmDA5zfs2+6AEPpYJwqblyjsfuh8oXY= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= -go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= -golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI= -golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210502030024-e5908800b52b/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221012135044-0b7e1fb9d458/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= -golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.0.0-20180302201248-b7ef84aaf62a/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200417140056-c07e33ef3290/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20200925191224-5d1fdd8fa346/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g= -google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= -google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= -google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= -google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= -google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= -google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= -google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= -google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g= -google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw= -google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI= -google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s= -google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91A08= -google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= -google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= -google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= -google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= -google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE= -google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc= -google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk= -google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo= -google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw= -google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI= -google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U= -google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM= -google.golang.org/genproto v0.0.0-20221024153911-1573dae28c9c/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221024183307-1bc688fe9f3e/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s= -google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo= -google.golang.org/genproto v0.0.0-20221201204527-e3fa12d562f3/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= -google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a h1:fwgW9j3vHirt4ObdHoYNwuO24BEZjSzbh+zPaNWoiY8= -google.golang.org/genproto v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:EMfReVxb80Dq1hhioy0sOsY9jCE46YDgHlJ7fWVUWRE= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= -google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= -google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= -google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw= -gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= -gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= -gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= -gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/driver/sqlite v1.5.1 h1:hYyrLkAWE71bcarJDPdZNTLWtr8XrSjOWyjUYI6xdL4= -gorm.io/driver/sqlite v1.5.1/go.mod h1:7MZZ2Z8bqyfSQA1gYEV6MagQWj3cpUkJj9Z+d1HEMEQ= -gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64= -gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go index 7d7039e28..c034cd9ff 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "runtime" "time" + _ "github.com/hootrhino/rulex/component/cron_task/docs" "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/ossupport" "github.com/hootrhino/rulex/typex" From acc8888eeaff1d72a9ec3b2cfcdc8d444e8a0874 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 3 Dec 2023 18:29:19 +0800 Subject: [PATCH 077/138] dev: add event bus --- component/intereventbus/intereventbus.go | 45 +++- component/intereventbus/intereventbus.md | 38 ++++ component/interqueue/xqueue.go | 176 +++++++++++++-- component/rtspserver/rtsp_server.go | 2 +- conf/rulex.ini | 2 +- core/ui_schema_cache.go | 2 +- engine/engine.go | 79 ++++--- engine/runner.go | 4 +- .../modbuscrc_tools.go | 0 .../modbuscrc_tools.md | 0 .../modbuscrc_tools_service.go | 0 plugin/rulex_api_server/apis/device_api.go | 19 +- plugin/rulex_api_server/apis/inend_api.go | 20 +- plugin/rulex_api_server/apis/rule_api.go | 211 ++++++++---------- plugin/rulex_api_server/model/model.go | 1 - .../rulex_api_server/server/res_supervisor.go | 35 ++- source/internal_event_source.go | 5 + source/internal_event_source.md | 4 +- test/conf/rulex.ini | 2 +- typex/version.go | 4 +- typex/xdevice.go | 5 + 21 files changed, 457 insertions(+), 197 deletions(-) create mode 100644 component/intereventbus/intereventbus.md rename plugin/{modbuscrc_tools => modbus_crc_tools}/modbuscrc_tools.go (100%) rename plugin/{modbuscrc_tools => modbus_crc_tools}/modbuscrc_tools.md (100%) rename plugin/{modbuscrc_tools => modbus_crc_tools}/modbuscrc_tools_service.go (100%) diff --git a/component/intereventbus/intereventbus.go b/component/intereventbus/intereventbus.go index 38a73a807..dc81279f3 100644 --- a/component/intereventbus/intereventbus.go +++ b/component/intereventbus/intereventbus.go @@ -17,12 +17,14 @@ package intereventbus import ( "context" + "errors" + "fmt" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" ) -var __DefaultInternalEventSource *InternalEventBus +var __DefaultInternalEventBus *InternalEventBus // --------------------------------------------------------- // Type @@ -34,6 +36,28 @@ type BaseEvent struct { Info interface{} } +/* +* +* Push +* + */ +func Push(e BaseEvent) error { + if len(__DefaultInternalEventBus.Queue)+1 > __DefaultInternalEventBus.GetSize() { + msg := fmt.Sprintf("attached max queue size, max size is:%v, current size is: %v", + __DefaultInternalEventBus.GetSize(), len(__DefaultInternalEventBus.Queue)+1) + glogger.GLogger.Error(msg) + return errors.New(msg) + } else { + __DefaultInternalEventBus.Queue <- e + return nil + } +} + +/* +* +* 内部事件总线 +* + */ type InternalEventBus struct { Queue chan BaseEvent Rulex typex.RuleX @@ -50,10 +74,11 @@ func (q *InternalEventBus) GetSize() int { * */ -func InitInternalEventSource(r typex.RuleX) *InternalEventBus { - __DefaultInternalEventSource = new(InternalEventBus) - __DefaultInternalEventSource.Rulex = r - return __DefaultInternalEventSource +func InitInternalEventBus(r typex.RuleX, MaxQueueSize int) *InternalEventBus { + __DefaultInternalEventBus = new(InternalEventBus) + __DefaultInternalEventBus.Queue = make(chan BaseEvent, MaxQueueSize) + __DefaultInternalEventBus.Rulex = r + return __DefaultInternalEventBus } /* @@ -62,17 +87,17 @@ func InitInternalEventSource(r typex.RuleX) *InternalEventBus { * */ func StartInternalEventQueue() { - go func(ctx context.Context, InternalEventBus InternalEventBus) { + go func(ctx context.Context, InternalEventBus *InternalEventBus) { for { select { case <-ctx.Done(): return - case Event := <-__DefaultInternalEventSource.Queue: + case Event := <-InternalEventBus.Queue: { - glogger.GLogger.Debug("Event:", Event) - + // Push to device Queue + glogger.GLogger.Debug("Internal Event:", Event) } } } - }(typex.GCTX, *__DefaultInternalEventSource) + }(typex.GCTX, __DefaultInternalEventBus) } diff --git a/component/intereventbus/intereventbus.md b/component/intereventbus/intereventbus.md new file mode 100644 index 000000000..9f2752a8d --- /dev/null +++ b/component/intereventbus/intereventbus.md @@ -0,0 +1,38 @@ +# 内部消息源 +可以使用这个数据源来监控系统内部的消息,比如设备离线,资源连接失败等。 + +## 消息类型 +- SOURCE: 南向事件 +- DEVICE: 设备事件 +- TARGET: 北向事件 +- SYSTEM: 系统内部事件 +- HARDWARE: 硬件事件 + +## 示例 +### 设备上线: +```json +{ + "type" :"DEVICE", + "event":"event.connected", + "ts":121312431432, + "device_info":{ + "uuid":"UUID1234567", + "name":"温湿度计" + } +} + +``` + +### 设备离线: +```json +{ + "type" :"DEVICE", + "event":"event.disconnected", + "ts":121312431432, + "device_info":{ + "uuid":"UUID1234567", + "name":"温湿度计" + } +} + +``` \ No newline at end of file diff --git a/component/interqueue/xqueue.go b/component/interqueue/xqueue.go index 4222b9483..bb13a0f3c 100644 --- a/component/interqueue/xqueue.go +++ b/component/interqueue/xqueue.go @@ -19,6 +19,9 @@ var DefaultDataCacheQueue XQueue */ type XQueue interface { GetQueue() chan QueueData + GetInQueue() chan QueueData + GetOutQueue() chan QueueData + GetDeviceQueue() chan QueueData GetSize() int Push(QueueData) error PushQueue(QueueData) error @@ -52,14 +55,20 @@ func (qd QueueData) String() string { * */ type DataCacheQueue struct { - Queue chan QueueData - rulex typex.RuleX + Queue chan QueueData + OutQueue chan QueueData + InQueue chan QueueData + DeviceQueue chan QueueData + rulex typex.RuleX } func InitDataCacheQueue(rulex typex.RuleX, maxQueueSize int) XQueue { DefaultDataCacheQueue = &DataCacheQueue{ - Queue: make(chan QueueData, maxQueueSize), - rulex: rulex, + Queue: make(chan QueueData, maxQueueSize), + OutQueue: make(chan QueueData, maxQueueSize), + InQueue: make(chan QueueData, maxQueueSize), + DeviceQueue: make(chan QueueData, maxQueueSize), + rulex: rulex, } return DefaultDataCacheQueue } @@ -96,6 +105,33 @@ func (q *DataCacheQueue) GetQueue() chan QueueData { return q.Queue } +/* +* +* GetQueue +* + */ +func (q *DataCacheQueue) GetInQueue() chan QueueData { + return q.InQueue +} + +/* +* +* GetQueue +* + */ +func (q *DataCacheQueue) GetOutQueue() chan QueueData { + return q.OutQueue +} + +/* +* +*GetDeviceQueue +* + */ +func (q *DataCacheQueue) GetDeviceQueue() chan QueueData { + return q.DeviceQueue +} + // TODO: 下个版本更换为可扩容的Chan func StartDataCacheQueue() { @@ -106,22 +142,43 @@ func StartDataCacheQueue() { return // 这个地方不能阻塞,需要借助一个外部queue // push qd -> Queue - case qd := <-xQueue.GetQueue(): + case qd := <-xQueue.GetInQueue(): + { + if qd.I != nil { + qd.E.RunSourceCallbacks(qd.I, qd.Data) + } + } + case qd := <-xQueue.GetDeviceQueue(): + { + if qd.D != nil { + qd.E.RunDeviceCallbacks(qd.D, qd.Data) + } + } + case qd := <-xQueue.GetOutQueue(): + { + if qd.O != nil { + v, ok := qd.E.AllOutEnd().Load(qd.O.UUID) + if ok { + target := v.(*typex.OutEnd).Target + if target == nil { + continue + } + if _, err := target.To(qd.Data); err != nil { + glogger.GLogger.Error(err) + intermetric.IncOutFailed() + } else { + intermetric.IncOut() + } + } + } + } + case qd := <-xQueue.GetQueue(): // 马上废弃 { - // - // Rulex内置消息队列用法: - // 1 进来的数据缓存 - // 2 出去的消息缓存 - // 3 设备数据缓存 - // 只需要判断 in 或者 out 是不是 nil即可 - // if qd.I != nil { - // 如果是Debug消息直接打印出来 qd.E.RunSourceCallbacks(qd.I, qd.Data) } if qd.D != nil { qd.E.RunDeviceCallbacks(qd.D, qd.Data) - qd.E.RunHooks(qd.Data) } if qd.O != nil { v, ok := qd.E.AllOutEnd().Load(qd.O.UUID) @@ -144,6 +201,11 @@ func StartDataCacheQueue() { }(typex.GCTX, DefaultDataCacheQueue) } +/* +* +* +* + */ func (q *DataCacheQueue) PushQueue(qd QueueData) error { err := DefaultDataCacheQueue.Push(qd) if err != nil { @@ -154,6 +216,12 @@ func (q *DataCacheQueue) PushQueue(qd QueueData) error { } return err } + +/* +* +*PushInQueue +* + */ func (q *DataCacheQueue) PushInQueue(in *typex.InEnd, data string) error { qd := QueueData{ E: q.rulex, @@ -161,9 +229,9 @@ func (q *DataCacheQueue) PushInQueue(in *typex.InEnd, data string) error { O: nil, Data: data, } - err := DefaultDataCacheQueue.Push(qd) + err := q.pushIn(qd) if err != nil { - glogger.GLogger.Error("PushInQueue error:", err) + glogger.GLogger.Error("Push InQueue error:", err) intermetric.IncInFailed() } else { intermetric.IncIn() @@ -173,7 +241,7 @@ func (q *DataCacheQueue) PushInQueue(in *typex.InEnd, data string) error { /* * -* 设备数据入流引擎 +* PushDeviceQueue * */ func (q *DataCacheQueue) PushDeviceQueue(Device *typex.Device, data string) error { @@ -184,15 +252,21 @@ func (q *DataCacheQueue) PushDeviceQueue(Device *typex.Device, data string) erro O: nil, Data: data, } - err := DefaultDataCacheQueue.Push(qd) + err := q.pushDevice(qd) if err != nil { - glogger.GLogger.Error("PushInQueue error:", err) + glogger.GLogger.Error("Push Device Queue error:", err) intermetric.IncInFailed() } else { intermetric.IncIn() } return err } + +/* +* +* PushOutQueue +* + */ func (q *DataCacheQueue) PushOutQueue(out *typex.OutEnd, data string) error { qd := QueueData{ E: q.rulex, @@ -201,12 +275,72 @@ func (q *DataCacheQueue) PushOutQueue(out *typex.OutEnd, data string) error { O: out, Data: data, } - err := DefaultDataCacheQueue.Push(qd) + err := q.pushOut(qd) if err != nil { - glogger.GLogger.Error("PushOutQueue error:", err) + glogger.GLogger.Error("Push OutQueue error:", err) intermetric.IncInFailed() } else { intermetric.IncIn() } return err } + +/* +* +* Push +* + */ +func (q *DataCacheQueue) pushIn(d QueueData) error { + // 动态扩容 + // if len(q.Queue)+1 > q.GetSize() { + // } + if len(q.InQueue)+1 > q.GetSize() { + msg := fmt.Sprintf("attached max queue size, max size is:%v, current size is: %v", + q.GetSize(), len(q.Queue)+1) + glogger.GLogger.Error(msg) + return errors.New(msg) + } else { + q.InQueue <- d + return nil + } +} + +/* +* +* Push +* + */ +func (q *DataCacheQueue) pushOut(d QueueData) error { + // 动态扩容 + // if len(q.Queue)+1 > q.GetSize() { + // } + if len(q.OutQueue)+1 > q.GetSize() { + msg := fmt.Sprintf("attached max queue size, max size is:%v, current size is: %v", + q.GetSize(), len(q.Queue)+1) + glogger.GLogger.Error(msg) + return errors.New(msg) + } else { + q.OutQueue <- d + return nil + } +} + +/* +* +* Push +* + */ +func (q *DataCacheQueue) pushDevice(d QueueData) error { + // 动态扩容 + // if len(q.Queue)+1 > q.GetSize() { + // } + if len(q.DeviceQueue)+1 > q.GetSize() { + msg := fmt.Sprintf("attached max queue size, max size is:%v, current size is: %v", + q.GetSize(), len(q.Queue)+1) + glogger.GLogger.Error(msg) + return errors.New(msg) + } else { + q.DeviceQueue <- d + return nil + } +} diff --git a/component/rtspserver/rtsp_server.go b/component/rtspserver/rtsp_server.go index 73837bc0d..c0abed69a 100644 --- a/component/rtspserver/rtsp_server.go +++ b/component/rtspserver/rtsp_server.go @@ -53,7 +53,7 @@ type rtspServer struct { } // NewRouter Gin 路由配置 -func InitRtspServer() *rtspServer { +func InitRtspServer(rulex typex.RuleX) *rtspServer { gin.SetMode(gin.ReleaseMode) __DefaultRtspServer = &rtspServer{ webServer: gin.New(), diff --git a/conf/rulex.ini b/conf/rulex.ini index ccf3bcadb..2e8e6d7e9 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -173,7 +173,7 @@ enable = true # # Modbus CRC calculator # -[plugin.modbuscrc_tools] +[plugin.modbus_crc_tools] # # Enable # diff --git a/core/ui_schema_cache.go b/core/ui_schema_cache.go index 7a09686b8..674e65520 100644 --- a/core/ui_schema_cache.go +++ b/core/ui_schema_cache.go @@ -33,7 +33,7 @@ var __lock sync.Mutex * 初始化缓冲器 * */ -func InitInternalSchemaCache() { +func InitInternalSchemaCache(rulex typex.RuleX) { __InternalSchemaCache = make(map[string]typex.DataSchema) __lock = sync.Mutex{} } diff --git a/engine/engine.go b/engine/engine.go index 77f02af78..df4f1c01b 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -28,6 +28,7 @@ import ( "github.com/hootrhino/rulex/component/datacenter" "github.com/hootrhino/rulex/component/hwportmanager" "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/intereventbus" "github.com/hootrhino/rulex/component/intermetric" "github.com/hootrhino/rulex/component/interqueue" "github.com/hootrhino/rulex/component/rtspserver" @@ -82,6 +83,14 @@ func InitRuleEngine(config typex.RulexConfig) typex.RuleX { } // Internal DB interdb.Init(__DefaultRuleEngine, __DEFAULT_DB_PATH) + // Internal Bus + intereventbus.InitInternalEventBus(__DefaultRuleEngine, core.GlobalConfig.MaxQueueSize) + // 前后交互组件 + interqueue.InitInteractQueue(__DefaultRuleEngine, core.GlobalConfig.MaxQueueSize) + // Web Pipeline + core.InitWebDataPipe(__DefaultRuleEngine) + // Internal Schema + core.InitInternalSchemaCache(__DefaultRuleEngine) // Load hardware Port Manager hwportmanager.InitHwPortsManager(__DefaultRuleEngine) // Internal Metric @@ -96,21 +105,26 @@ func InitRuleEngine(config typex.RulexConfig) typex.RuleX { interqueue.InitDataCacheQueue(__DefaultRuleEngine, core.GlobalConfig.MaxQueueSize) // Data center datacenter.InitDataCenter(__DefaultRuleEngine) + // Rtsp server + rtspserver.InitRtspServer(__DefaultRuleEngine) return __DefaultRuleEngine } +/* +* +* Engine Start +* + */ func (e *RuleEngine) Start() *typex.RulexConfig { + // Resource Manager e.InitDeviceTypeManager() e.InitSourceTypeManager() e.InitTargetTypeManager() // 内部队列 - interqueue.InitDataCacheQueue(e, core.GlobalConfig.MaxQueueSize) interqueue.StartDataCacheQueue() - // 前后交互组件 - interqueue.InitInteractQueue(e, core.GlobalConfig.MaxQueueSize) - core.InitWebDataPipe(e) - core.InitInternalSchemaCache() - rtspserver.InitRtspServer() + // InternalEventQueue + intereventbus.StartInternalEventQueue() + // WebDataPip go core.StartWebDataPipe() return e.Config } @@ -211,20 +225,18 @@ func (e *RuleEngine) RunSourceCallbacks(in *typex.InEnd, callbackArgs string) { // 执行来自资源的脚本 for _, rule := range in.BindRules { if rule.Status == typex.RULE_RUNNING { - if rule.Type == "lua" { - _, errA := core.ExecuteActions(&rule, lua.LString(callbackArgs)) - if errA != nil { - glogger.GLogger.Error("RunLuaCallbacks error:", errA) - _, err0 := core.ExecuteFailed(rule.LuaVM, lua.LString(errA.Error())) - if err0 != nil { - glogger.GLogger.Error(err0) - } - } else { - _, errS := core.ExecuteSuccess(rule.LuaVM) - if errS != nil { - glogger.GLogger.Error(errS) - return // lua 是规则链,有短路原则,中途出错会中断 - } + _, errA := core.ExecuteActions(&rule, lua.LString(callbackArgs)) + if errA != nil { + glogger.GLogger.Error("RunLuaCallbacks error:", errA) + _, err0 := core.ExecuteFailed(rule.LuaVM, lua.LString(errA.Error())) + if err0 != nil { + glogger.GLogger.Error(err0) + } + } else { + _, errS := core.ExecuteSuccess(rule.LuaVM) + if errS != nil { + glogger.GLogger.Error(errS) + return // lua 是规则链,有短路原则,中途出错会中断 } } } @@ -239,23 +251,20 @@ func (e *RuleEngine) RunSourceCallbacks(in *typex.InEnd, callbackArgs string) { func (e *RuleEngine) RunDeviceCallbacks(Device *typex.Device, callbackArgs string) { for _, rule := range Device.BindRules { if rule.Status == typex.RULE_RUNNING { - if rule.Type == "lua" { - _, errA := core.ExecuteActions(&rule, lua.LString(callbackArgs)) - if errA != nil { - glogger.GLogger.Error("RunLuaCallbacks error:", errA) - _, err1 := core.ExecuteFailed(rule.LuaVM, lua.LString(errA.Error())) - if err1 != nil { - glogger.GLogger.Error(err1) - } - } else { - _, err2 := core.ExecuteSuccess(rule.LuaVM) - if err2 != nil { - glogger.GLogger.Error(err2) - return - } + _, errA := core.ExecuteActions(&rule, lua.LString(callbackArgs)) + if errA != nil { + glogger.GLogger.Error("RunLuaCallbacks error:", errA) + _, err1 := core.ExecuteFailed(rule.LuaVM, lua.LString(errA.Error())) + if err1 != nil { + glogger.GLogger.Error(err1) + } + } else { + _, err2 := core.ExecuteSuccess(rule.LuaVM) + if err2 != nil { + glogger.GLogger.Error(err2) + return } } - } } } diff --git a/engine/runner.go b/engine/runner.go index f106ea6ef..7856a97bc 100644 --- a/engine/runner.go +++ b/engine/runner.go @@ -22,8 +22,8 @@ import ( "syscall" wdog "github.com/hootrhino/rulex/plugin/generic_watchdog" + modbusscrc "github.com/hootrhino/rulex/plugin/modbus_crc_tools" modbusscanner "github.com/hootrhino/rulex/plugin/modbus_scanner" - modbusscrc "github.com/hootrhino/rulex/plugin/modbuscrc_tools" mqttserver "github.com/hootrhino/rulex/plugin/mqtt_server" netdiscover "github.com/hootrhino/rulex/plugin/net_discover" ttyterminal "github.com/hootrhino/rulex/plugin/ttyd_terminal" @@ -117,7 +117,7 @@ func loadPlugin(engine typex.RuleX) { if name == "ttyd" { plugin = ttyterminal.NewWebTTYPlugin() } - if name == "modbuscrc_tools" { + if name == "modbus_crc_tools" { plugin = modbusscrc.NewModbusCrcCalculator() } if name == "soft_wdog" { diff --git a/plugin/modbuscrc_tools/modbuscrc_tools.go b/plugin/modbus_crc_tools/modbuscrc_tools.go similarity index 100% rename from plugin/modbuscrc_tools/modbuscrc_tools.go rename to plugin/modbus_crc_tools/modbuscrc_tools.go diff --git a/plugin/modbuscrc_tools/modbuscrc_tools.md b/plugin/modbus_crc_tools/modbuscrc_tools.md similarity index 100% rename from plugin/modbuscrc_tools/modbuscrc_tools.md rename to plugin/modbus_crc_tools/modbuscrc_tools.md diff --git a/plugin/modbuscrc_tools/modbuscrc_tools_service.go b/plugin/modbus_crc_tools/modbuscrc_tools_service.go similarity index 100% rename from plugin/modbuscrc_tools/modbuscrc_tools_service.go rename to plugin/modbus_crc_tools/modbuscrc_tools_service.go diff --git a/plugin/rulex_api_server/apis/device_api.go b/plugin/rulex_api_server/apis/device_api.go index 6558eecd5..23ae1b24c 100644 --- a/plugin/rulex_api_server/apis/device_api.go +++ b/plugin/rulex_api_server/apis/device_api.go @@ -2,6 +2,7 @@ package apis import ( "errors" + "fmt" "io" "strconv" @@ -141,7 +142,6 @@ func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { // 创建设备 func CreateDevice(c *gin.Context, ruleEngine typex.RuleX) { - form := DeviceVo{} if err := c.ShouldBindJSON(&form); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) @@ -152,6 +152,23 @@ func CreateDevice(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } + isSingle := false + // 红外线是单例模式 + if form.Type == typex.INTERNAL_EVENT.String() { + ruleEngine.AllDevices().Range(func(key, value any) bool { + In := value.(*typex.Device) + if In.Type.String() == form.Type { + isSingle = true + return false + } + return true + }) + } + if isSingle { + msg := fmt.Errorf("the %s is singleton Device, can not create again", form.Name) + c.JSON(common.HTTP_OK, common.Error400(msg)) + return + } newUUID := utils.DeviceUuid() MDevice := model.MDevice{ UUID: newUUID, diff --git a/plugin/rulex_api_server/apis/inend_api.go b/plugin/rulex_api_server/apis/inend_api.go index 72027c806..97549175c 100644 --- a/plugin/rulex_api_server/apis/inend_api.go +++ b/plugin/rulex_api_server/apis/inend_api.go @@ -1,6 +1,8 @@ package apis import ( + "fmt" + "github.com/gin-gonic/gin" common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/plugin/rulex_api_server/model" @@ -84,7 +86,23 @@ func CreateInend(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err1)) return } - + isSingle := false + // 内部消息总线是单例模式 + if form.Type == typex.INTERNAL_EVENT.String() { + ruleEngine.AllInEnd().Range(func(key, value any) bool { + In := value.(*typex.InEnd) + if In.Type.String() == form.Type { + isSingle = true + return false + } + return true + }) + } + if isSingle { + msg := fmt.Errorf("the %s is singleton Source, can not create again", form.Name) + c.JSON(common.HTTP_OK, common.Error400(msg)) + return + } newUUID := utils.InUuid() if err := service.InsertMInEnd(&model.MInEnd{ diff --git a/plugin/rulex_api_server/apis/rule_api.go b/plugin/rulex_api_server/apis/rule_api.go index 429a55718..e699d733b 100644 --- a/plugin/rulex_api_server/apis/rule_api.go +++ b/plugin/rulex_api_server/apis/rule_api.go @@ -42,7 +42,6 @@ func RuleDetail(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.OkWithData(ruleVo{ UUID: rule.UUID, Name: rule.Name, - Type: rule.Type, Status: 1, Description: rule.Description, FromSource: rule.FromSource, @@ -61,7 +60,6 @@ func Rules(c *gin.Context, ruleEngine typex.RuleX) { DataList = append(DataList, ruleVo{ UUID: rule.UUID, Name: rule.Name, - Type: rule.Type, Status: 1, Description: rule.Description, FromSource: rule.FromSource, @@ -154,7 +152,6 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { // mRule := &model.MRule{ Name: form.Name, - Type: form.Type, UUID: rule.UUID, Description: form.Description, FromSource: form.FromSource, @@ -194,7 +191,6 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { // SaveDB mRule := &model.MRule{ Name: form.Name, - Type: form.Type, UUID: rule.UUID, Description: form.Description, FromSource: form.FromSource, @@ -263,117 +259,110 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { return } - if form.Type == "lua" { - mRule, err := service.GetMRuleWithUUID(form.UUID) - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - rule := typex.NewLuaRule( - ruleEngine, - mRule.UUID, - mRule.Name, - mRule.Description, - mRule.FromSource, - mRule.FromDevice, - mRule.Success, - mRule.Actions, - mRule.Failed) - ruleEngine.RemoveRule(rule.UUID) - if err := ruleEngine.LoadRule(rule); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // SaveDB - // - if err := service.UpdateMRule(mRule.UUID, &model.MRule{ - Name: form.Name, - Type: form.Type, - Description: form.Description, - FromSource: form.FromSource, - FromDevice: form.FromDevice, - Success: form.Success, - Failed: form.Failed, - Actions: form.Actions, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // 更新FromSource RULE到Device表中 - for _, inId := range form.FromSource { - if inId != "" { - InEnd, _ := service.GetMInEndWithUUID(inId) - if InEnd == nil { - c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) - return - } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range InEnd.BindRules { - ruleMap[rule] = rule - } - // 追加新的ID - ruleMap[inId] = mRule.UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } - InEnd.BindRules = BindRules - if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ - BindRules: BindRules, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // LoadNewest!!! - if err := server.LoadNewestInEnd(inId, ruleEngine); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } + mRule, err := service.GetMRuleWithUUID(form.UUID) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + rule := typex.NewLuaRule( + ruleEngine, + mRule.UUID, + mRule.Name, + mRule.Description, + mRule.FromSource, + mRule.FromDevice, + mRule.Success, + mRule.Actions, + mRule.Failed) + ruleEngine.RemoveRule(rule.UUID) + if err := ruleEngine.LoadRule(rule); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // SaveDB + // + if err := service.UpdateMRule(mRule.UUID, &model.MRule{ + Name: form.Name, + Description: form.Description, + FromSource: form.FromSource, + FromDevice: form.FromDevice, + Success: form.Success, + Failed: form.Failed, + Actions: form.Actions, + }); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // 更新FromSource RULE到Device表中 + for _, inId := range form.FromSource { + if inId != "" { + InEnd, _ := service.GetMInEndWithUUID(inId) + if InEnd == nil { + c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) + return } - - } - // FromDevice - for _, devId := range form.FromDevice { - if devId != "" { - Device, _ := service.GetMDeviceWithUUID(devId) - if Device == nil { - c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) - return - } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range Device.BindRules { - ruleMap[rule] = rule - } - // 追加新的ID - ruleMap[devId] = mRule.UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } - Device.BindRules = BindRules - if err := service.UpdateDevice(Device.UUID, &model.MDevice{ - BindRules: BindRules, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // LoadNewest!!! - if err := server.LoadNewestDevice(devId, ruleEngine); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range InEnd.BindRules { + ruleMap[rule] = rule + } + // 追加新的ID + ruleMap[inId] = mRule.UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + InEnd.BindRules = BindRules + if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ + BindRules: BindRules, + }); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // LoadNewest!!! + if err := server.LoadNewestInEnd(inId, ruleEngine); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return } } - c.JSON(common.HTTP_OK, common.Ok()) - return } - c.JSON(common.HTTP_OK, common.Error("rule type invalid:"+form.Type)) - + // FromDevice + for _, devId := range form.FromDevice { + if devId != "" { + Device, _ := service.GetMDeviceWithUUID(devId) + if Device == nil { + c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) + return + } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range Device.BindRules { + ruleMap[rule] = rule + } + // 追加新的ID + ruleMap[devId] = mRule.UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + Device.BindRules = BindRules + if err := service.UpdateDevice(Device.UUID, &model.MDevice{ + BindRules: BindRules, + }); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // LoadNewest!!! + if err := server.LoadNewestDevice(devId, ruleEngine); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + } + } + c.JSON(common.HTTP_OK, common.Ok()) } // Delete rule by UUID @@ -602,7 +591,6 @@ func ListByDevice(c *gin.Context, ruleEngine typex.RuleX) { FromSource: rule.FromSource, FromDevice: rule.FromDevice, Name: rule.Name, - Type: rule.Type, Status: 1, Description: rule.Description, Actions: rule.Actions, @@ -637,7 +625,6 @@ func ListByInend(c *gin.Context, ruleEngine typex.RuleX) { FromSource: rule.FromSource, FromDevice: rule.FromDevice, Name: rule.Name, - Type: rule.Type, Status: 1, Description: rule.Description, Actions: rule.Actions, diff --git a/plugin/rulex_api_server/model/model.go b/plugin/rulex_api_server/model/model.go index 608e3ecc0..53569b339 100644 --- a/plugin/rulex_api_server/model/model.go +++ b/plugin/rulex_api_server/model/model.go @@ -44,7 +44,6 @@ type MRule struct { RulexModel UUID string `gorm:"not null"` Name string `gorm:"not null"` - Type string // 脚本类型,目前支持"lua" FromSource StringList `gorm:"not null type:string[]"` FromDevice StringList `gorm:"not null type:string[]"` Actions string `gorm:"not null"` diff --git a/plugin/rulex_api_server/server/res_supervisor.go b/plugin/rulex_api_server/server/res_supervisor.go index aaf913a5e..384f06ed8 100644 --- a/plugin/rulex_api_server/server/res_supervisor.go +++ b/plugin/rulex_api_server/server/res_supervisor.go @@ -2,8 +2,10 @@ package server import ( "context" + "fmt" "time" + "github.com/hootrhino/rulex/component/intereventbus" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" ) @@ -41,8 +43,15 @@ func StartInSupervisor(ctx context.Context, in *typex.InEnd, ruleEngine typex.Ru } // 资源可能不会及时DOWN if currentIn.Source.Status() == typex.SOURCE_DOWN { - glogger.GLogger.Debugf("Source:%v DOWN, supervisor try to Restart", UUID) - time.Sleep(2 * time.Second) + info := fmt.Sprintf("Source:%v DOWN, supervisor try to Restart", UUID) + glogger.GLogger.Debugf(info) + intereventbus.Push(intereventbus.BaseEvent{ + Type: "SOURCE", + Event: "event.down", + Ts: uint64(time.Now().UnixNano()), + Info: info, + }) + time.Sleep(4 * time.Second) go LoadNewestInEnd(UUID, ruleEngine) return } @@ -83,8 +92,15 @@ func StartOutSupervisor(ctx context.Context, out *typex.OutEnd, ruleEngine typex } // 资源可能不会及时DOWN if currentOut.Target.Status() == typex.SOURCE_DOWN { - glogger.GLogger.Debugf("OutEnd:%v DOWN, supervisor try to Restart", UUID) - time.Sleep(5 * time.Second) + info := fmt.Sprintf("OutEnd:%v DOWN, supervisor try to Restart", UUID) + glogger.GLogger.Debugf(info) + intereventbus.Push(intereventbus.BaseEvent{ + Type: "TARGET", + Event: "event.down", + Ts: uint64(time.Now().UnixNano()), + Info: info, + }) + time.Sleep(4 * time.Second) go LoadNewestOutEnd(UUID, ruleEngine) return } @@ -125,8 +141,15 @@ func StartDeviceSupervisor(ctx context.Context, device *typex.Device, ruleEngine } // 资源可能不会及时DOWN if currentDevice.Device.Status() == typex.DEV_DOWN { - glogger.GLogger.Debugf("Device:%v DOWN, supervisor try to Restart", UUID) - time.Sleep(2 * time.Second) + info := fmt.Sprintf("Device:%v DOWN, supervisor try to Restart", UUID) + glogger.GLogger.Debugf(info) + intereventbus.Push(intereventbus.BaseEvent{ + Type: "DEVICE", + Event: "event.down", + Ts: uint64(time.Now().UnixNano()), + Info: info, + }) + time.Sleep(4 * time.Second) go LoadNewestDevice(UUID, ruleEngine) return } diff --git a/source/internal_event_source.go b/source/internal_event_source.go index 8b97b541c..fe2efcc5e 100644 --- a/source/internal_event_source.go +++ b/source/internal_event_source.go @@ -20,6 +20,11 @@ import ( "github.com/hootrhino/rulex/utils" ) +/* +* +* 用来将内部消息总线的事件推到资源脚本 +* + */ type __InternalEventSourceConfig struct { } type InternalEventSource struct { diff --git a/source/internal_event_source.md b/source/internal_event_source.md index db37c26d4..9f2752a8d 100644 --- a/source/internal_event_source.md +++ b/source/internal_event_source.md @@ -2,9 +2,9 @@ 可以使用这个数据源来监控系统内部的消息,比如设备离线,资源连接失败等。 ## 消息类型 -- SOURCE: 北向事件 +- SOURCE: 南向事件 - DEVICE: 设备事件 -- TARGET: 南向事件 +- TARGET: 北向事件 - SYSTEM: 系统内部事件 - HARDWARE: 硬件事件 diff --git a/test/conf/rulex.ini b/test/conf/rulex.ini index e97dac83c..d51ee592b 100644 --- a/test/conf/rulex.ini +++ b/test/conf/rulex.ini @@ -181,7 +181,7 @@ enable = true # # Modbus CRC calculator # -[plugin.modbuscrc_tools] +[plugin.modbus_crc_tools] # # Enable # diff --git a/typex/version.go b/typex/version.go index 975f63bfd..75e731ffb 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-01 18:34:26", + ReleaseTime: "2023-12-03 18:27:34", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-66fb869800cc380 +** Version: v0.6.4-cff7dab8876f129 ** Document: https://hootrhino.github.io ` diff --git a/typex/xdevice.go b/typex/xdevice.go index a6969ee85..781dbad19 100644 --- a/typex/xdevice.go +++ b/typex/xdevice.go @@ -41,6 +41,11 @@ func (s DeviceState) String() string { type DeviceType string +func (d DeviceType) String() string { + return string(d) + +} + // 支持的设备类型 const ( TSS200V02 DeviceType = "TSS200V02" // Multi params Sensor From a5cd8f4ee778875e58fcdbe029611be8462be02e Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 3 Dec 2023 18:42:01 +0800 Subject: [PATCH 078/138] dev: optimize global context --- component/intereventbus/intereventbus.go | 7 +++++++ engine/runner.go | 1 + typex/global.go | 2 +- typex/version.go | 4 ++-- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/component/intereventbus/intereventbus.go b/component/intereventbus/intereventbus.go index dc81279f3..ee9c28606 100644 --- a/component/intereventbus/intereventbus.go +++ b/component/intereventbus/intereventbus.go @@ -36,6 +36,13 @@ type BaseEvent struct { Info interface{} } +func (be *BaseEvent) String() string { + return fmt.Sprintf( + `BaseEvent@ Type:%s, Event:%s, Ts:%d, Info:%s`, + be.Type, be.Event, be.Ts, be.Info) + +} + /* * * Push diff --git a/engine/runner.go b/engine/runner.go index 7856a97bc..157982c6c 100644 --- a/engine/runner.go +++ b/engine/runner.go @@ -80,6 +80,7 @@ func RunRulex(iniPath string) { s := <-c glogger.GLogger.Warn("RULEX Receive Stop Signal: ", s) + typex.GCancel() engine.Stop() os.Exit(0) } diff --git a/typex/global.go b/typex/global.go index c254d82a7..981a81dd0 100644 --- a/typex/global.go +++ b/typex/global.go @@ -3,7 +3,7 @@ package typex import "context" // Global context -var GCTX = context.Background() +var GCTX, GCancel = context.WithCancel(context.Background()) // child context type CCTX struct { diff --git a/typex/version.go b/typex/version.go index 75e731ffb..56351cfa4 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-03 18:27:34", + ReleaseTime: "2023-12-03 18:40:39", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-cff7dab8876f129 +** Version: v0.6.4-acc8888eeaff1d7 ** Document: https://hootrhino.github.io ` From 42c88f0b777b22d8057ba7a83c6cd03d81eac948 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 3 Dec 2023 18:45:08 +0800 Subject: [PATCH 079/138] dev: rename modbus_crc_tools --- plugin/modbus_crc_tools/modbuscrc_tools.go | 2 +- plugin/modbus_crc_tools/modbuscrc_tools_service.go | 2 +- typex/version.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/modbus_crc_tools/modbuscrc_tools.go b/plugin/modbus_crc_tools/modbuscrc_tools.go index d97b2acf2..8550dfced 100644 --- a/plugin/modbus_crc_tools/modbuscrc_tools.go +++ b/plugin/modbus_crc_tools/modbuscrc_tools.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -package modbuscrctools +package modbus_crc_tools import ( "github.com/hootrhino/rulex/typex" diff --git a/plugin/modbus_crc_tools/modbuscrc_tools_service.go b/plugin/modbus_crc_tools/modbuscrc_tools_service.go index b3094bef3..72fb67aa9 100644 --- a/plugin/modbus_crc_tools/modbuscrc_tools_service.go +++ b/plugin/modbus_crc_tools/modbuscrc_tools_service.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -package modbuscrctools +package modbus_crc_tools import ( "encoding/binary" diff --git a/typex/version.go b/typex/version.go index 56351cfa4..7dedafff9 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-03 18:40:39", + ReleaseTime: "2023-12-03 18:44:37", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-acc8888eeaff1d7 +** Version: v0.6.4-a5cd8f4ee778875 ** Document: https://hootrhino.github.io ` From d4c605b95119eebc7c9f6640ecdd4d3e0d5a57ea Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 3 Dec 2023 21:32:56 +0800 Subject: [PATCH 080/138] dev: add Internal Notifies Api --- component/intereventbus/intereventbus.go | 4 +- .../apis/internal_notify_api.go | 93 +++++++++++++++++++ plugin/rulex_api_server/http_api_server.go | 8 ++ .../rulex_api_server/model/internal_notify.go | 29 ++++++ .../service/internal_notify_service.go | 64 +++++++++++++ typex/version.go | 4 +- 6 files changed, 198 insertions(+), 4 deletions(-) create mode 100644 plugin/rulex_api_server/apis/internal_notify_api.go create mode 100644 plugin/rulex_api_server/model/internal_notify.go create mode 100644 plugin/rulex_api_server/service/internal_notify_service.go diff --git a/component/intereventbus/intereventbus.go b/component/intereventbus/intereventbus.go index ee9c28606..713bd5285 100644 --- a/component/intereventbus/intereventbus.go +++ b/component/intereventbus/intereventbus.go @@ -36,9 +36,9 @@ type BaseEvent struct { Info interface{} } -func (be *BaseEvent) String() string { +func (be BaseEvent) String() string { return fmt.Sprintf( - `BaseEvent@ Type:%s, Event:%s, Ts:%d, Info:%s`, + `BaseEvent@Type:%s, Event:%s, Ts:%d, Info:%s`, be.Type, be.Event, be.Ts, be.Info) } diff --git a/plugin/rulex_api_server/apis/internal_notify_api.go b/plugin/rulex_api_server/apis/internal_notify_api.go new file mode 100644 index 000000000..c535407bf --- /dev/null +++ b/plugin/rulex_api_server/apis/internal_notify_api.go @@ -0,0 +1,93 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package apis + +import ( + "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + "github.com/hootrhino/rulex/typex" +) + +/* +* +* 内部事件 +* + */ +type InternalNotifyVo struct { + UUID string `json:"uuid"` // UUID + Type string `json:"type"` // INFO | ERROR | WARNING + Event string `json:"event"` // 字符串 + Ts uint64 `json:"ts"` // 时间戳 + Summary string `json:"summary"` // 概览,为了节省流量,在消息列表只显示这个字段,Info值为“” + Info string `json:"info,omitempty"` // 消息内容,是个文本,详情显示 +} + +/* +* +* 站内消息 +* + */ +func InternalNotifiesHeader(c *gin.Context, ruleEngine typex.RuleX) { + data := []InternalNotifyVo{} + models := service.AllInternalNotifiesHeader() + for _, model := range models { + data = append(data, InternalNotifyVo{ + UUID: model.UUID, + Type: model.Type, + Event: model.Event, + Ts: model.Ts, + Summary: model.Summary, + }) + + } + c.JSON(common.HTTP_OK, common.OkWithData(data)) +} + +/* +* +* 站内消息 +* + */ +func InternalNotifies(c *gin.Context, ruleEngine typex.RuleX) { + data := []InternalNotifyVo{} + models := service.AllInternalNotifies() + for _, model := range models { + data = append(data, InternalNotifyVo{ + UUID: model.UUID, + Type: model.Type, + Event: model.Event, + Ts: model.Ts, + Summary: model.Summary, + Info: model.Info, + }) + + } + c.JSON(common.HTTP_OK, common.OkWithData(data)) +} + +/* +* +* 清空 +* + */ +func ClearInternalNotifies(c *gin.Context, ruleEngine typex.RuleX) { + if err := service.ClearInternalNotifies(); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) +} diff --git a/plugin/rulex_api_server/http_api_server.go b/plugin/rulex_api_server/http_api_server.go index 4faff1e15..bd817a726 100644 --- a/plugin/rulex_api_server/http_api_server.go +++ b/plugin/rulex_api_server/http_api_server.go @@ -210,6 +210,7 @@ func (hs *ApiServerPlugin) Init(config *ini.Section) error { &model.MCronTask{}, &model.MCronResult{}, &model.MHwPort{}, + &model.MInternalNotify{}, ) // 初始化所有预制参数 server.DefaultApiServer.InitializeGenericOSData() @@ -443,6 +444,13 @@ func (hs *ApiServerPlugin) LoadRoute() { HwIFaceApi.POST("/update", server.AddRoute(apis.UpdateHwPortConfig)) HwIFaceApi.GET("/refresh", server.AddRoute(apis.RefreshPortList)) } + // 站内公告 + internalNotifyApi := server.DefaultApiServer.GetGroup(server.ContextUrl("/notify")) + { + internalNotifyApi.GET("/header", server.AddRoute(apis.InternalNotifiesHeader)) + internalNotifyApi.GET("/list", server.AddRoute(apis.InternalNotifies)) + internalNotifyApi.PUT("/clear", server.AddRoute(apis.ClearInternalNotifies)) + } // // 系统设置 // diff --git a/plugin/rulex_api_server/model/internal_notify.go b/plugin/rulex_api_server/model/internal_notify.go new file mode 100644 index 000000000..c80f77b49 --- /dev/null +++ b/plugin/rulex_api_server/model/internal_notify.go @@ -0,0 +1,29 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +package model + +/* +* +* 内部通知 +* + */ +type MInternalNotify struct { + UUID string `gorm:"not null"` // UUID + Type string `gorm:"not null"` // INFO | ERROR | WARNING + Event string `gorm:"not null"` // 字符串 + Ts uint64 `gorm:"not null"` // 时间戳 + Summary string `gorm:"not null"` // 概览,为了节省流量,在消息列表只显示这个字段,Info值为“” + Info string `gorm:"not null"` // 消息内容,是个文本,详情显示 +} diff --git a/plugin/rulex_api_server/service/internal_notify_service.go b/plugin/rulex_api_server/service/internal_notify_service.go new file mode 100644 index 000000000..68476b5d5 --- /dev/null +++ b/plugin/rulex_api_server/service/internal_notify_service.go @@ -0,0 +1,64 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package service + +import ( + "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" +) + +func InsertInternalNotifies(m model.MInternalNotify) error { + + var count int64 + interdb.DB().Model(&m).Count(&count) + if count > 100 { + if err := ClearInternalNotifies(); err != nil { + return err + } + } + return interdb.DB().Model(&m).Save(&m).Error +} + +/* +* +* 右上角 +* + */ +func AllInternalNotifiesHeader() []model.MInternalNotify { + m := []model.MInternalNotify{} + interdb.DB().Model(&model.MInternalNotify{}).Limit(6).Find(&m) + return m +} + +/* +* +* 所有列表 +* + */ +func AllInternalNotifies() []model.MInternalNotify { + m := []model.MInternalNotify{} + interdb.DB().Model(&model.MInternalNotify{}).Limit(100).Find(&m) + return m +} + +/* +* +* 清空表 +* + */ +func ClearInternalNotifies() error { + return interdb.DB().Exec("DELETE FROM m_internal_notifies;VACUUM;").Error +} diff --git a/typex/version.go b/typex/version.go index 7dedafff9..1a41c0ace 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-03 18:44:37", + ReleaseTime: "2023-12-03 18:45:36", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-a5cd8f4ee778875 +** Version: v0.6.4-42c88f0b777b22d ** Document: https://hootrhino.github.io ` From 960528cb15c6846105686ff10559eae4b75daff1 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 3 Dec 2023 22:44:59 +0800 Subject: [PATCH 081/138] dev: add internal notify api --- component/eventbus/eventbus.go | 24 +++++ component/eventbus/eventbus.md | 7 ++ .../internotify.go} | 40 ++++++-- .../internotify.md} | 0 engine/engine.go | 6 +- .../rulex_api_server/server/res_supervisor.go | 8 +- source/internal_event_source.go | 98 +++++++++++++++---- 7 files changed, 149 insertions(+), 34 deletions(-) create mode 100644 component/eventbus/eventbus.go create mode 100644 component/eventbus/eventbus.md rename component/{intereventbus/intereventbus.go => internotify/internotify.go} (76%) rename component/{intereventbus/intereventbus.md => internotify/internotify.md} (100%) diff --git a/component/eventbus/eventbus.go b/component/eventbus/eventbus.go new file mode 100644 index 000000000..2de0fe3b3 --- /dev/null +++ b/component/eventbus/eventbus.go @@ -0,0 +1,24 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package eventbus + +/* +* +* 内部消息总线 +* + */ +type EventBus struct { +} diff --git a/component/eventbus/eventbus.md b/component/eventbus/eventbus.md new file mode 100644 index 000000000..9e13357a9 --- /dev/null +++ b/component/eventbus/eventbus.md @@ -0,0 +1,7 @@ +# 内部消息总线 +类似于Nats一样的简单Pub\Sub框架 +## 示例 +```go + ebus.publish("a.b.c", "data") + ebus.subscribe("a.b.c", func(data)) +``` \ No newline at end of file diff --git a/component/intereventbus/intereventbus.go b/component/internotify/internotify.go similarity index 76% rename from component/intereventbus/intereventbus.go rename to component/internotify/internotify.go index 713bd5285..46b2284c9 100644 --- a/component/intereventbus/intereventbus.go +++ b/component/internotify/internotify.go @@ -13,7 +13,7 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -package intereventbus +package internotify import ( "context" @@ -29,6 +29,12 @@ var __DefaultInternalEventBus *InternalEventBus // --------------------------------------------------------- // Type // --------------------------------------------------------- +// - SOURCE: 南向事件 +// - DEVICE: 设备事件 +// - TARGET: 北向事件 +// - SYSTEM: 系统内部事件 +// - HARDWARE: 硬件事件 + type BaseEvent struct { Type string Event string @@ -66,13 +72,25 @@ func Push(e BaseEvent) error { * */ type InternalEventBus struct { - Queue chan BaseEvent - Rulex typex.RuleX + Queue chan BaseEvent + Rulex typex.RuleX + SourceCount uint } func (q *InternalEventBus) GetSize() int { return cap(q.Queue) } +func RemoveSource() { + if __DefaultInternalEventBus.SourceCount > 0 { + __DefaultInternalEventBus.SourceCount-- + } +} +func AddSource() { + __DefaultInternalEventBus.SourceCount++ +} +func GetQueue() chan BaseEvent { + return __DefaultInternalEventBus.Queue +} /* * @@ -96,13 +114,15 @@ func InitInternalEventBus(r typex.RuleX, MaxQueueSize int) *InternalEventBus { func StartInternalEventQueue() { go func(ctx context.Context, InternalEventBus *InternalEventBus) { for { - select { - case <-ctx.Done(): - return - case Event := <-InternalEventBus.Queue: - { - // Push to device Queue - glogger.GLogger.Debug("Internal Event:", Event) + // 当无订阅者时,及时释放channel里面的数据 + if __DefaultInternalEventBus.SourceCount == 0 { + select { + case <-ctx.Done(): + return + case Event := <-InternalEventBus.Queue: + { + glogger.GLogger.Debug("Internal Event:", Event) + } } } } diff --git a/component/intereventbus/intereventbus.md b/component/internotify/internotify.md similarity index 100% rename from component/intereventbus/intereventbus.md rename to component/internotify/internotify.md diff --git a/engine/engine.go b/engine/engine.go index df4f1c01b..ddd2fd30c 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -28,8 +28,8 @@ import ( "github.com/hootrhino/rulex/component/datacenter" "github.com/hootrhino/rulex/component/hwportmanager" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/component/intereventbus" "github.com/hootrhino/rulex/component/intermetric" + "github.com/hootrhino/rulex/component/internotify" "github.com/hootrhino/rulex/component/interqueue" "github.com/hootrhino/rulex/component/rtspserver" "github.com/hootrhino/rulex/component/trailer" @@ -84,7 +84,7 @@ func InitRuleEngine(config typex.RulexConfig) typex.RuleX { // Internal DB interdb.Init(__DefaultRuleEngine, __DEFAULT_DB_PATH) // Internal Bus - intereventbus.InitInternalEventBus(__DefaultRuleEngine, core.GlobalConfig.MaxQueueSize) + internotify.InitInternalEventBus(__DefaultRuleEngine, core.GlobalConfig.MaxQueueSize) // 前后交互组件 interqueue.InitInteractQueue(__DefaultRuleEngine, core.GlobalConfig.MaxQueueSize) // Web Pipeline @@ -123,7 +123,7 @@ func (e *RuleEngine) Start() *typex.RulexConfig { // 内部队列 interqueue.StartDataCacheQueue() // InternalEventQueue - intereventbus.StartInternalEventQueue() + internotify.StartInternalEventQueue() // WebDataPip go core.StartWebDataPipe() return e.Config diff --git a/plugin/rulex_api_server/server/res_supervisor.go b/plugin/rulex_api_server/server/res_supervisor.go index 384f06ed8..c7cf41dcb 100644 --- a/plugin/rulex_api_server/server/res_supervisor.go +++ b/plugin/rulex_api_server/server/res_supervisor.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - "github.com/hootrhino/rulex/component/intereventbus" + "github.com/hootrhino/rulex/component/internotify" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" ) @@ -45,7 +45,7 @@ func StartInSupervisor(ctx context.Context, in *typex.InEnd, ruleEngine typex.Ru if currentIn.Source.Status() == typex.SOURCE_DOWN { info := fmt.Sprintf("Source:%v DOWN, supervisor try to Restart", UUID) glogger.GLogger.Debugf(info) - intereventbus.Push(intereventbus.BaseEvent{ + internotify.Push(internotify.BaseEvent{ Type: "SOURCE", Event: "event.down", Ts: uint64(time.Now().UnixNano()), @@ -94,7 +94,7 @@ func StartOutSupervisor(ctx context.Context, out *typex.OutEnd, ruleEngine typex if currentOut.Target.Status() == typex.SOURCE_DOWN { info := fmt.Sprintf("OutEnd:%v DOWN, supervisor try to Restart", UUID) glogger.GLogger.Debugf(info) - intereventbus.Push(intereventbus.BaseEvent{ + internotify.Push(internotify.BaseEvent{ Type: "TARGET", Event: "event.down", Ts: uint64(time.Now().UnixNano()), @@ -143,7 +143,7 @@ func StartDeviceSupervisor(ctx context.Context, device *typex.Device, ruleEngine if currentDevice.Device.Status() == typex.DEV_DOWN { info := fmt.Sprintf("Device:%v DOWN, supervisor try to Restart", UUID) glogger.GLogger.Debugf(info) - intereventbus.Push(intereventbus.BaseEvent{ + internotify.Push(internotify.BaseEvent{ Type: "DEVICE", Event: "event.down", Ts: uint64(time.Now().UnixNano()), diff --git a/source/internal_event_source.go b/source/internal_event_source.go index fe2efcc5e..91f7bf63b 100644 --- a/source/internal_event_source.go +++ b/source/internal_event_source.go @@ -16,6 +16,10 @@ package source import ( + "context" + "encoding/json" + + "github.com/hootrhino/rulex/component/internotify" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) @@ -26,6 +30,13 @@ import ( * */ type __InternalEventSourceConfig struct { + // - ALL: 全部事件 + // - SOURCE: 南向事件 + // - DEVICE: 设备事件 + // - TARGET: 北向事件 + // - SYSTEM: 系统事件 + // - HARDWARE: 硬件事件 + Type string `json:"type"` } type InternalEventSource struct { typex.XStatus @@ -34,26 +45,13 @@ type InternalEventSource struct { func NewInternalEventSource(r typex.RuleX) typex.XSource { s := InternalEventSource{} + s.mainConfig = __InternalEventSourceConfig{ + Type: "ALL", + } s.RuleEngine = r return &s } -func (u *InternalEventSource) Start(cctx typex.CCTX) error { - u.Ctx = cctx.Ctx - u.CancelCTX = cctx.CancelCTX - - return nil - -} - -func (u *InternalEventSource) Details() *typex.InEnd { - return u.RuleEngine.GetInEnd(u.PointId) -} - -func (u *InternalEventSource) Test(inEndId string) bool { - return true -} - func (u *InternalEventSource) Init(inEndId string, configMap map[string]interface{}) error { u.PointId = inEndId if err := utils.BindSourceConfig(configMap, &u.mainConfig); err != nil { @@ -62,6 +60,13 @@ func (u *InternalEventSource) Init(inEndId string, configMap map[string]interfac return nil } +func (u *InternalEventSource) Start(cctx typex.CCTX) error { + u.Ctx = cctx.Ctx + u.CancelCTX = cctx.CancelCTX + u.startInternalEventQueue() + return nil + +} func (u *InternalEventSource) DataModels() []typex.XDataModel { return u.XDataModels } @@ -74,12 +79,19 @@ func (u *InternalEventSource) Stop() { if u.CancelCTX != nil { u.CancelCTX() } - } func (*InternalEventSource) Driver() typex.XExternalDriver { return nil } +func (u *InternalEventSource) Details() *typex.InEnd { + return u.RuleEngine.GetInEnd(u.PointId) +} + +func (u *InternalEventSource) Test(inEndId string) bool { + return true +} + // 拓扑 func (*InternalEventSource) Topology() []typex.TopologyPoint { return []typex.TopologyPoint{} @@ -94,3 +106,55 @@ func (*InternalEventSource) DownStream([]byte) (int, error) { func (*InternalEventSource) UpStream([]byte) (int, error) { return 0, nil } + +type event struct { + // - ALL: 全部 + // - SOURCE: 南向事件 + // - DEVICE: 设备事件 + // - TARGET: 北向事件 + // - SYSTEM: 系统内部事件 + // - HARDWARE: 硬件事件 + Type string `json:"type"` + Event string `json:"event"` + Ts uint64 `json:"ts"` + Info interface{} `json:"info"` +} + +/* +* +* 从内部总线拿数据 +* + */ +func (ie *InternalEventSource) startInternalEventQueue() { + go func(ctx context.Context) { + internotify.AddSource() + defer internotify.RemoveSource() + for { + select { + case <-ctx.Done(): + return + case Event := <-internotify.GetQueue(): + if ie.mainConfig.Type == "ALL" { + bytes, _ := json.Marshal(event{ + Type: Event.Type, + Event: Event.Event, + Ts: Event.Ts, + Info: Event.Info, + }) + ie.RuleEngine.WorkInEnd(ie.RuleEngine.GetInEnd(ie.PointId), string(bytes)) + continue + } + if ie.mainConfig.Type == Event.Type { + bytes, _ := json.Marshal(event{ + Type: Event.Type, + Event: Event.Event, + Ts: Event.Ts, + Info: Event.Info, + }) + ie.RuleEngine.WorkInEnd(ie.RuleEngine.GetInEnd(ie.PointId), string(bytes)) + continue + } + } + } + }(ie.Ctx) +} From 4ede03412d2c57379916d647285bcb8e0c240431 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 3 Dec 2023 23:50:07 +0800 Subject: [PATCH 082/138] dev: enhance notify; sqlite VACUUM --- component/interdb/inter_sqlite_db.go | 1 + .../generic_watchdog_windows.go | 2 +- .../apis/internal_notify_api.go | 17 ++++++++++++++++ plugin/rulex_api_server/http_api_server.go | 3 +++ .../rulex_api_server/model/internal_notify.go | 2 ++ .../service/internal_notify_service.go | 20 ++++++++++++++++--- 6 files changed, 41 insertions(+), 4 deletions(-) diff --git a/component/interdb/inter_sqlite_db.go b/component/interdb/inter_sqlite_db.go index 50d443be8..08b5ddc1c 100644 --- a/component/interdb/inter_sqlite_db.go +++ b/component/interdb/inter_sqlite_db.go @@ -51,6 +51,7 @@ func Init(engine typex.RuleX, dbPath string) error { if err != nil { glogger.GLogger.Fatal(err) } + __Sqlite.db.Exec("VACUUM;") return err } diff --git a/plugin/generic_watchdog/generic_watchdog_windows.go b/plugin/generic_watchdog/generic_watchdog_windows.go index 47a7ca85a..a8319b8da 100644 --- a/plugin/generic_watchdog/generic_watchdog_windows.go +++ b/plugin/generic_watchdog/generic_watchdog_windows.go @@ -39,7 +39,7 @@ func NewGenericWatchDog() *genericWatchDog { } func (dog *genericWatchDog) Init(config *ini.Section) error { - return fmt.Errorf("OS support Wdog:%s", runtime.GOOS) + return fmt.Errorf("OS Not Support Soft WatchDog:%s", runtime.GOOS) } func (dog *genericWatchDog) Start(typex.RuleX) error { diff --git a/plugin/rulex_api_server/apis/internal_notify_api.go b/plugin/rulex_api_server/apis/internal_notify_api.go index c535407bf..a7e4fc027 100644 --- a/plugin/rulex_api_server/apis/internal_notify_api.go +++ b/plugin/rulex_api_server/apis/internal_notify_api.go @@ -30,6 +30,7 @@ import ( type InternalNotifyVo struct { UUID string `json:"uuid"` // UUID Type string `json:"type"` // INFO | ERROR | WARNING + Status int `json:"status"` // 1 未读 2 已读 Event string `json:"event"` // 字符串 Ts uint64 `json:"ts"` // 时间戳 Summary string `json:"summary"` // 概览,为了节省流量,在消息列表只显示这个字段,Info值为“” @@ -51,6 +52,7 @@ func InternalNotifiesHeader(c *gin.Context, ruleEngine typex.RuleX) { Event: model.Event, Ts: model.Ts, Summary: model.Summary, + Status: model.Status, }) } @@ -73,6 +75,7 @@ func InternalNotifies(c *gin.Context, ruleEngine typex.RuleX) { Ts: model.Ts, Summary: model.Summary, Info: model.Info, + Status: model.Status, }) } @@ -91,3 +94,17 @@ func ClearInternalNotifies(c *gin.Context, ruleEngine typex.RuleX) { } c.JSON(common.HTTP_OK, common.Ok()) } + +/* +* +* 阅读 +* + */ +func ReadInternalNotifies(c *gin.Context, ruleEngine typex.RuleX) { + uuid, _ := c.GetQuery("uuid") + if err := service.ReadInternalNotifies(uuid); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) +} diff --git a/plugin/rulex_api_server/http_api_server.go b/plugin/rulex_api_server/http_api_server.go index bd817a726..834e5e46a 100644 --- a/plugin/rulex_api_server/http_api_server.go +++ b/plugin/rulex_api_server/http_api_server.go @@ -189,6 +189,8 @@ func (hs *ApiServerPlugin) Init(config *ini.Section) error { return err } server.StartRulexApiServer(hs.ruleEngine) + + interdb.DB().Exec("VACUUM;") interdb.RegisterModel( &model.MInEnd{}, &model.MOutEnd{}, @@ -450,6 +452,7 @@ func (hs *ApiServerPlugin) LoadRoute() { internalNotifyApi.GET("/header", server.AddRoute(apis.InternalNotifiesHeader)) internalNotifyApi.GET("/list", server.AddRoute(apis.InternalNotifies)) internalNotifyApi.PUT("/clear", server.AddRoute(apis.ClearInternalNotifies)) + internalNotifyApi.PUT("/read", server.AddRoute(apis.ReadInternalNotifies)) } // // 系统设置 diff --git a/plugin/rulex_api_server/model/internal_notify.go b/plugin/rulex_api_server/model/internal_notify.go index c80f77b49..9cb016538 100644 --- a/plugin/rulex_api_server/model/internal_notify.go +++ b/plugin/rulex_api_server/model/internal_notify.go @@ -20,8 +20,10 @@ package model * */ type MInternalNotify struct { + RulexModel UUID string `gorm:"not null"` // UUID Type string `gorm:"not null"` // INFO | ERROR | WARNING + Status int `gorm:"not null"` // 1 未读 2 已读 Event string `gorm:"not null"` // 字符串 Ts uint64 `gorm:"not null"` // 时间戳 Summary string `gorm:"not null"` // 概览,为了节省流量,在消息列表只显示这个字段,Info值为“” diff --git a/plugin/rulex_api_server/service/internal_notify_service.go b/plugin/rulex_api_server/service/internal_notify_service.go index 68476b5d5..1d9b7cf2c 100644 --- a/plugin/rulex_api_server/service/internal_notify_service.go +++ b/plugin/rulex_api_server/service/internal_notify_service.go @@ -20,10 +20,15 @@ import ( "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) +/* +* +* InsertInternalNotifies +* + */ func InsertInternalNotifies(m model.MInternalNotify) error { - var count int64 interdb.DB().Model(&m).Count(&count) + // 超过100条记录就清空 if count > 100 { if err := ClearInternalNotifies(); err != nil { return err @@ -39,7 +44,7 @@ func InsertInternalNotifies(m model.MInternalNotify) error { */ func AllInternalNotifiesHeader() []model.MInternalNotify { m := []model.MInternalNotify{} - interdb.DB().Model(&model.MInternalNotify{}).Limit(6).Find(&m) + interdb.DB().Table("m_internal_notifies").Where("status=1").Limit(6).Find(&m) return m } @@ -50,7 +55,7 @@ func AllInternalNotifiesHeader() []model.MInternalNotify { */ func AllInternalNotifies() []model.MInternalNotify { m := []model.MInternalNotify{} - interdb.DB().Model(&model.MInternalNotify{}).Limit(100).Find(&m) + interdb.DB().Table("m_internal_notifies").Where("status=1").Limit(100).Find(&m) return m } @@ -62,3 +67,12 @@ func AllInternalNotifies() []model.MInternalNotify { func ClearInternalNotifies() error { return interdb.DB().Exec("DELETE FROM m_internal_notifies;VACUUM;").Error } + +/* +* +* 点击已读 +* + */ +func ReadInternalNotifies(uuid string) error { + return interdb.DB().Where("uuid=?", uuid).Delete(&model.MInternalNotify{}).Error +} From e040348f9ef010743e4df8beca122bd299400842 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 3 Dec 2023 23:54:37 +0800 Subject: [PATCH 083/138] ci: fix ci failed --- .github/workflows/2_build_and_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/2_build_and_test.yml b/.github/workflows/2_build_and_test.yml index e07dfa78c..e6c7c3cea 100644 --- a/.github/workflows/2_build_and_test.yml +++ b/.github/workflows/2_build_and_test.yml @@ -25,6 +25,7 @@ jobs: gcc-mingw-w64 \ gcc-aarch64-linux-gnu -y cloc ./ + go get make # for test mqtt echo "Start Mqtt Server" From b9b053e1ad1c29984e0174478dcaa98b69b57c08 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 3 Dec 2023 23:58:10 +0800 Subject: [PATCH 084/138] ci: fix ci failed --- .github/workflows/2_build_and_test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/2_build_and_test.yml b/.github/workflows/2_build_and_test.yml index e6c7c3cea..3b7e6d77e 100644 --- a/.github/workflows/2_build_and_test.yml +++ b/.github/workflows/2_build_and_test.yml @@ -26,6 +26,7 @@ jobs: gcc-aarch64-linux-gnu -y cloc ./ go get + go get -t github.com/hootrhino/rulex/test make # for test mqtt echo "Start Mqtt Server" From eed0fed05dbbeb11f955ff5cf4a162c17b33f0f2 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 4 Dec 2023 15:58:39 +0800 Subject: [PATCH 085/138] dev: add notify test --- .../apis/internal_notify_api.go | 20 +++++++ plugin/rulex_api_server/http_api_server.go | 1 + .../service/internal_notify_service.go | 2 +- utils/os_common.go | 52 ++++++++++++------- 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/plugin/rulex_api_server/apis/internal_notify_api.go b/plugin/rulex_api_server/apis/internal_notify_api.go index a7e4fc027..8889cdd41 100644 --- a/plugin/rulex_api_server/apis/internal_notify_api.go +++ b/plugin/rulex_api_server/apis/internal_notify_api.go @@ -16,10 +16,15 @@ package apis import ( + "fmt" + "time" + "github.com/gin-gonic/gin" common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" ) /* @@ -108,3 +113,18 @@ func ReadInternalNotifies(c *gin.Context, ruleEngine typex.RuleX) { } c.JSON(common.HTTP_OK, common.Ok()) } + +func TestCreateNotifies(c *gin.Context, ruleEngine typex.RuleX) { + for i := 0; i < 50; i++ { + service.InsertInternalNotify(model.MInternalNotify{ + UUID: utils.MakeUUID("NOTIFY"), // UUID + Type: `WARNING`, // INFO | ERROR | WARNING + Status: 1, + Event: `event.down`, // 字符串 + Ts: uint64(time.Now().UnixMilli()), + Info: "位于某处的某个设备已经离线, 请及时检查处理,这是测试数据而已", + Summary: fmt.Sprintf(`测试数据:设备 %d 离线`, i), + }) + } + c.JSON(common.HTTP_OK, common.Ok()) +} diff --git a/plugin/rulex_api_server/http_api_server.go b/plugin/rulex_api_server/http_api_server.go index 834e5e46a..d1d2cb1e0 100644 --- a/plugin/rulex_api_server/http_api_server.go +++ b/plugin/rulex_api_server/http_api_server.go @@ -453,6 +453,7 @@ func (hs *ApiServerPlugin) LoadRoute() { internalNotifyApi.GET("/list", server.AddRoute(apis.InternalNotifies)) internalNotifyApi.PUT("/clear", server.AddRoute(apis.ClearInternalNotifies)) internalNotifyApi.PUT("/read", server.AddRoute(apis.ReadInternalNotifies)) + internalNotifyApi.POST("/test", server.AddRoute(apis.TestCreateNotifies)) } // // 系统设置 diff --git a/plugin/rulex_api_server/service/internal_notify_service.go b/plugin/rulex_api_server/service/internal_notify_service.go index 1d9b7cf2c..2c6e819bb 100644 --- a/plugin/rulex_api_server/service/internal_notify_service.go +++ b/plugin/rulex_api_server/service/internal_notify_service.go @@ -25,7 +25,7 @@ import ( * InsertInternalNotifies * */ -func InsertInternalNotifies(m model.MInternalNotify) error { +func InsertInternalNotify(m model.MInternalNotify) error { var count int64 interdb.DB().Model(&m).Count(&count) // 超过100条记录就清空 diff --git a/utils/os_common.go b/utils/os_common.go index 71fa708c6..4c28e31e1 100644 --- a/utils/os_common.go +++ b/utils/os_common.go @@ -94,30 +94,42 @@ func GetOSDistribution() (string, error) { } // Linux 有很多发行版, 目前特别要识别一下Openwrt if runtime.GOOS == "linux" { - cmd := exec.Command("cat", "/etc/os-release") - output, err := cmd.Output() - if err != nil { - return runtime.GOOS, err - } - osIssue := strings.ToLower(string(output)) - if strings.Contains((osIssue), "openwrt") { - return "openwrt", nil - } - if strings.Contains((osIssue), "ubuntu") { - return "ubuntu", nil - } - if strings.Contains((osIssue), "debian") { - return "debian", nil - } - if strings.Contains((osIssue), "armbian") { - return "armbian", nil - } - if strings.Contains((osIssue), "deepin") { - return "deepin", nil + if PathExists("/etc/os-release") { + cmd := exec.Command("cat", "/etc/os-release") + output, err := cmd.Output() + if err != nil { + return runtime.GOOS, err + } + osIssue := strings.ToLower(string(output)) + if strings.Contains((osIssue), "openwrt") { + return "openwrt", nil + } + if strings.Contains((osIssue), "ubuntu") { + return "ubuntu", nil + } + if strings.Contains((osIssue), "debian") { + return "debian", nil + } + if strings.Contains((osIssue), "armbian") { + return "armbian", nil + } + if strings.Contains((osIssue), "deepin") { + return "deepin", nil + } } } return runtime.GOOS, nil } +func PathExists(path string) bool { + _, err := os.Stat(path) + if err == nil { + return true + } + if os.IsNotExist(err) { + return false + } + return false +} /* * From 9181776715a851ee702422227a5eaf8558568929 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 4 Dec 2023 19:08:43 +0800 Subject: [PATCH 086/138] dev: fix get unknown distribution os info failed --- utils/os_util_linux.go | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/utils/os_util_linux.go b/utils/os_util_linux.go index 35739ef30..76c43778a 100644 --- a/utils/os_util_linux.go +++ b/utils/os_util_linux.go @@ -5,6 +5,7 @@ import ( "os" "os/exec" "strings" + "runtime" ) /* @@ -139,17 +140,23 @@ func GetSystemDevices() (SystemDevices, error) { */ func CatOsRelease() (map[string]string, error) { returnMap := map[string]string{} - cfg, err := ini.ShadowLoad("/etc/os-release") - if err != nil { - return nil, err - } - DefaultSection, err := cfg.GetSection("DEFAULT") - if err != nil { - return nil, err - } - for _, Key := range DefaultSection.KeyStrings() { - V, _ := DefaultSection.GetKey(Key) - returnMap[Key] = V.String() + if runtime.GOOS == "linux" { + if PathExists("/etc/os-release") { + cfg, err := ini.ShadowLoad("/etc/os-release") + if err != nil { + return nil, err + } + DefaultSection, err := cfg.GetSection("DEFAULT") + if err != nil { + return nil, err + } + for _, Key := range DefaultSection.KeyStrings() { + V, _ := DefaultSection.GetKey(Key) + returnMap[Key] = V.String() + } + } else { + returnMap["OS Version"] = "UNKNOWN" + } } return returnMap, nil From 5c84edc0a95be01a8857f20c21eac2256e62c590 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 4 Dec 2023 23:58:51 +0800 Subject: [PATCH 087/138] dev: optimize modbus write api --- rulexlib/modbus_lib.go | 174 ++++++++++++++++++++++------------------- typex/version.go | 4 +- 2 files changed, 95 insertions(+), 83 deletions(-) diff --git a/rulexlib/modbus_lib.go b/rulexlib/modbus_lib.go index c49cdcce4..b9b019499 100644 --- a/rulexlib/modbus_lib.go +++ b/rulexlib/modbus_lib.go @@ -96,27 +96,30 @@ func F5(rx typex.RuleX) func(l *lua.LState) int { } } Device := rx.GetDevice(devUUID) - if Device != nil { - if Device.Type != typex.GENERIC_MODBUS { - l.Push(lua.LString("Only support GENERIC_MODBUS device")) - return 1 - } - if Device.Device.Status() == typex.DEV_UP { - args, _ := json.Marshal([]common.RegisterW{ - { - Function: 5, - SlaverId: byte(slaverId), - Address: uint16(Address), - Values: HexValues, - }, - }) - _, err := Device.Device.OnWrite([]byte("F5"), args) - if err != nil { - l.Push(lua.LString(err.Error())) - return 1 - } - } - l.Push(lua.LString("Device down:" + devUUID)) + if Device == nil { + l.Push(lua.LString("Device is not exists")) + return 1 + } + + if Device.Type != typex.GENERIC_MODBUS { + l.Push(lua.LString("Only support GENERIC_MODBUS device")) + return 1 + } + if Device.Device.Status() != typex.DEV_UP { + l.Push(lua.LString("device down:" + devUUID)) + return 1 + } + args, _ := json.Marshal([]common.RegisterW{ + { + Function: 5, + SlaverId: byte(slaverId), + Address: uint16(Address), + Values: HexValues, + }, + }) + _, err0 := Device.Device.OnWrite([]byte("F5"), args) + if err0 != nil { + l.Push(lua.LString(err0.Error())) return 1 } l.Push(lua.LNil) @@ -142,29 +145,32 @@ func F6(rx typex.RuleX) func(l *lua.LState) int { return 1 } Device := rx.GetDevice(devUUID) - if Device != nil { - if Device.Type != typex.GENERIC_MODBUS { - l.Push(lua.LString("Only support GENERIC_MODBUS device")) - return 1 - } - if Device.Device.Status() == typex.DEV_UP { - args, _ := json.Marshal(common.RegisterW{ - Function: 6, - SlaverId: byte(slaverId), - Address: uint16(Address), - Quantity: uint16(1), //2字节 - Values: HexValues, - }) - _, err := Device.Device.OnWrite([]byte("F6"), args) - if err != nil { - glogger.GLogger.Error(err) - l.Push(lua.LString(err.Error())) - return 1 - } - } + if Device == nil { + l.Push(lua.LString("Device is not exists")) + return 1 + } + + if Device.Type != typex.GENERIC_MODBUS { + l.Push(lua.LString("Only support GENERIC_MODBUS device")) + return 1 + } + if Device.Device.Status() != typex.DEV_UP { l.Push(lua.LString("device down:" + devUUID)) return 1 } + args, _ := json.Marshal(common.RegisterW{ + Function: 6, + SlaverId: byte(slaverId), + Address: uint16(Address), + Quantity: uint16(1), //2字节 + Values: HexValues, + }) + _, err0 := Device.Device.OnWrite([]byte("F6"), args) + if err0 != nil { + glogger.GLogger.Error(err0) + l.Push(lua.LString(err0.Error())) + return 1 + } l.Push(lua.LNil) return 1 } @@ -190,29 +196,31 @@ func F15(rx typex.RuleX) func(l *lua.LState) int { return 1 } Device := rx.GetDevice(devUUID) - if Device != nil { - if Device.Type != typex.GENERIC_MODBUS { - l.Push(lua.LString("Only support GENERIC_MODBUS device")) - return 1 - } - if Device.Device.Status() == typex.DEV_UP { - args, _ := json.Marshal(common.RegisterW{ - Function: 15, - SlaverId: byte(slaverId), - Address: uint16(Address), - Quantity: uint16(Quantity), - Values: HexValues, - }) - _, err := Device.Device.OnWrite([]byte("F15"), args) - if err != nil { - glogger.GLogger.Error(err) - l.Push(lua.LString(err.Error())) - return 1 - } - } + if Device == nil { + l.Push(lua.LString("Device is not exists")) + return 1 + } + if Device.Type != typex.GENERIC_MODBUS { + l.Push(lua.LString("Only support GENERIC_MODBUS device")) + return 1 + } + if Device.Device.Status() != typex.DEV_UP { l.Push(lua.LString("device down:" + devUUID)) return 1 } + args, _ := json.Marshal(common.RegisterW{ + Function: 15, + SlaverId: byte(slaverId), + Address: uint16(Address), + Quantity: uint16(Quantity), + Values: HexValues, + }) + _, err0 := Device.Device.OnWrite([]byte("F15"), args) + if err0 != nil { + glogger.GLogger.Error(err0) + l.Push(lua.LString(err0.Error())) + return 1 + } l.Push(lua.LNil) return 1 } @@ -236,26 +244,30 @@ func F16(rx typex.RuleX) func(l *lua.LState) int { return 1 } Device := rx.GetDevice(devUUID) - if Device != nil { - if Device.Type != typex.GENERIC_MODBUS { - l.Push(lua.LString("Only support GENERIC_MODBUS device")) - return 1 - } - if Device.Device.Status() == typex.DEV_UP { - args, _ := json.Marshal(common.RegisterW{ - Function: 16, - SlaverId: byte(slaverId), - Address: uint16(Address), - Quantity: uint16(Quantity), - Values: HexValues, - }) - _, err := Device.Device.OnWrite([]byte("F16"), args) - if err != nil { - glogger.GLogger.Error(err) - l.Push(lua.LString(err.Error())) - return 1 - } - } + if Device == nil { + l.Push(lua.LString("Device is not exists")) + return 1 + } + if Device.Type != typex.GENERIC_MODBUS { + l.Push(lua.LString("Only support GENERIC_MODBUS device")) + return 1 + } + if Device.Device.Status() != typex.DEV_UP { + l.Push(lua.LString("device down:" + devUUID)) + return 1 + } + args, _ := json.Marshal(common.RegisterW{ + Function: 16, + SlaverId: byte(slaverId), + Address: uint16(Address), + Quantity: uint16(Quantity), + Values: HexValues, + }) + _, err0 := Device.Device.OnWrite([]byte("F16"), args) + if err0 != nil { + glogger.GLogger.Error(err0) + l.Push(lua.LString(err0.Error())) + return 1 } l.Push(lua.LNil) return 1 diff --git a/typex/version.go b/typex/version.go index 1a41c0ace..c1038487e 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-03 18:45:36", + ReleaseTime: "2023-12-04 23:57:37", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-42c88f0b777b22d +** Version: v0.6.4-9181776715a851e ** Document: https://hootrhino.github.io ` From 5c62e76b4f01f334c30abadb3015261e3a839031 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 5 Dec 2023 00:12:25 +0800 Subject: [PATCH 088/138] dev; enhance modbus --- common/modbus_config.go | 15 ++++++++------- device/generic_modbus_device.go | 5 +++-- driver/modbus_rtu_driver.go | 5 ++++- driver/modbus_tcp_driver.go | 5 ++++- typex/version.go | 4 ++-- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/common/modbus_config.go b/common/modbus_config.go index 0cdc35e8d..a2de155f9 100644 --- a/common/modbus_config.go +++ b/common/modbus_config.go @@ -39,13 +39,14 @@ type Registers struct { * */ type RegisterRW struct { - Tag string `json:"tag" validate:"required" title:"数据Tag"` // 数据Tag - Alias string `json:"alias" validate:"required" title:"别名"` // 别名 - Function int `json:"function" validate:"required" title:"Modbus功能"` // Function - SlaverId byte `json:"slaverId" validate:"required" title:"从机ID"` // 从机ID - Address uint16 `json:"address" validate:"required" title:"地址"` // Address - Quantity uint16 `json:"quantity" validate:"required" title:"数量"` // Quantity - Value string `json:"value" title:"值" info:"本地系统的串口路径"` // Value + Tag string `json:"tag" validate:"required" title:"数据Tag"` // 数据Tag + Alias string `json:"alias" validate:"required" title:"别名"` // 别名 + Function int `json:"function" validate:"required" title:"Modbus功能"` // Function + SlaverId byte `json:"slaverId" validate:"required" title:"从机ID"` // 从机ID + Address uint16 `json:"address" validate:"required" title:"地址"` // Address + Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` // 间隔 + Quantity uint16 `json:"quantity" validate:"required" title:"数量"` // Quantity + Value string `json:"value" title:"值" info:"本地系统的串口路径"` // Value } /* diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index 3f08a883e..0cc227ccf 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -192,7 +192,6 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { mdev.tcpHandler.Logger = golog.New(glogger.GLogger.Writer(), "Modbus TCP Mode: "+mdev.PointId+", ", golog.LstdFlags) } - if err := mdev.tcpHandler.Connect(); err != nil { return err } @@ -222,7 +221,9 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { if err != nil { glogger.GLogger.Error(err) mdev.retryTimes++ - } else { + continue + } + if n > 0 { mdev.RuleEngine.WorkDevice(mdev.Details(), string(buffer[:n])) } } diff --git a/driver/modbus_rtu_driver.go b/driver/modbus_rtu_driver.go index 09565d08a..6f372f95e 100644 --- a/driver/modbus_rtu_driver.go +++ b/driver/modbus_rtu_driver.go @@ -64,6 +64,9 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { var results []byte dataMap := map[string]common.RegisterRW{} count := len(d.Registers) + if count == 0 { + return 0, nil + } for _, r := range d.Registers { d.handler.SlaveId = r.SlaverId if r.Function == common.READ_COIL { @@ -135,7 +138,7 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { } dataMap[r.Tag] = value } - time.Sleep(time.Duration(d.frequency) * time.Millisecond) + time.Sleep(time.Duration(r.Frequency) * time.Millisecond) } bytes, _ := json.Marshal(dataMap) copy(data, bytes) diff --git a/driver/modbus_tcp_driver.go b/driver/modbus_tcp_driver.go index e9eb498ac..20788b898 100644 --- a/driver/modbus_tcp_driver.go +++ b/driver/modbus_tcp_driver.go @@ -64,6 +64,9 @@ func (d *modBusTCPDriver) Read(cmd []byte, data []byte) (int, error) { var err error var results []byte count := len(d.Registers) + if count == 0 { + return 0, nil + } for _, r := range d.Registers { d.handler.SlaveId = r.SlaverId if r.Function == common.READ_COIL { @@ -135,7 +138,7 @@ func (d *modBusTCPDriver) Read(cmd []byte, data []byte) (int, error) { } dataMap[r.Tag] = value } - time.Sleep(time.Duration(d.frequency) * time.Millisecond) + time.Sleep(time.Duration(r.Frequency) * time.Millisecond) } bytes, _ := json.Marshal(dataMap) copy(data, bytes) diff --git a/typex/version.go b/typex/version.go index c1038487e..18b573e82 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-04 23:57:37", + ReleaseTime: "2023-12-05 00:07:35", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-9181776715a851e +** Version: v0.6.4-5c84edc0a95be01 ** Document: https://hootrhino.github.io ` From 0d1a6390a1925e58042dafc0e5e02b115e8ea300 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 5 Dec 2023 21:07:05 +0800 Subject: [PATCH 089/138] feat: add user lua template api --- plugin/rulex_api_server/apis/device_api.go | 2 +- .../apis/user_lua_template_api.go | 199 ++++++++++++++++++ plugin/rulex_api_server/apis/visual_api.go | 2 +- plugin/rulex_api_server/http_api_server.go | 13 ++ .../model/user_lua_template.go | 28 +++ plugin/rulex_api_server/server/apiserver.go | 6 + .../rulex_api_server/service/group_service.go | 63 ++++-- .../service/user_lua_template_service.go | 76 +++++++ typex/version.go | 4 +- utils/uuid_util.go | 5 + 10 files changed, 380 insertions(+), 18 deletions(-) create mode 100644 plugin/rulex_api_server/apis/user_lua_template_api.go create mode 100644 plugin/rulex_api_server/model/user_lua_template.go create mode 100644 plugin/rulex_api_server/service/user_lua_template_service.go diff --git a/plugin/rulex_api_server/apis/device_api.go b/plugin/rulex_api_server/apis/device_api.go index 23ae1b24c..907c2bd9f 100644 --- a/plugin/rulex_api_server/apis/device_api.go +++ b/plugin/rulex_api_server/apis/device_api.go @@ -68,7 +68,7 @@ func DeviceDetail(c *gin.Context, ruleEngine typex.RuleX) { func ListDeviceByGroup(c *gin.Context, ruleEngine typex.RuleX) { Gid, _ := c.GetQuery("uuid") devices := []DeviceVo{} - _, MDevices := service.FindByType(Gid, "DEVICE") + MDevices := service.FindDeviceByGroup(Gid) for _, mdev := range MDevices { DeviceVo := DeviceVo{} DeviceVo.UUID = mdev.UUID diff --git a/plugin/rulex_api_server/apis/user_lua_template_api.go b/plugin/rulex_api_server/apis/user_lua_template_api.go new file mode 100644 index 000000000..509e4c2ef --- /dev/null +++ b/plugin/rulex_api_server/apis/user_lua_template_api.go @@ -0,0 +1,199 @@ +package apis + +import ( + "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" +) + +type UserLuaTemplateVo struct { + Gid string `json:"gid,omitempty"` // 分组ID + UUID string `json:"uuid,omitempty"` // 名称 + Label string `json:"label"` //快捷代码名称 + Apply string `json:"apply"` //快捷代码 + Type string `json:"type"` // 类型 固定为function类型detail +} + +/* +* +* 新建用户模板 +* + */ + +func CreateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { + form := UserLuaTemplateVo{Type: "function"} + if err := c.ShouldBindJSON(&form); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + _, err0 := service.GetGenericGroupWithUUID(form.Gid) + if err0 != nil { + c.JSON(common.HTTP_OK, common.Error400(err0)) + return + } + MUserLuaTemplate := model.MUserLuaTemplate{ + UUID: utils.UserLuaUuid(), + Label: form.Label, + Type: "function", + Apply: form.Apply, + } + if err := service.InsertUserLuaTemplate(MUserLuaTemplate); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // 新建用户模板的时候必须给一个分组 + if err := service.BindResource(form.Gid, MUserLuaTemplate.UUID); err != nil { + c.JSON(common.HTTP_OK, common.Error("Group not found")) + return + } + // 返回新建的用户模板字段 用来跳转编辑器 + c.JSON(common.HTTP_OK, common.OkWithData(map[string]string{ + "uuid": MUserLuaTemplate.UUID, + })) + +} + +/* +* +* 更新用户模板 +* + */ +func UpdateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { + form := UserLuaTemplateVo{} + if err := c.ShouldBindJSON(&form); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + MUserLuaTemplate := model.MUserLuaTemplate{ + UUID: form.UUID, + Label: form.Label, + Type: form.Type, + Apply: form.Apply, + } + + if err := service.UpdateUserLuaTemplate(MUserLuaTemplate); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // 取消绑定分组,删除原来旧的分组 + Group := service.GetUserLuaTemplateGroup(MUserLuaTemplate.UUID) + if err := service.UnBindResource(Group.UUID, MUserLuaTemplate.UUID); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // 重新绑定分组 + if err := service.BindResource(form.Gid, MUserLuaTemplate.UUID); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // 返回新建的用户模板字段 用来跳转编辑器 + c.JSON(common.HTTP_OK, common.OkWithData(map[string]string{ + "uuid": MUserLuaTemplate.UUID, + })) +} + +/* +* +* 删除用户模板 +* + */ +func DeleteUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { + uuid, _ := c.GetQuery("uuid") + if err := service.DeleteUserLuaTemplate(uuid); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) + +} +func ListUserLuaTemplateGroup(c *gin.Context, ruleEngine typex.RuleX) { + visuals := []MGenericGroupVo{} + for _, vv := range service.ListByGroupType("USER_LUA_TEMPLATE") { + visuals = append(visuals, MGenericGroupVo{ + UUID: vv.UUID, + Name: vv.Name, + Type: vv.Type, + Parent: vv.Parent, + }) + } + c.JSON(common.HTTP_OK, common.OkWithData(visuals)) +} + +/* +* +* 用户模板列表 +* + */ +func ListUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { + UserLuaTemplates := []UserLuaTemplateVo{} + for _, vv := range service.AllUserLuaTemplate() { + Vo := UserLuaTemplateVo{ + UUID: vv.UUID, + Label: vv.Label, + Type: vv.Type, + Apply: vv.Apply, + } + Group := service.GetUserLuaTemplateGroup(vv.UUID) + if Group.UUID != "" { + Vo.Gid = Group.UUID + } else { + Vo.Gid = "" + } + UserLuaTemplates = append(UserLuaTemplates, Vo) + } + c.JSON(common.HTTP_OK, common.OkWithData(UserLuaTemplates)) + +} + +/* +* +* 用户模板分组查看 +* + */ +func ListUserLuaTemplateByGroup(c *gin.Context, ruleEngine typex.RuleX) { + Gid, _ := c.GetQuery("uuid") + UserLuaTemplates := []UserLuaTemplateVo{} + MUserLuaTemplates := service.FindUserTemplateByGroup(Gid) + for _, vv := range MUserLuaTemplates { + Vo := UserLuaTemplateVo{ + UUID: vv.UUID, + Label: vv.Label, + Type: vv.Type, + Apply: vv.Apply, + } + Group := service.GetUserLuaTemplateGroup(vv.UUID) + Vo.Gid = Group.UUID + UserLuaTemplates = append(UserLuaTemplates, Vo) + } + c.JSON(common.HTTP_OK, common.OkWithData(UserLuaTemplates)) +} + +/* +* +* 用户模板详情 +* + */ +func UserLuaTemplateDetail(c *gin.Context, ruleEngine typex.RuleX) { + uuid, _ := c.GetQuery("uuid") + mUserLuaTemplate, err := service.GetUserLuaTemplateWithUUID(uuid) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + Vo := UserLuaTemplateVo{ + UUID: mUserLuaTemplate.UUID, + Label: mUserLuaTemplate.Label, + Type: mUserLuaTemplate.Type, + Apply: mUserLuaTemplate.Apply, + } + Group := service.GetUserLuaTemplateGroup(mUserLuaTemplate.UUID) + if Group.UUID != "" { + Vo.Gid = Group.UUID + } else { + Vo.Gid = "" + } + c.JSON(common.HTTP_OK, common.OkWithData(Vo)) +} diff --git a/plugin/rulex_api_server/apis/visual_api.go b/plugin/rulex_api_server/apis/visual_api.go index e6bf6a142..1b95cdf30 100644 --- a/plugin/rulex_api_server/apis/visual_api.go +++ b/plugin/rulex_api_server/apis/visual_api.go @@ -180,7 +180,7 @@ func ListVisual(c *gin.Context, ruleEngine typex.RuleX) { func ListVisualByGroup(c *gin.Context, ruleEngine typex.RuleX) { Gid, _ := c.GetQuery("uuid") visuals := []VisualVo{} - MVisuals, _ := service.FindByType(Gid, "VISUAL") + MVisuals := service.FindVisualByGroup(Gid) for _, vv := range MVisuals { Vo := VisualVo{ UUID: vv.UUID, diff --git a/plugin/rulex_api_server/http_api_server.go b/plugin/rulex_api_server/http_api_server.go index d1d2cb1e0..6b764e18e 100644 --- a/plugin/rulex_api_server/http_api_server.go +++ b/plugin/rulex_api_server/http_api_server.go @@ -213,6 +213,7 @@ func (hs *ApiServerPlugin) Init(config *ini.Section) error { &model.MCronResult{}, &model.MHwPort{}, &model.MInternalNotify{}, + &model.MUserLuaTemplate{}, ) // 初始化所有预制参数 server.DefaultApiServer.InitializeGenericOSData() @@ -395,6 +396,18 @@ func (hs *ApiServerPlugin) LoadRoute() { visualApi.POST("/thumbnail", server.AddRoute(apis.UploadFile)) visualApi.GET("/thumbnail", server.AddRoute(apis.GetThumbnail)) } + // + // 用户LUA代码段管理 + // + userLuaApi := server.RouteGroup(server.ContextUrl("/userlua")) + { + userLuaApi.POST("/create", server.AddRoute(apis.CreateUserLuaTemplate)) + userLuaApi.PUT("/update", server.AddRoute(apis.UpdateUserLuaTemplate)) + userLuaApi.GET("/listByGroup", server.AddRoute(apis.ListUserLuaTemplateByGroup)) + userLuaApi.GET("/detail", server.AddRoute(apis.UserLuaTemplateDetail)) + userLuaApi.GET("/group", server.AddRoute(apis.ListUserLuaTemplateGroup)) + userLuaApi.DELETE("/delete", server.AddRoute(apis.DeleteUserLuaTemplate)) + } /* * * 模型管理 diff --git a/plugin/rulex_api_server/model/user_lua_template.go b/plugin/rulex_api_server/model/user_lua_template.go new file mode 100644 index 000000000..20c7cc466 --- /dev/null +++ b/plugin/rulex_api_server/model/user_lua_template.go @@ -0,0 +1,28 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +package model + +/* +* +* 用户自定义代码模板 +* + */ +type MUserLuaTemplate struct { + RulexModel + UUID string + Type string // 类型 固定为 'function' + Label string //快捷代码名称 + Apply string //快捷代码 +} diff --git a/plugin/rulex_api_server/server/apiserver.go b/plugin/rulex_api_server/server/apiserver.go index 7dda03cca..72e3c701b 100644 --- a/plugin/rulex_api_server/server/apiserver.go +++ b/plugin/rulex_api_server/server/apiserver.go @@ -233,6 +233,12 @@ func initStaticModel() { Name: "默认分组", Parent: "NULL", }) + service.InitGenericGroup(&model.MGenericGroup{ + UUID: "ULTROOT", + Type: "USER_LUA_TEMPLATE", + Name: "默认分组", + Parent: "NULL", + }) // 初始化网站配置 service.InitSiteConfig(model.MSiteConfig{ SiteName: "Rhino EEKit", diff --git a/plugin/rulex_api_server/service/group_service.go b/plugin/rulex_api_server/service/group_service.go index a14ef3a6c..cce4bc8db 100644 --- a/plugin/rulex_api_server/service/group_service.go +++ b/plugin/rulex_api_server/service/group_service.go @@ -34,30 +34,65 @@ func ListByGroupType(t string) []model.MGenericGroup { /* * - - 根据分组类型查询:DEVICE, VISUAL +* 查询分组下的设备 +* + */ +func FindDeviceByGroup(uuid string) []model.MDevice { + sql := ` +WHERE uuid IN ( + SELECT m_generic_group_relations.rid + FROM m_generic_groups + LEFT JOIN + m_generic_group_relations ON (m_generic_groups.uuid = m_generic_group_relations.gid) + WHERE type = 'DEVICE' AND gid = ? +);` + + m := []model.MDevice{} + interdb.DB().Raw(`SELECT * FROM m_devices `+sql, uuid).Find(&m) + return m + +} + +/* +* +* 查询分组吓得大屏 +* + */ +func FindVisualByGroup(uuid string) []model.MVisual { + sql := ` +WHERE uuid IN ( + SELECT m_generic_group_relations.rid + FROM m_generic_groups + LEFT JOIN + m_generic_group_relations ON (m_generic_groups.uuid = m_generic_group_relations.gid) + WHERE type = 'VISUAL' AND gid = ? +);` + + m := []model.MVisual{} + interdb.DB().Raw(`SELECT * FROM m_visuals `+sql, uuid).Find(&m) + return m + +} + +/* +* + - 根据分组类型查询:代码模板 *~ */ -func FindByType(uuid, t string) ([]model.MVisual, []model.MDevice) { +func FindUserTemplateByGroup(uuid string) []model.MUserLuaTemplate { sql := ` WHERE uuid IN ( SELECT m_generic_group_relations.rid FROM m_generic_groups LEFT JOIN m_generic_group_relations ON (m_generic_groups.uuid = m_generic_group_relations.gid) - WHERE type = ? AND gid = ? + WHERE type = 'USER_LUA_TEMPLATE' AND gid = ? );` - if t == "VISUAL" { - m := []model.MVisual{} - interdb.DB().Raw(`SELECT * FROM m_visuals `+sql, t, uuid).Find(&m) - return m, nil - } - if t == "DEVICE" { - m := []model.MDevice{} - interdb.DB().Raw(`SELECT * FROM m_devices `+sql, t, uuid).Find(&m) - return nil, m - } - return nil, nil + m := []model.MUserLuaTemplate{} + interdb.DB().Raw(`SELECT * FROM m_user_lua_templates `+sql, uuid).Find(&m) + return m + } func GetGenericGroupWithUUID(uuid string) (*model.MGenericGroup, error) { diff --git a/plugin/rulex_api_server/service/user_lua_template_service.go b/plugin/rulex_api_server/service/user_lua_template_service.go new file mode 100644 index 000000000..8ba12be19 --- /dev/null +++ b/plugin/rulex_api_server/service/user_lua_template_service.go @@ -0,0 +1,76 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package service + +import ( + "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/plugin/rulex_api_server/model" +) + +// 获取UserLuaTemplate列表 +func AllUserLuaTemplate() []model.MUserLuaTemplate { + m := []model.MUserLuaTemplate{} + interdb.DB().Find(&m) + return m + +} + +/* +* +* 获取分组 +* + */ +func GetUserLuaTemplateGroup(rid string) model.MGenericGroup { + sql := ` +SELECT m_generic_groups.* + FROM m_generic_group_relations + LEFT JOIN + m_generic_groups ON (m_generic_groups.uuid = m_generic_group_relations.gid) + WHERE m_generic_group_relations.rid = ?; +` + m := model.MGenericGroup{} + interdb.DB().Raw(sql, rid).Find(&m) + return m +} + +/* +* +* ID获取 +* + */ +func GetUserLuaTemplateWithUUID(uuid string) (model.MUserLuaTemplate, error) { + m := model.MUserLuaTemplate{} + err := interdb.DB().Where("uuid=?", uuid).First(&m).Error + return m, err +} + +// 删除UserLuaTemplate +func DeleteUserLuaTemplate(uuid string) error { + return interdb.DB().Where("uuid=?", uuid).Delete(&model.MUserLuaTemplate{}).Error +} + +// 创建UserLuaTemplate +func InsertUserLuaTemplate(UserLuaTemplate model.MUserLuaTemplate) error { + return interdb.DB().Create(&UserLuaTemplate).Error +} + +// 更新UserLuaTemplate +func UpdateUserLuaTemplate(UserLuaTemplate model.MUserLuaTemplate) error { + return interdb.DB(). + Model(UserLuaTemplate). + Where("uuid=?", UserLuaTemplate.UUID). + Updates(&UserLuaTemplate).Error +} diff --git a/typex/version.go b/typex/version.go index 18b573e82..03b0b41e0 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-05 00:07:35", + ReleaseTime: "2023-12-05 20:54:27", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-5c84edc0a95be01 +** Version: v0.6.4-5c62e76b4f01f33 ** Document: https://hootrhino.github.io ` diff --git a/utils/uuid_util.go b/utils/uuid_util.go index 9f6ebaa60..7c17e7e45 100644 --- a/utils/uuid_util.go +++ b/utils/uuid_util.go @@ -50,6 +50,11 @@ func RuleUuid() string { return MakeUUID("RULE") } +// MakeUUID +func UserLuaUuid() string { + return MakeUUID("USERLUA") +} + // MakeUUID func MakeUUID(prefix string) string { return prefix + strings.ToUpper(shortuuid.New()[:6]) From 197287bd39f45e9ff2eb7c6982c36dabe3fb0b52 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 5 Dec 2023 21:15:03 +0800 Subject: [PATCH 090/138] doc: add some doc --- source/readme.md | 46 ++-------------------------------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/source/readme.md b/source/readme.md index 3a3799632..5009d0ee6 100644 --- a/source/readme.md +++ b/source/readme.md @@ -1,44 +1,2 @@ -## - -### 开发模板 -资源需要实现以下接口: -```go - -type XSource interface { - Test(inEndId string) bool - Init(inEndId string, cfg map[string]interface{}) error - Start(CCTX) error - DataModels() []XDataModel - Status() SourceState - Details() *InEnd - Driver() XExternalDriver - Topology() []TopologyPoint - Stop() -} - -``` -### 加载配置 -我们以一个 `COAP Server` 为例来解释,首先定义一个配置结构体: -```go -type coAPConfig struct { - Port uint16 `json:"port" validate:"required" title:"端口"` - DataModels []typex.XDataModel `json:"dataModels" title:"数据模型"` -} -``` -然后在Init里面解析外部配置到资源的配置结构体,相当于是加载配置: -```go - -func (cc *coAPInEndSource) Init(inEndId string, cfg map[string]interface{}) error { - cc.PointId = inEndId - var mainConfig coAPConfig - if err := utils.BindSourceConfig(cfg, &mainConfig); err != nil { - return err - } - cc.port = mainConfig.Port - cc.dataModels = mainConfig.DataModels - return nil -} -``` -参数说明 -- inEndId:资源元数据的ID -- cfg:配置数据的Map形式结构 \ No newline at end of file +## 外部双向、单向资源 +主要用来和外部资源对接,比如Mqtt等。具备双向通信的功能。 \ No newline at end of file From 098cdcb3acf3ee2c164b251385b0c20b437ea2a6 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 5 Dec 2023 22:35:48 +0800 Subject: [PATCH 091/138] fix: fix rule update missing bind list --- device/rhinopi_ir_control_device_linux.go | 33 +++++++----- device/rhinopi_ir_control_device_windows.go | 31 +++++++---- plugin/rulex_api_server/apis/rule_api.go | 59 ++++++++++++++------- plugin/rulex_api_server/service/dao.go | 18 ++----- typex/version.go | 4 +- 5 files changed, 87 insertions(+), 58 deletions(-) diff --git a/device/rhinopi_ir_control_device_linux.go b/device/rhinopi_ir_control_device_linux.go index 0f0ea2e96..615b54f8b 100644 --- a/device/rhinopi_ir_control_device_linux.go +++ b/device/rhinopi_ir_control_device_linux.go @@ -27,27 +27,27 @@ Found /sys/class/rc/rc0/ (/dev/input/event1) with: bus: 25, vendor/product: 0001:0001, version: 0x0100 Repeat delay = 500 ms, repeat period = 125 ms */ +type __IrConfig struct { + InputHandle string `json:"inputHandle"` // 信号源 +} type IR struct { typex.XStatus status typex.DeviceState irFd int // irFd syscall.Handle windows RuleEngine typex.RuleX + mainConfig __IrConfig } func NewIRDevice(e typex.RuleX) typex.XDevice { uart := new(IR) uart.RuleEngine = e + uart.mainConfig = __IrConfig{ + InputHandle: __IR_DEV, + } return uart } -//  初始化 -func (ird *IR) Init(devId string, configMap map[string]interface{}) error { - ird.PointId = devId - - return nil -} - type timeval struct { Second int32 `json:"second,omitempty"` USecond int32 `json:"uSecond,omitempty"` @@ -64,12 +64,19 @@ func (v irInputEvent) String() string { return string(b) } +//  初始化 +func (ird *IR) Init(devId string, configMap map[string]interface{}) error { + ird.PointId = devId + + return nil +} + // 启动 func (ird *IR) Start(cctx typex.CCTX) error { ird.Ctx = cctx.Ctx ird.CancelCTX = cctx.CancelCTX - fd, err := syscall.Open("/dev/input/event1", syscall.O_RDONLY, 0777) + fd, err := syscall.Open(ird.mainConfig.InputHandle, syscall.O_RDONLY, 0777) if err != nil { fmt.Printf("device open failed\r\n") syscall.Close(fd) @@ -89,17 +96,19 @@ func (ird *IR) Start(cctx typex.CCTX) error { { } } - n, e := syscall.Read(fd, buf) + n1, e := syscall.Read(fd, buf) if e != nil { glogger.GLogger.Error(e) continue } - if n > 0 { + if n1 > 0 { event := irInputEvent{} - _, err := syscall.Read(fd, (*[24]byte)(unsafe.Pointer(&event))[:]) + n2, err := syscall.Read(fd, (*[24]byte)(unsafe.Pointer(&event))[:]) if err != nil { glogger.GLogger.Error(err) - } else { + continue + } + if n2 > 0 { ird.RuleEngine.WorkDevice(ird.Details(), event.String()) } } diff --git a/device/rhinopi_ir_control_device_windows.go b/device/rhinopi_ir_control_device_windows.go index 99379198e..1e7a260c4 100644 --- a/device/rhinopi_ir_control_device_windows.go +++ b/device/rhinopi_ir_control_device_windows.go @@ -27,25 +27,26 @@ Found /sys/class/rc/rc0/ (/dev/input/event1) with: bus: 25, vendor/product: 0001:0001, version: 0x0100 Repeat delay = 500 ms, repeat period = 125 ms */ +type __IrConfig struct { + InputHandle string `json:"inputHandle"` // 信号源 +} type IR struct { typex.XStatus status typex.DeviceState irFd syscall.Handle RuleEngine typex.RuleX + mainConfig __IrConfig } func NewIRDevice(e typex.RuleX) typex.XDevice { uart := new(IR) uart.RuleEngine = e + uart.mainConfig = __IrConfig{ + InputHandle: __IR_DEV, + } return uart } -//  初始化 -func (ird *IR) Init(devId string, configMap map[string]interface{}) error { - ird.PointId = devId - return nil -} - type timeval struct { Second int32 `json:"second,omitempty"` USecond int32 `json:"uSecond,omitempty"` @@ -62,12 +63,18 @@ func (v irInputEvent) String() string { return string(b) } +//  初始化 +func (ird *IR) Init(devId string, configMap map[string]interface{}) error { + ird.PointId = devId + return nil +} + // 启动 func (ird *IR) Start(cctx typex.CCTX) error { ird.Ctx = cctx.Ctx ird.CancelCTX = cctx.CancelCTX - fd, err := syscall.Open(__IR_DEV, syscall.O_RDONLY, 0777) + fd, err := syscall.Open(ird.mainConfig.InputHandle, syscall.O_RDONLY, 0777) if err != nil { fmt.Printf("device open failed\r\n") syscall.Close(fd) @@ -84,17 +91,19 @@ func (ird *IR) Start(cctx typex.CCTX) error { { } } - n, e := syscall.Read(fd, buf) + n1, e := syscall.Read(fd, buf) if e != nil { glogger.GLogger.Error(e) continue } - if n > 0 { + if n1 > 0 { event := irInputEvent{} - _, err := syscall.Read(fd, (*[24]byte)(unsafe.Pointer(&event))[:]) + n2, err := syscall.Read(fd, (*[24]byte)(unsafe.Pointer(&event))[:]) if err != nil { glogger.GLogger.Error(err) - } else { + continue + } + if n2 > 0 { ird.RuleEngine.WorkDevice(ird.Details(), event.String()) } } diff --git a/plugin/rulex_api_server/apis/rule_api.go b/plugin/rulex_api_server/apis/rule_api.go index e699d733b..389d2c188 100644 --- a/plugin/rulex_api_server/apis/rule_api.go +++ b/plugin/rulex_api_server/apis/rule_api.go @@ -140,14 +140,6 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) return } - BindRules := []string{rule.UUID} - InEnd.BindRules = BindRules - if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ - BindRules: BindRules, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } // SaveDB // mRule := &model.MRule{ @@ -160,6 +152,26 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { Failed: form.Failed, Actions: form.Actions, } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range InEnd.BindRules { + ruleMap[rule] = rule + } + // 追加新的ID + ruleMap[inId] = mRule.UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + InEnd.BindRules = BindRules + if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ + BindRules: BindRules, + }); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + if err := service.InsertMRule(mRule); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return @@ -179,14 +191,10 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) return } - // 最后ID列表 - BindRules := []string{rule.UUID} - Device.BindRules = BindRules - if err := service.UpdateDevice(Device.UUID, &model.MDevice{ - BindRules: BindRules, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range Device.BindRules { + ruleMap[rule] = rule // for ["", "", "" ....] } // SaveDB mRule := &model.MRule{ @@ -199,6 +207,21 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { Failed: form.Failed, Actions: form.Actions, } + // 追加新的ID + ruleMap[devId] = mRule.UUID // append New Rule UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + Device.BindRules = BindRules + if err := service.UpdateDevice(Device.UUID, &model.MDevice{ + BindRules: BindRules, + }); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + if err := service.InsertMRule(mRule); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return @@ -339,10 +362,10 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { // 去重旧的 ruleMap := map[string]string{} for _, rule := range Device.BindRules { - ruleMap[rule] = rule + ruleMap[rule] = rule // for ["", "", "" ....] } // 追加新的ID - ruleMap[devId] = mRule.UUID + ruleMap[devId] = mRule.UUID // append New Rule UUID // 最后ID列表 BindRules := []string{} for _, iid := range ruleMap { diff --git a/plugin/rulex_api_server/service/dao.go b/plugin/rulex_api_server/service/dao.go index 209d45a4a..101bef191 100644 --- a/plugin/rulex_api_server/service/dao.go +++ b/plugin/rulex_api_server/service/dao.go @@ -10,28 +10,16 @@ import ( // ----------------------------------------------------------------------------------- func GetMRule(uuid string) (*model.MRule, error) { m := new(model.MRule) - if err := interdb.DB().Where("uuid=?", uuid).First(m).Error; err != nil { - return nil, err - } else { - return m, nil - } + return m, interdb.DB().Where("uuid=?", uuid).First(m).Error } func GetAllMRule() ([]model.MRule, error) { m := []model.MRule{} - if err := interdb.DB().Find(&m).Error; err != nil { - return nil, err - } else { - return m, nil - } + return m, interdb.DB().Find(&m).Error } func GetMRuleWithUUID(uuid string) (*model.MRule, error) { m := new(model.MRule) - if err := interdb.DB().Where("uuid=?", uuid).First(m).Error; err != nil { - return nil, err - } else { - return m, nil - } + return m, interdb.DB().Where("uuid=?", uuid).First(m).Error } func InsertMRule(r *model.MRule) error { diff --git a/typex/version.go b/typex/version.go index 03b0b41e0..a6a510d41 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-05 20:54:27", + ReleaseTime: "2023-12-05 22:28:39", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-5c62e76b4f01f33 +** Version: v0.6.4-197287bd39f45e9 ** Document: https://hootrhino.github.io ` From c36c563c96bd80ab57bd681b039ce7088b06d130 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 5 Dec 2023 23:30:07 +0800 Subject: [PATCH 092/138] dev: add supervisor --- component/supervisor/device_supervisor.go | 75 ++++++++++++++++++++++ component/supervisor/inend_supervisor.go | 76 +++++++++++++++++++++++ component/supervisor/outend_supervisor.go | 76 +++++++++++++++++++++++ component/supervisor/readme.md | 2 + 4 files changed, 229 insertions(+) create mode 100644 component/supervisor/device_supervisor.go create mode 100644 component/supervisor/inend_supervisor.go create mode 100644 component/supervisor/outend_supervisor.go create mode 100644 component/supervisor/readme.md diff --git a/component/supervisor/device_supervisor.go b/component/supervisor/device_supervisor.go new file mode 100644 index 000000000..30ea35534 --- /dev/null +++ b/component/supervisor/device_supervisor.go @@ -0,0 +1,75 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +package supervisor + +import ( + "context" + "fmt" + "time" + + "github.com/hootrhino/rulex/component/internotify" + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/typex" +) + +func StartDeviceSupervisor(ctx context.Context, device *typex.Device, ruleEngine typex.RuleX) { + UUID := device.UUID + ticker := time.NewTicker(time.Duration(time.Second * 5)) + defer func() { + ticker.Stop() + }() + for { + select { + case <-ctx.Done(): + { + ticker.Stop() + glogger.GLogger.Debugf("Device Context cancel:%v, supervisor exit", UUID) + return + } + case <-typex.GCTX.Done(): + { + return + } + default: + { + } + } + currentDevice := ruleEngine.GetDevice(UUID) + if currentDevice == nil { + glogger.GLogger.Debugf("Device:%v Deleted, supervisor exit", UUID) + return + } + if currentDevice.Device.Status() == typex.DEV_STOP { + glogger.GLogger.Debugf("Device:%v Stopped, supervisor exit", UUID) + return + } + // 资源可能不会及时DOWN + if currentDevice.Device.Status() == typex.DEV_DOWN { + info := fmt.Sprintf("Device:%v DOWN, supervisor try to Restart", UUID) + glogger.GLogger.Debugf(info) + internotify.Push(internotify.BaseEvent{ + Type: "DEVICE", + Event: "event.down", + Ts: uint64(time.Now().UnixNano()), + Info: info, + }) + time.Sleep(4 * time.Second) + // go LoadNewestDevice(UUID, ruleEngine) + return + } + // glogger.GLogger.Debugf("Supervisor Get Device :%v state:%v", UUID, currentDevice.Device.Status().String()) + <-ticker.C + } +} diff --git a/component/supervisor/inend_supervisor.go b/component/supervisor/inend_supervisor.go new file mode 100644 index 000000000..3766b0749 --- /dev/null +++ b/component/supervisor/inend_supervisor.go @@ -0,0 +1,76 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package supervisor + +import ( + "context" + "fmt" + "time" + + "github.com/hootrhino/rulex/component/internotify" + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/typex" +) + +func StartInSupervisor(ctx context.Context, in *typex.InEnd, ruleEngine typex.RuleX) { + UUID := in.UUID + ticker := time.NewTicker(time.Duration(time.Second * 5)) + defer func() { + ticker.Stop() + }() + for { + select { + case <-ctx.Done(): + { + ticker.Stop() + glogger.GLogger.Debugf("Source Context cancel:%v, supervisor exit", UUID) + return + } + case <-typex.GCTX.Done(): + { + return + } + default: + { + } + } + currentIn := ruleEngine.GetInEnd(UUID) + if currentIn == nil { + glogger.GLogger.Debugf("Source:%v Deleted, supervisor exit", UUID) + return + } + if currentIn.Source.Status() == typex.SOURCE_STOP { + glogger.GLogger.Debugf("Source:%v Stopped, supervisor exit", UUID) + return + } + // 资源可能不会及时DOWN + if currentIn.Source.Status() == typex.SOURCE_DOWN { + info := fmt.Sprintf("Source:%v DOWN, supervisor try to Restart", UUID) + glogger.GLogger.Debugf(info) + internotify.Push(internotify.BaseEvent{ + Type: "SOURCE", + Event: "event.down", + Ts: uint64(time.Now().UnixNano()), + Info: info, + }) + time.Sleep(4 * time.Second) + // go LoadNewestInEnd(UUID, ruleEngine) + return + } + // glogger.GLogger.Debugf("Supervisor Get Source :%v state:%v", UUID, currentIn.Source.Status().String()) + <-ticker.C + } +} diff --git a/component/supervisor/outend_supervisor.go b/component/supervisor/outend_supervisor.go new file mode 100644 index 000000000..355969bde --- /dev/null +++ b/component/supervisor/outend_supervisor.go @@ -0,0 +1,76 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package supervisor + +import ( + "context" + "fmt" + "time" + + "github.com/hootrhino/rulex/component/internotify" + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/typex" +) + +func StartOutSupervisor(ctx context.Context, out *typex.OutEnd, ruleEngine typex.RuleX) { + UUID := out.UUID + ticker := time.NewTicker(time.Duration(time.Second * 5)) + defer func() { + ticker.Stop() + }() + for { + select { + case <-ctx.Done(): + { + ticker.Stop() + glogger.GLogger.Debugf("OutEnd Context cancel:%v, supervisor exit", UUID) + return + } + case <-typex.GCTX.Done(): + { + return + } + default: + { + } + } + currentOut := ruleEngine.GetOutEnd(UUID) + if currentOut == nil { + glogger.GLogger.Debugf("OutEnd:%v Deleted, supervisor exit", UUID) + return + } + if currentOut.Target.Status() == typex.SOURCE_STOP { + glogger.GLogger.Debugf("OutEnd:%v Stopped, supervisor exit", UUID) + return + } + // 资源可能不会及时DOWN + if currentOut.Target.Status() == typex.SOURCE_DOWN { + info := fmt.Sprintf("OutEnd:%v DOWN, supervisor try to Restart", UUID) + glogger.GLogger.Debugf(info) + internotify.Push(internotify.BaseEvent{ + Type: "TARGET", + Event: "event.down", + Ts: uint64(time.Now().UnixNano()), + Info: info, + }) + time.Sleep(4 * time.Second) + // go LoadNewestOutEnd(UUID, ruleEngine) + return + } + // glogger.GLogger.Debugf("Supervisor Get OutEnd :%v state:%v", UUID, currentOut.Target.Status().String()) + <-ticker.C + } +} diff --git a/component/supervisor/readme.md b/component/supervisor/readme.md new file mode 100644 index 000000000..840a58ac3 --- /dev/null +++ b/component/supervisor/readme.md @@ -0,0 +1,2 @@ +## 资源守护 +用来守护监控系统内各种资源的存活状态。因为之前的老版本依赖Http组件,存在高耦合情况,所以需要单独优化,现阶段暂未启用,等以后的版本逐步优化. \ No newline at end of file From 6e4718245e4e90d710c4d906bdb15d9a051a9b5a Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 5 Dec 2023 23:38:46 +0800 Subject: [PATCH 093/138] refactor: move api server to component --- .gitignore | 10 +++------- component/cron_task/cron_manager.go | 2 +- component/cron_task/process_manager.go | 2 +- .../rulex_api_server/apis/aibase_api.go | 2 +- .../rulex_api_server/apis/appstack_api.go | 6 +++--- .../rulex_api_server/apis/crontask_api.go | 6 +++--- .../apis/crontaskresult_api.go | 4 ++-- .../rulex_api_server/apis/datacenter_api.go | 2 +- .../rulex_api_server/apis/dataschema_api.go | 6 +++--- .../rulex_api_server/apis/device_api.go | 8 ++++---- .../rulex_api_server/apis/group_api.go | 6 +++--- .../rulex_api_server/apis/hw_port_api.go | 6 +++--- .../rulex_api_server/apis/inend_api.go | 8 ++++---- .../apis/internal_notify_api.go | 6 +++--- .../rulex_api_server/apis/outend_api.go | 8 ++++---- .../rulex_api_server/apis/plugin_api.go | 2 +- .../rulex_api_server/apis/protocolapp_api.go | 0 .../apis/rhinoh3_firmware_api.go | 2 +- .../apis/rhinoh3_iproute_api.go | 6 +++--- .../rulex_api_server/apis/rhinopi_4g_api.go | 2 +- .../rulex_api_server/apis/rhinopi_wifi_api.go | 2 +- .../rulex_api_server/apis/rtsp_stream_api.go | 0 .../rulex_api_server/apis/rule_api.go | 8 ++++---- .../rulex_api_server/apis/site_config_api.go | 6 +++--- .../apis/sysconfig_backup_api.go | 2 +- .../rulex_api_server/apis/system_api.go | 4 ++-- .../apis/system_config_api_linux.go | 6 +++--- .../apis/system_firmware_api.go | 2 +- .../apis/system_settings_linux.go | 2 +- .../apis/system_settings_windows.go | 2 +- .../rulex_api_server/apis/trailer_api.go | 6 +++--- .../rulex_api_server/apis/user_api.go | 6 +++--- .../apis/user_lua_template_api.go | 6 +++--- .../apis/vendor_security_api.go | 2 +- .../rulex_api_server/apis/visual_api.go | 6 +++--- .../rulex_api_server/common/response.go | 0 .../rulex_api_server/dto/crontask_dto.go | 0 .../rulex_api_server/dto/data_schema.go | 0 .../rulex_api_server/dto/etcnet_config.go | 0 .../rulex_api_server/dto/netplan_config.go | 0 .../rulex_api_server/http_api_server.go | 8 ++++---- .../rulex_api_server/model/data_schema.go | 0 .../rulex_api_server/model/hw_interface.go | 0 .../rulex_api_server/model/internal_notify.go | 0 .../rulex_api_server/model/iproute_config.go | 0 .../rulex_api_server/model/model.go | 0 .../rulex_api_server/model/site_config.go | 0 .../rulex_api_server/model/syslogo.go | 0 .../model/user_lua_template.go | 0 .../rulex_api_server/readme.md | 0 .../rulex_api_server/server/apiserver.go | 6 +++--- .../rulex_api_server/server/auth.go | 0 .../rulex_api_server/server/cros.go | 0 .../rulex_api_server/server/hello_api.go | 0 .../rulex_api_server/server/rate_limit.go | 0 .../rulex_api_server/server/res_loader.go | 2 +- .../rulex_api_server/server/res_supervisor.go | 0 .../rulex_api_server/server/staticfs.go | 0 .../service/crontask_service.go | 4 ++-- .../rulex_api_server/service/dao.go | 2 +- .../service/data_schema_service.go | 2 +- .../service/database_manage_service.go | 0 .../rulex_api_server/service/group_service.go | 2 +- .../service/hw_intrerface_service.go | 2 +- .../service/internal_notify_service.go | 2 +- .../service/linux_network_config_service.go | 2 +- .../service/linux_wlan_config_service.go | 2 +- .../rulex_api_server/service/linuxamixer.md | 0 .../rulex_api_server/service/linuxnetcfg.md | 0 .../rulex_api_server/service/linuxtimecfg.md | 0 .../service/memory_usage_linux.go | 0 .../service/memory_usage_windows.go | 0 .../rulex_api_server/service/page_service.go | 2 +- .../rhinoh3_ubuntu18_iproute_service.go | 2 +- .../service/site_config_service.go | 2 +- .../service/user_lua_template_service.go | 2 +- .../service/visual_screen_service.go | 2 +- .../rulex_api_server/service/windows.md | 0 .../service/windows_eth_config.go | 0 .../rulex_api_server/structure.png | Bin engine/runner.go | 2 +- glogger/ws_logger.md | 4 ++-- plugin/rulex_api_server/server/www/index.html | 18 ------------------ test/appstack_httpapi_test.go | 2 +- test/binary_lua_test.go | 2 +- test/custom_tcp_server_test.go | 2 +- test/device_485ther_gw_test.go | 2 +- test/device_custom_protocol_device_test.go | 2 +- test/device_daccall_test.go | 2 +- test/device_g776dtu_test.go | 2 +- test/device_generic_ais_rxtx_device_test.go | 2 +- test/device_generic_camera_stream_test.go | 2 +- test/device_generic_modbus_device_test.go | 2 +- test/device_generic_opcua_device_test.go | 2 +- test/device_generic_snmp_device_test.go | 2 +- test/device_generic_uart_device_test.go | 2 +- test/device_gos7_plc_data_parse_test.go | 2 +- test/device_icmp_sender_test.go | 2 +- test/device_modbus_wite_with_app_test.go | 2 +- test/device_th_485_sensor_data_parse_test.go | 2 +- test/device_tss200_test.go | 2 +- test/device_yk8_with_rulex_test.go | 2 +- test/fully_test.go | 2 +- test/http_api_device_snmp_curd_test.go | 2 +- test/init_data_test.go | 6 +++--- test/jq_test.go | 2 +- test/modbus_parse_test.go | 2 +- test/rpc_codec_test.go | 2 +- test/rule_id_get_test.go | 2 +- test/rulex_snapshot_dump_test.go | 2 +- test/source_http_source_test.go | 2 +- test/suorce_txiothub_test.go | 2 +- test/target_data_to_mongodb_test.go | 2 +- test/target_data_tohttp_test.go | 4 ++-- test/target_data_toudp_test.go | 4 ++-- test/target_tdengine_test.go | 2 +- test/test_utils.go | 2 +- test/trailer_test.go | 2 +- typex/version.go | 4 ++-- 119 files changed, 141 insertions(+), 163 deletions(-) rename {plugin => component}/rulex_api_server/apis/aibase_api.go (94%) rename {plugin => component}/rulex_api_server/apis/appstack_api.go (97%) rename {plugin => component}/rulex_api_server/apis/crontask_api.go (95%) rename {plugin => component}/rulex_api_server/apis/crontaskresult_api.go (90%) rename {plugin => component}/rulex_api_server/apis/datacenter_api.go (97%) rename {plugin => component}/rulex_api_server/apis/dataschema_api.go (95%) rename {plugin => component}/rulex_api_server/apis/device_api.go (97%) rename {plugin => component}/rulex_api_server/apis/group_api.go (96%) rename {plugin => component}/rulex_api_server/apis/hw_port_api.go (95%) rename {plugin => component}/rulex_api_server/apis/inend_api.go (95%) rename {plugin => component}/rulex_api_server/apis/internal_notify_api.go (94%) rename {plugin => component}/rulex_api_server/apis/outend_api.go (95%) rename {plugin => component}/rulex_api_server/apis/plugin_api.go (94%) rename {plugin => component}/rulex_api_server/apis/protocolapp_api.go (100%) rename {plugin => component}/rulex_api_server/apis/rhinoh3_firmware_api.go (95%) rename {plugin => component}/rulex_api_server/apis/rhinoh3_iproute_api.go (96%) rename {plugin => component}/rulex_api_server/apis/rhinopi_4g_api.go (98%) rename {plugin => component}/rulex_api_server/apis/rhinopi_wifi_api.go (93%) rename {plugin => component}/rulex_api_server/apis/rtsp_stream_api.go (100%) rename {plugin => component}/rulex_api_server/apis/rule_api.go (98%) rename {plugin => component}/rulex_api_server/apis/site_config_api.go (89%) rename {plugin => component}/rulex_api_server/apis/sysconfig_backup_api.go (96%) rename {plugin => component}/rulex_api_server/apis/system_api.go (98%) rename {plugin => component}/rulex_api_server/apis/system_config_api_linux.go (98%) rename {plugin => component}/rulex_api_server/apis/system_firmware_api.go (98%) rename {plugin => component}/rulex_api_server/apis/system_settings_linux.go (97%) rename {plugin => component}/rulex_api_server/apis/system_settings_windows.go (92%) rename {plugin => component}/rulex_api_server/apis/trailer_api.go (98%) rename {plugin => component}/rulex_api_server/apis/user_api.go (97%) rename {plugin => component}/rulex_api_server/apis/user_lua_template_api.go (96%) rename {plugin => component}/rulex_api_server/apis/vendor_security_api.go (95%) rename {plugin => component}/rulex_api_server/apis/visual_api.go (96%) rename {plugin => component}/rulex_api_server/common/response.go (100%) rename {plugin => component}/rulex_api_server/dto/crontask_dto.go (100%) rename {plugin => component}/rulex_api_server/dto/data_schema.go (100%) rename {plugin => component}/rulex_api_server/dto/etcnet_config.go (100%) rename {plugin => component}/rulex_api_server/dto/netplan_config.go (100%) rename {plugin => component}/rulex_api_server/http_api_server.go (98%) rename {plugin => component}/rulex_api_server/model/data_schema.go (100%) rename {plugin => component}/rulex_api_server/model/hw_interface.go (100%) rename {plugin => component}/rulex_api_server/model/internal_notify.go (100%) rename {plugin => component}/rulex_api_server/model/iproute_config.go (100%) rename {plugin => component}/rulex_api_server/model/model.go (100%) rename {plugin => component}/rulex_api_server/model/site_config.go (100%) rename {plugin => component}/rulex_api_server/model/syslogo.go (100%) rename {plugin => component}/rulex_api_server/model/user_lua_template.go (100%) rename {plugin => component}/rulex_api_server/readme.md (100%) rename {plugin => component}/rulex_api_server/server/apiserver.go (96%) rename {plugin => component}/rulex_api_server/server/auth.go (100%) rename {plugin => component}/rulex_api_server/server/cros.go (100%) rename {plugin => component}/rulex_api_server/server/hello_api.go (100%) rename {plugin => component}/rulex_api_server/server/rate_limit.go (100%) rename {plugin => component}/rulex_api_server/server/res_loader.go (98%) rename {plugin => component}/rulex_api_server/server/res_supervisor.go (100%) rename {plugin => component}/rulex_api_server/server/staticfs.go (100%) rename {plugin => component}/rulex_api_server/service/crontask_service.go (94%) rename {plugin => component}/rulex_api_server/service/dao.go (99%) rename {plugin => component}/rulex_api_server/service/data_schema_service.go (96%) rename {plugin => component}/rulex_api_server/service/database_manage_service.go (100%) rename {plugin => component}/rulex_api_server/service/group_service.go (98%) rename {plugin => component}/rulex_api_server/service/hw_intrerface_service.go (98%) rename {plugin => component}/rulex_api_server/service/internal_notify_service.go (96%) rename {plugin => component}/rulex_api_server/service/linux_network_config_service.go (98%) rename {plugin => component}/rulex_api_server/service/linux_wlan_config_service.go (96%) rename {plugin => component}/rulex_api_server/service/linuxamixer.md (100%) rename {plugin => component}/rulex_api_server/service/linuxnetcfg.md (100%) rename {plugin => component}/rulex_api_server/service/linuxtimecfg.md (100%) rename {plugin => component}/rulex_api_server/service/memory_usage_linux.go (100%) rename {plugin => component}/rulex_api_server/service/memory_usage_windows.go (100%) rename {plugin => component}/rulex_api_server/service/page_service.go (93%) rename {plugin => component}/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go (98%) rename {plugin => component}/rulex_api_server/service/site_config_service.go (95%) rename {plugin => component}/rulex_api_server/service/user_lua_template_service.go (97%) rename {plugin => component}/rulex_api_server/service/visual_screen_service.go (94%) rename {plugin => component}/rulex_api_server/service/windows.md (100%) rename {plugin => component}/rulex_api_server/service/windows_eth_config.go (100%) rename {plugin => component}/rulex_api_server/structure.png (100%) delete mode 100644 plugin/rulex_api_server/server/www/index.html diff --git a/.gitignore b/.gitignore index 15a2f6603..482bcfd22 100644 --- a/.gitignore +++ b/.gitignore @@ -17,14 +17,10 @@ profile* _release* _build* lua-log* -*.txt -*.txt.gz -plugin/rulex_api_server/www/* -plugin/rulex_api_server/server/www/* +*.txt* dist/ apps/*.lua -plugin/rulex_api_server/www/index.html -plugin/rulex_api_server/server/www/index.html test/script/_temp/* upload/* -go.sum \ No newline at end of file +go.sum +component/rulex_api_server/server/www/* diff --git a/component/cron_task/cron_manager.go b/component/cron_task/cron_manager.go index 4fa653fcc..02b0ea089 100644 --- a/component/cron_task/cron_manager.go +++ b/component/cron_task/cron_manager.go @@ -10,8 +10,8 @@ import ( "time" "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "github.com/robfig/cron/v3" ) diff --git a/component/cron_task/process_manager.go b/component/cron_task/process_manager.go index c70e5ebb2..083a0484f 100644 --- a/component/cron_task/process_manager.go +++ b/component/cron_task/process_manager.go @@ -8,8 +8,8 @@ import ( "os/exec" "sync" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) // ProcessManager diff --git a/plugin/rulex_api_server/apis/aibase_api.go b/component/rulex_api_server/apis/aibase_api.go similarity index 94% rename from plugin/rulex_api_server/apis/aibase_api.go rename to component/rulex_api_server/apis/aibase_api.go index 181e27bff..94e8f1497 100644 --- a/plugin/rulex_api_server/apis/aibase_api.go +++ b/component/rulex_api_server/apis/aibase_api.go @@ -3,7 +3,7 @@ package apis import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/aibase" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/appstack_api.go b/component/rulex_api_server/apis/appstack_api.go similarity index 97% rename from plugin/rulex_api_server/apis/appstack_api.go rename to component/rulex_api_server/apis/appstack_api.go index 6461d55fe..b52029642 100644 --- a/plugin/rulex_api_server/apis/appstack_api.go +++ b/component/rulex_api_server/apis/appstack_api.go @@ -3,9 +3,9 @@ package apis import ( "fmt" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/appstack" diff --git a/plugin/rulex_api_server/apis/crontask_api.go b/component/rulex_api_server/apis/crontask_api.go similarity index 95% rename from plugin/rulex_api_server/apis/crontask_api.go rename to component/rulex_api_server/apis/crontask_api.go index 8beee66fc..db5f599d3 100644 --- a/plugin/rulex_api_server/apis/crontask_api.go +++ b/component/rulex_api_server/apis/crontask_api.go @@ -6,9 +6,9 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/cron_task" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/dto" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + "github.com/hootrhino/rulex/component/rulex_api_server/dto" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/crontaskresult_api.go b/component/rulex_api_server/apis/crontaskresult_api.go similarity index 90% rename from plugin/rulex_api_server/apis/crontaskresult_api.go rename to component/rulex_api_server/apis/crontaskresult_api.go index 1d443db41..5e1610498 100644 --- a/plugin/rulex_api_server/apis/crontaskresult_api.go +++ b/component/rulex_api_server/apis/crontaskresult_api.go @@ -3,8 +3,8 @@ package apis import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/datacenter_api.go b/component/rulex_api_server/apis/datacenter_api.go similarity index 97% rename from plugin/rulex_api_server/apis/datacenter_api.go rename to component/rulex_api_server/apis/datacenter_api.go index 49dde5498..5c27544c6 100644 --- a/plugin/rulex_api_server/apis/datacenter_api.go +++ b/component/rulex_api_server/apis/datacenter_api.go @@ -18,7 +18,7 @@ package apis import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/datacenter" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/dataschema_api.go b/component/rulex_api_server/apis/dataschema_api.go similarity index 95% rename from plugin/rulex_api_server/apis/dataschema_api.go rename to component/rulex_api_server/apis/dataschema_api.go index 000e4ca46..bfe820107 100644 --- a/plugin/rulex_api_server/apis/dataschema_api.go +++ b/component/rulex_api_server/apis/dataschema_api.go @@ -4,10 +4,10 @@ import ( "encoding/json" "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/core" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/apis/device_api.go b/component/rulex_api_server/apis/device_api.go similarity index 97% rename from plugin/rulex_api_server/apis/device_api.go rename to component/rulex_api_server/apis/device_api.go index 907c2bd9f..fd1588fca 100644 --- a/plugin/rulex_api_server/apis/device_api.go +++ b/component/rulex_api_server/apis/device_api.go @@ -6,10 +6,10 @@ import ( "io" "strconv" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/server" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/server" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/xuri/excelize/v2" diff --git a/plugin/rulex_api_server/apis/group_api.go b/component/rulex_api_server/apis/group_api.go similarity index 96% rename from plugin/rulex_api_server/apis/group_api.go rename to component/rulex_api_server/apis/group_api.go index e8a44d7e9..364383d1a 100644 --- a/plugin/rulex_api_server/apis/group_api.go +++ b/component/rulex_api_server/apis/group_api.go @@ -4,9 +4,9 @@ import ( "fmt" "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/apis/hw_port_api.go b/component/rulex_api_server/apis/hw_port_api.go similarity index 95% rename from plugin/rulex_api_server/apis/hw_port_api.go rename to component/rulex_api_server/apis/hw_port_api.go index 6b6f29921..888680db2 100644 --- a/plugin/rulex_api_server/apis/hw_port_api.go +++ b/component/rulex_api_server/apis/hw_port_api.go @@ -20,9 +20,9 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/hwportmanager" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/apis/inend_api.go b/component/rulex_api_server/apis/inend_api.go similarity index 95% rename from plugin/rulex_api_server/apis/inend_api.go rename to component/rulex_api_server/apis/inend_api.go index 97549175c..20139b800 100644 --- a/plugin/rulex_api_server/apis/inend_api.go +++ b/component/rulex_api_server/apis/inend_api.go @@ -4,10 +4,10 @@ import ( "fmt" "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/server" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/server" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "gopkg.in/square/go-jose.v2/json" diff --git a/plugin/rulex_api_server/apis/internal_notify_api.go b/component/rulex_api_server/apis/internal_notify_api.go similarity index 94% rename from plugin/rulex_api_server/apis/internal_notify_api.go rename to component/rulex_api_server/apis/internal_notify_api.go index 8889cdd41..b361c696b 100644 --- a/plugin/rulex_api_server/apis/internal_notify_api.go +++ b/component/rulex_api_server/apis/internal_notify_api.go @@ -20,9 +20,9 @@ import ( "time" "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/apis/outend_api.go b/component/rulex_api_server/apis/outend_api.go similarity index 95% rename from plugin/rulex_api_server/apis/outend_api.go rename to component/rulex_api_server/apis/outend_api.go index 4ec5a7a40..38eb8a1cb 100644 --- a/plugin/rulex_api_server/apis/outend_api.go +++ b/component/rulex_api_server/apis/outend_api.go @@ -1,10 +1,10 @@ package apis import ( - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/server" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/server" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" diff --git a/plugin/rulex_api_server/apis/plugin_api.go b/component/rulex_api_server/apis/plugin_api.go similarity index 94% rename from plugin/rulex_api_server/apis/plugin_api.go rename to component/rulex_api_server/apis/plugin_api.go index 0479a749c..b2b08c05e 100644 --- a/plugin/rulex_api_server/apis/plugin_api.go +++ b/component/rulex_api_server/apis/plugin_api.go @@ -3,7 +3,7 @@ package apis import ( "fmt" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/typex" "github.com/gin-gonic/gin" diff --git a/plugin/rulex_api_server/apis/protocolapp_api.go b/component/rulex_api_server/apis/protocolapp_api.go similarity index 100% rename from plugin/rulex_api_server/apis/protocolapp_api.go rename to component/rulex_api_server/apis/protocolapp_api.go diff --git a/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go b/component/rulex_api_server/apis/rhinoh3_firmware_api.go similarity index 95% rename from plugin/rulex_api_server/apis/rhinoh3_firmware_api.go rename to component/rulex_api_server/apis/rhinoh3_firmware_api.go index afd985312..b33d8e01e 100644 --- a/plugin/rulex_api_server/apis/rhinoh3_firmware_api.go +++ b/component/rulex_api_server/apis/rhinoh3_firmware_api.go @@ -20,8 +20,8 @@ import ( "os" "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/rhinoh3_iproute_api.go b/component/rulex_api_server/apis/rhinoh3_iproute_api.go similarity index 96% rename from plugin/rulex_api_server/apis/rhinoh3_iproute_api.go rename to component/rulex_api_server/apis/rhinoh3_iproute_api.go index fedcac6f6..834441e55 100644 --- a/plugin/rulex_api_server/apis/rhinoh3_iproute_api.go +++ b/component/rulex_api_server/apis/rhinoh3_iproute_api.go @@ -19,10 +19,10 @@ import ( "fmt" "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/apis/rhinopi_4g_api.go b/component/rulex_api_server/apis/rhinopi_4g_api.go similarity index 98% rename from plugin/rulex_api_server/apis/rhinopi_4g_api.go rename to component/rulex_api_server/apis/rhinopi_4g_api.go index 233eab3ca..a788b4368 100644 --- a/plugin/rulex_api_server/apis/rhinopi_4g_api.go +++ b/component/rulex_api_server/apis/rhinopi_4g_api.go @@ -20,7 +20,7 @@ import ( "github.com/gin-gonic/gin" archsupport "github.com/hootrhino/rulex/bspsupport" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/rhinopi_wifi_api.go b/component/rulex_api_server/apis/rhinopi_wifi_api.go similarity index 93% rename from plugin/rulex_api_server/apis/rhinopi_wifi_api.go rename to component/rulex_api_server/apis/rhinopi_wifi_api.go index 99a03eb78..164f626a7 100644 --- a/plugin/rulex_api_server/apis/rhinopi_wifi_api.go +++ b/component/rulex_api_server/apis/rhinopi_wifi_api.go @@ -17,8 +17,8 @@ package apis import ( "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/rtsp_stream_api.go b/component/rulex_api_server/apis/rtsp_stream_api.go similarity index 100% rename from plugin/rulex_api_server/apis/rtsp_stream_api.go rename to component/rulex_api_server/apis/rtsp_stream_api.go diff --git a/plugin/rulex_api_server/apis/rule_api.go b/component/rulex_api_server/apis/rule_api.go similarity index 98% rename from plugin/rulex_api_server/apis/rule_api.go rename to component/rulex_api_server/apis/rule_api.go index 389d2c188..8c06a3a7e 100644 --- a/plugin/rulex_api_server/apis/rule_api.go +++ b/component/rulex_api_server/apis/rule_api.go @@ -4,11 +4,11 @@ import ( "fmt" "github.com/hootrhino/rulex/component/interqueue" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/server" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/glogger" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/server" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/sirupsen/logrus" "github.com/hootrhino/rulex/core" diff --git a/plugin/rulex_api_server/apis/site_config_api.go b/component/rulex_api_server/apis/site_config_api.go similarity index 89% rename from plugin/rulex_api_server/apis/site_config_api.go rename to component/rulex_api_server/apis/site_config_api.go index fc55d5f1c..b45793ee9 100644 --- a/plugin/rulex_api_server/apis/site_config_api.go +++ b/component/rulex_api_server/apis/site_config_api.go @@ -17,9 +17,9 @@ package apis import ( "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/sysconfig_backup_api.go b/component/rulex_api_server/apis/sysconfig_backup_api.go similarity index 96% rename from plugin/rulex_api_server/apis/sysconfig_backup_api.go rename to component/rulex_api_server/apis/sysconfig_backup_api.go index e96f31ada..6ab35a3b8 100644 --- a/plugin/rulex_api_server/apis/sysconfig_backup_api.go +++ b/component/rulex_api_server/apis/sysconfig_backup_api.go @@ -9,8 +9,8 @@ import ( "time" "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/system_api.go b/component/rulex_api_server/apis/system_api.go similarity index 98% rename from plugin/rulex_api_server/apis/system_api.go rename to component/rulex_api_server/apis/system_api.go index 82d50047f..ef9163e7c 100644 --- a/plugin/rulex_api_server/apis/system_api.go +++ b/component/rulex_api_server/apis/system_api.go @@ -11,10 +11,10 @@ import ( "github.com/hootrhino/rulex/component/appstack" "github.com/hootrhino/rulex/component/intermetric" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/utils" "github.com/hootrhino/rulex/device" diff --git a/plugin/rulex_api_server/apis/system_config_api_linux.go b/component/rulex_api_server/apis/system_config_api_linux.go similarity index 98% rename from plugin/rulex_api_server/apis/system_config_api_linux.go rename to component/rulex_api_server/apis/system_config_api_linux.go index dca7bf3c9..5ac5fc658 100644 --- a/plugin/rulex_api_server/apis/system_config_api_linux.go +++ b/component/rulex_api_server/apis/system_config_api_linux.go @@ -11,11 +11,11 @@ import ( "strings" "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/apis/system_firmware_api.go b/component/rulex_api_server/apis/system_firmware_api.go similarity index 98% rename from plugin/rulex_api_server/apis/system_firmware_api.go rename to component/rulex_api_server/apis/system_firmware_api.go index f6ad10d04..96423a2fd 100644 --- a/plugin/rulex_api_server/apis/system_firmware_api.go +++ b/component/rulex_api_server/apis/system_firmware_api.go @@ -24,10 +24,10 @@ import ( "path/filepath" "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/ossupport" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" ) diff --git a/plugin/rulex_api_server/apis/system_settings_linux.go b/component/rulex_api_server/apis/system_settings_linux.go similarity index 97% rename from plugin/rulex_api_server/apis/system_settings_linux.go rename to component/rulex_api_server/apis/system_settings_linux.go index f184be065..641592afa 100644 --- a/plugin/rulex_api_server/apis/system_settings_linux.go +++ b/component/rulex_api_server/apis/system_settings_linux.go @@ -1,6 +1,6 @@ package apis -import "github.com/hootrhino/rulex/plugin/rulex_api_server/server" +import "github.com/hootrhino/rulex/component/rulex_api_server/server" // Copyright (C) 2023 wwhai // diff --git a/plugin/rulex_api_server/apis/system_settings_windows.go b/component/rulex_api_server/apis/system_settings_windows.go similarity index 92% rename from plugin/rulex_api_server/apis/system_settings_windows.go rename to component/rulex_api_server/apis/system_settings_windows.go index 6652165f1..bd4fafbfe 100644 --- a/plugin/rulex_api_server/apis/system_settings_windows.go +++ b/component/rulex_api_server/apis/system_settings_windows.go @@ -1,6 +1,6 @@ package apis -import "github.com/hootrhino/rulex/plugin/rulex_api_server/server" +import "github.com/hootrhino/rulex/component/rulex_api_server/server" // Copyright (C) 2023 wwhai // diff --git a/plugin/rulex_api_server/apis/trailer_api.go b/component/rulex_api_server/apis/trailer_api.go similarity index 98% rename from plugin/rulex_api_server/apis/trailer_api.go rename to component/rulex_api_server/apis/trailer_api.go index 8dba8e160..2ff640f7d 100644 --- a/plugin/rulex_api_server/apis/trailer_api.go +++ b/component/rulex_api_server/apis/trailer_api.go @@ -10,11 +10,11 @@ import ( "runtime" "time" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/glogger" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "google.golang.org/grpc" diff --git a/plugin/rulex_api_server/apis/user_api.go b/component/rulex_api_server/apis/user_api.go similarity index 97% rename from plugin/rulex_api_server/apis/user_api.go rename to component/rulex_api_server/apis/user_api.go index a40130ea4..94e2de056 100644 --- a/plugin/rulex_api_server/apis/user_api.go +++ b/component/rulex_api_server/apis/user_api.go @@ -12,9 +12,9 @@ import ( "time" "unicode/utf8" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/dgrijalva/jwt-go" diff --git a/plugin/rulex_api_server/apis/user_lua_template_api.go b/component/rulex_api_server/apis/user_lua_template_api.go similarity index 96% rename from plugin/rulex_api_server/apis/user_lua_template_api.go rename to component/rulex_api_server/apis/user_lua_template_api.go index 509e4c2ef..8c51638fb 100644 --- a/plugin/rulex_api_server/apis/user_lua_template_api.go +++ b/component/rulex_api_server/apis/user_lua_template_api.go @@ -2,9 +2,9 @@ package apis import ( "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/apis/vendor_security_api.go b/component/rulex_api_server/apis/vendor_security_api.go similarity index 95% rename from plugin/rulex_api_server/apis/vendor_security_api.go rename to component/rulex_api_server/apis/vendor_security_api.go index 606e3cef5..5585d5c11 100644 --- a/plugin/rulex_api_server/apis/vendor_security_api.go +++ b/component/rulex_api_server/apis/vendor_security_api.go @@ -20,8 +20,8 @@ import ( "strings" "github.com/gin-gonic/gin" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/core" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" "github.com/hootrhino/rulex/typex" "gopkg.in/ini.v1" ) diff --git a/plugin/rulex_api_server/apis/visual_api.go b/component/rulex_api_server/apis/visual_api.go similarity index 96% rename from plugin/rulex_api_server/apis/visual_api.go rename to component/rulex_api_server/apis/visual_api.go index 1b95cdf30..0bcc64af5 100644 --- a/plugin/rulex_api_server/apis/visual_api.go +++ b/component/rulex_api_server/apis/visual_api.go @@ -9,9 +9,9 @@ import ( "time" "github.com/gin-gonic/gin" - common "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/common/response.go b/component/rulex_api_server/common/response.go similarity index 100% rename from plugin/rulex_api_server/common/response.go rename to component/rulex_api_server/common/response.go diff --git a/plugin/rulex_api_server/dto/crontask_dto.go b/component/rulex_api_server/dto/crontask_dto.go similarity index 100% rename from plugin/rulex_api_server/dto/crontask_dto.go rename to component/rulex_api_server/dto/crontask_dto.go diff --git a/plugin/rulex_api_server/dto/data_schema.go b/component/rulex_api_server/dto/data_schema.go similarity index 100% rename from plugin/rulex_api_server/dto/data_schema.go rename to component/rulex_api_server/dto/data_schema.go diff --git a/plugin/rulex_api_server/dto/etcnet_config.go b/component/rulex_api_server/dto/etcnet_config.go similarity index 100% rename from plugin/rulex_api_server/dto/etcnet_config.go rename to component/rulex_api_server/dto/etcnet_config.go diff --git a/plugin/rulex_api_server/dto/netplan_config.go b/component/rulex_api_server/dto/netplan_config.go similarity index 100% rename from plugin/rulex_api_server/dto/netplan_config.go rename to component/rulex_api_server/dto/netplan_config.go diff --git a/plugin/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go similarity index 98% rename from plugin/rulex_api_server/http_api_server.go rename to component/rulex_api_server/http_api_server.go index 6b764e18e..85fd195b6 100644 --- a/plugin/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -8,12 +8,12 @@ import ( "github.com/hootrhino/rulex/component/appstack" "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/rulex_api_server/apis" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/server" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/core" - "github.com/hootrhino/rulex/plugin/rulex_api_server/apis" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/server" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" diff --git a/plugin/rulex_api_server/model/data_schema.go b/component/rulex_api_server/model/data_schema.go similarity index 100% rename from plugin/rulex_api_server/model/data_schema.go rename to component/rulex_api_server/model/data_schema.go diff --git a/plugin/rulex_api_server/model/hw_interface.go b/component/rulex_api_server/model/hw_interface.go similarity index 100% rename from plugin/rulex_api_server/model/hw_interface.go rename to component/rulex_api_server/model/hw_interface.go diff --git a/plugin/rulex_api_server/model/internal_notify.go b/component/rulex_api_server/model/internal_notify.go similarity index 100% rename from plugin/rulex_api_server/model/internal_notify.go rename to component/rulex_api_server/model/internal_notify.go diff --git a/plugin/rulex_api_server/model/iproute_config.go b/component/rulex_api_server/model/iproute_config.go similarity index 100% rename from plugin/rulex_api_server/model/iproute_config.go rename to component/rulex_api_server/model/iproute_config.go diff --git a/plugin/rulex_api_server/model/model.go b/component/rulex_api_server/model/model.go similarity index 100% rename from plugin/rulex_api_server/model/model.go rename to component/rulex_api_server/model/model.go diff --git a/plugin/rulex_api_server/model/site_config.go b/component/rulex_api_server/model/site_config.go similarity index 100% rename from plugin/rulex_api_server/model/site_config.go rename to component/rulex_api_server/model/site_config.go diff --git a/plugin/rulex_api_server/model/syslogo.go b/component/rulex_api_server/model/syslogo.go similarity index 100% rename from plugin/rulex_api_server/model/syslogo.go rename to component/rulex_api_server/model/syslogo.go diff --git a/plugin/rulex_api_server/model/user_lua_template.go b/component/rulex_api_server/model/user_lua_template.go similarity index 100% rename from plugin/rulex_api_server/model/user_lua_template.go rename to component/rulex_api_server/model/user_lua_template.go diff --git a/plugin/rulex_api_server/readme.md b/component/rulex_api_server/readme.md similarity index 100% rename from plugin/rulex_api_server/readme.md rename to component/rulex_api_server/readme.md diff --git a/plugin/rulex_api_server/server/apiserver.go b/component/rulex_api_server/server/apiserver.go similarity index 96% rename from plugin/rulex_api_server/server/apiserver.go rename to component/rulex_api_server/server/apiserver.go index 72e3c701b..09b756702 100644 --- a/plugin/rulex_api_server/server/apiserver.go +++ b/component/rulex_api_server/server/apiserver.go @@ -11,12 +11,12 @@ import ( "github.com/gin-contrib/static" "github.com/gin-gonic/gin" + response "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/device" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/ossupport" - response "github.com/hootrhino/rulex/plugin/rulex_api_server/common" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/source" "github.com/hootrhino/rulex/target" "github.com/hootrhino/rulex/typex" diff --git a/plugin/rulex_api_server/server/auth.go b/component/rulex_api_server/server/auth.go similarity index 100% rename from plugin/rulex_api_server/server/auth.go rename to component/rulex_api_server/server/auth.go diff --git a/plugin/rulex_api_server/server/cros.go b/component/rulex_api_server/server/cros.go similarity index 100% rename from plugin/rulex_api_server/server/cros.go rename to component/rulex_api_server/server/cros.go diff --git a/plugin/rulex_api_server/server/hello_api.go b/component/rulex_api_server/server/hello_api.go similarity index 100% rename from plugin/rulex_api_server/server/hello_api.go rename to component/rulex_api_server/server/hello_api.go diff --git a/plugin/rulex_api_server/server/rate_limit.go b/component/rulex_api_server/server/rate_limit.go similarity index 100% rename from plugin/rulex_api_server/server/rate_limit.go rename to component/rulex_api_server/server/rate_limit.go diff --git a/plugin/rulex_api_server/server/res_loader.go b/component/rulex_api_server/server/res_loader.go similarity index 98% rename from plugin/rulex_api_server/server/res_loader.go rename to component/rulex_api_server/server/res_loader.go index 6c75b9e40..28cbf162d 100644 --- a/plugin/rulex_api_server/server/res_loader.go +++ b/component/rulex_api_server/server/res_loader.go @@ -3,8 +3,8 @@ package server import ( "errors" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "gopkg.in/square/go-jose.v2/json" ) diff --git a/plugin/rulex_api_server/server/res_supervisor.go b/component/rulex_api_server/server/res_supervisor.go similarity index 100% rename from plugin/rulex_api_server/server/res_supervisor.go rename to component/rulex_api_server/server/res_supervisor.go diff --git a/plugin/rulex_api_server/server/staticfs.go b/component/rulex_api_server/server/staticfs.go similarity index 100% rename from plugin/rulex_api_server/server/staticfs.go rename to component/rulex_api_server/server/staticfs.go diff --git a/plugin/rulex_api_server/service/crontask_service.go b/component/rulex_api_server/service/crontask_service.go similarity index 94% rename from plugin/rulex_api_server/service/crontask_service.go rename to component/rulex_api_server/service/crontask_service.go index 2cf263b10..2bee589c4 100644 --- a/plugin/rulex_api_server/service/crontask_service.go +++ b/component/rulex_api_server/service/crontask_service.go @@ -6,8 +6,8 @@ import ( "github.com/hootrhino/rulex/component/cron_task" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/dto" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/dto" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/utils" ) diff --git a/plugin/rulex_api_server/service/dao.go b/component/rulex_api_server/service/dao.go similarity index 99% rename from plugin/rulex_api_server/service/dao.go rename to component/rulex_api_server/service/dao.go index 101bef191..f9beeccdc 100644 --- a/plugin/rulex_api_server/service/dao.go +++ b/component/rulex_api_server/service/dao.go @@ -2,7 +2,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "gorm.io/gorm" ) diff --git a/plugin/rulex_api_server/service/data_schema_service.go b/component/rulex_api_server/service/data_schema_service.go similarity index 96% rename from plugin/rulex_api_server/service/data_schema_service.go rename to component/rulex_api_server/service/data_schema_service.go index 1cd3d956f..3127441b0 100644 --- a/plugin/rulex_api_server/service/data_schema_service.go +++ b/component/rulex_api_server/service/data_schema_service.go @@ -17,7 +17,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) // 获取DataSchema列表 diff --git a/plugin/rulex_api_server/service/database_manage_service.go b/component/rulex_api_server/service/database_manage_service.go similarity index 100% rename from plugin/rulex_api_server/service/database_manage_service.go rename to component/rulex_api_server/service/database_manage_service.go diff --git a/plugin/rulex_api_server/service/group_service.go b/component/rulex_api_server/service/group_service.go similarity index 98% rename from plugin/rulex_api_server/service/group_service.go rename to component/rulex_api_server/service/group_service.go index cce4bc8db..5677f7be2 100644 --- a/plugin/rulex_api_server/service/group_service.go +++ b/component/rulex_api_server/service/group_service.go @@ -17,7 +17,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) // 获取GenericGroup列表 diff --git a/plugin/rulex_api_server/service/hw_intrerface_service.go b/component/rulex_api_server/service/hw_intrerface_service.go similarity index 98% rename from plugin/rulex_api_server/service/hw_intrerface_service.go rename to component/rulex_api_server/service/hw_intrerface_service.go index 2b6293da8..6ca3e318f 100644 --- a/plugin/rulex_api_server/service/hw_intrerface_service.go +++ b/component/rulex_api_server/service/hw_intrerface_service.go @@ -20,8 +20,8 @@ import ( "runtime" "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/ossupport" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "go.bug.st/serial" diff --git a/plugin/rulex_api_server/service/internal_notify_service.go b/component/rulex_api_server/service/internal_notify_service.go similarity index 96% rename from plugin/rulex_api_server/service/internal_notify_service.go rename to component/rulex_api_server/service/internal_notify_service.go index 2c6e819bb..7f2a44365 100644 --- a/plugin/rulex_api_server/service/internal_notify_service.go +++ b/component/rulex_api_server/service/internal_notify_service.go @@ -17,7 +17,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) /* diff --git a/plugin/rulex_api_server/service/linux_network_config_service.go b/component/rulex_api_server/service/linux_network_config_service.go similarity index 98% rename from plugin/rulex_api_server/service/linux_network_config_service.go rename to component/rulex_api_server/service/linux_network_config_service.go index b3f470540..6cdeea9fc 100644 --- a/plugin/rulex_api_server/service/linux_network_config_service.go +++ b/component/rulex_api_server/service/linux_network_config_service.go @@ -5,8 +5,8 @@ import ( "os/exec" "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) /* diff --git a/plugin/rulex_api_server/service/linux_wlan_config_service.go b/component/rulex_api_server/service/linux_wlan_config_service.go similarity index 96% rename from plugin/rulex_api_server/service/linux_wlan_config_service.go rename to component/rulex_api_server/service/linux_wlan_config_service.go index 085ad01e2..61b10ed95 100644 --- a/plugin/rulex_api_server/service/linux_wlan_config_service.go +++ b/component/rulex_api_server/service/linux_wlan_config_service.go @@ -2,8 +2,8 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" ) /* diff --git a/plugin/rulex_api_server/service/linuxamixer.md b/component/rulex_api_server/service/linuxamixer.md similarity index 100% rename from plugin/rulex_api_server/service/linuxamixer.md rename to component/rulex_api_server/service/linuxamixer.md diff --git a/plugin/rulex_api_server/service/linuxnetcfg.md b/component/rulex_api_server/service/linuxnetcfg.md similarity index 100% rename from plugin/rulex_api_server/service/linuxnetcfg.md rename to component/rulex_api_server/service/linuxnetcfg.md diff --git a/plugin/rulex_api_server/service/linuxtimecfg.md b/component/rulex_api_server/service/linuxtimecfg.md similarity index 100% rename from plugin/rulex_api_server/service/linuxtimecfg.md rename to component/rulex_api_server/service/linuxtimecfg.md diff --git a/plugin/rulex_api_server/service/memory_usage_linux.go b/component/rulex_api_server/service/memory_usage_linux.go similarity index 100% rename from plugin/rulex_api_server/service/memory_usage_linux.go rename to component/rulex_api_server/service/memory_usage_linux.go diff --git a/plugin/rulex_api_server/service/memory_usage_windows.go b/component/rulex_api_server/service/memory_usage_windows.go similarity index 100% rename from plugin/rulex_api_server/service/memory_usage_windows.go rename to component/rulex_api_server/service/memory_usage_windows.go diff --git a/plugin/rulex_api_server/service/page_service.go b/component/rulex_api_server/service/page_service.go similarity index 93% rename from plugin/rulex_api_server/service/page_service.go rename to component/rulex_api_server/service/page_service.go index 4ef7993db..564540cc9 100644 --- a/plugin/rulex_api_server/service/page_service.go +++ b/component/rulex_api_server/service/page_service.go @@ -4,7 +4,7 @@ import ( "strconv" "github.com/gin-gonic/gin" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "gorm.io/gorm" ) diff --git a/plugin/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go b/component/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go similarity index 98% rename from plugin/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go rename to component/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go index 2416e3615..0ac9d6159 100644 --- a/plugin/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go +++ b/component/rulex_api_server/service/rhinoh3_ubuntu18_iproute_service.go @@ -21,7 +21,7 @@ import ( "strings" "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) /* diff --git a/plugin/rulex_api_server/service/site_config_service.go b/component/rulex_api_server/service/site_config_service.go similarity index 95% rename from plugin/rulex_api_server/service/site_config_service.go rename to component/rulex_api_server/service/site_config_service.go index a6fd88978..7e3cadee6 100644 --- a/plugin/rulex_api_server/service/site_config_service.go +++ b/component/rulex_api_server/service/site_config_service.go @@ -17,7 +17,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) func GetSiteConfig() (model.MSiteConfig, error) { diff --git a/plugin/rulex_api_server/service/user_lua_template_service.go b/component/rulex_api_server/service/user_lua_template_service.go similarity index 97% rename from plugin/rulex_api_server/service/user_lua_template_service.go rename to component/rulex_api_server/service/user_lua_template_service.go index 8ba12be19..8788f26ee 100644 --- a/plugin/rulex_api_server/service/user_lua_template_service.go +++ b/component/rulex_api_server/service/user_lua_template_service.go @@ -17,7 +17,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) // 获取UserLuaTemplate列表 diff --git a/plugin/rulex_api_server/service/visual_screen_service.go b/component/rulex_api_server/service/visual_screen_service.go similarity index 94% rename from plugin/rulex_api_server/service/visual_screen_service.go rename to component/rulex_api_server/service/visual_screen_service.go index a0e994fb0..3820054b9 100644 --- a/plugin/rulex_api_server/service/visual_screen_service.go +++ b/component/rulex_api_server/service/visual_screen_service.go @@ -2,7 +2,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) // 获取Visual列表 diff --git a/plugin/rulex_api_server/service/windows.md b/component/rulex_api_server/service/windows.md similarity index 100% rename from plugin/rulex_api_server/service/windows.md rename to component/rulex_api_server/service/windows.md diff --git a/plugin/rulex_api_server/service/windows_eth_config.go b/component/rulex_api_server/service/windows_eth_config.go similarity index 100% rename from plugin/rulex_api_server/service/windows_eth_config.go rename to component/rulex_api_server/service/windows_eth_config.go diff --git a/plugin/rulex_api_server/structure.png b/component/rulex_api_server/structure.png similarity index 100% rename from plugin/rulex_api_server/structure.png rename to component/rulex_api_server/structure.png diff --git a/engine/runner.go b/engine/runner.go index 157982c6c..dc66e9940 100644 --- a/engine/runner.go +++ b/engine/runner.go @@ -30,11 +30,11 @@ import ( usbmonitor "github.com/hootrhino/rulex/plugin/usb_monitor" "gopkg.in/ini.v1" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/glogger" icmpsender "github.com/hootrhino/rulex/plugin/icmp_sender" license_manager "github.com/hootrhino/rulex/plugin/license_manager" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/glogger/ws_logger.md b/glogger/ws_logger.md index 4675e2afa..c72e751a8 100644 --- a/glogger/ws_logger.md +++ b/glogger/ws_logger.md @@ -63,7 +63,7 @@ $$ { "appId":"rulex", "file":"C:/Users/wangwenhai/workspace/rulex/plugin/http_server/rule_api.go:580", - "func":"github.com/hootrhino/rulex/plugin/rulex_api_server.TestSourceCallback", + "func":"github.com/hootrhino/rulex/component/rulex_api_server.TestSourceCallback", "level":"debug", "msg":"string", "time":"2023-06-30T17:52:31+08:00", @@ -75,7 +75,7 @@ $$ { "appId":"rulex", "file":"C:/Users/wangwenhai/workspace/rulex/plugin/http_server/rule_api.go:580", - "func":"github.com/hootrhino/rulex/plugin/rulex_api_server.TestSourceCallback", + "func":"github.com/hootrhino/rulex/component/rulex_api_server.TestSourceCallback", "level":"debug", "msg":"string", "time":"2023-06-30T17:52:31+08:00", diff --git a/plugin/rulex_api_server/server/www/index.html b/plugin/rulex_api_server/server/www/index.html deleted file mode 100644 index 8e6265367..000000000 --- a/plugin/rulex_api_server/server/www/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - Rulex - - - - - - Hello,Rulex. - - - \ No newline at end of file diff --git a/test/appstack_httpapi_test.go b/test/appstack_httpapi_test.go index 94f5fbee8..76f419901 100644 --- a/test/appstack_httpapi_test.go +++ b/test/appstack_httpapi_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/go-playground/assert/v2" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) /* diff --git a/test/binary_lua_test.go b/test/binary_lua_test.go index 26648bba2..0eb7efbfe 100644 --- a/test/binary_lua_test.go +++ b/test/binary_lua_test.go @@ -5,12 +5,12 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/plugin/demo_plugin" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/custom_tcp_server_test.go b/test/custom_tcp_server_test.go index 94ce31e91..3eba538c7 100644 --- a/test/custom_tcp_server_test.go +++ b/test/custom_tcp_server_test.go @@ -7,7 +7,7 @@ import ( "time" "github.com/hootrhino/rulex/component/appstack" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/test/device_485ther_gw_test.go b/test/device_485ther_gw_test.go index 660a0896b..96201f8d1 100644 --- a/test/device_485ther_gw_test.go +++ b/test/device_485ther_gw_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "testing" diff --git a/test/device_custom_protocol_device_test.go b/test/device_custom_protocol_device_test.go index f2f71cbcb..82e3f46a6 100644 --- a/test/device_custom_protocol_device_test.go +++ b/test/device_custom_protocol_device_test.go @@ -9,8 +9,8 @@ import ( serial "github.com/wwhai/tarmserial" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "google.golang.org/grpc" diff --git a/test/device_daccall_test.go b/test/device_daccall_test.go index c159201a7..e72d8bc16 100644 --- a/test/device_daccall_test.go +++ b/test/device_daccall_test.go @@ -4,9 +4,9 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/glogger" mqttserver "github.com/hootrhino/rulex/plugin/mqtt_server" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/test/device_g776dtu_test.go b/test/device_g776dtu_test.go index 61faac9ca..037d222b9 100644 --- a/test/device_g776dtu_test.go +++ b/test/device_g776dtu_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/test/device_generic_ais_rxtx_device_test.go b/test/device_generic_ais_rxtx_device_test.go index 78bdee473..beaf44172 100644 --- a/test/device_generic_ais_rxtx_device_test.go +++ b/test/device_generic_ais_rxtx_device_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/adrianmo/go-nmea" "github.com/hootrhino/rulex/typex" diff --git a/test/device_generic_camera_stream_test.go b/test/device_generic_camera_stream_test.go index a32f0a3ad..514990070 100644 --- a/test/device_generic_camera_stream_test.go +++ b/test/device_generic_camera_stream_test.go @@ -1,8 +1,8 @@ package test import ( + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" "time" diff --git a/test/device_generic_modbus_device_test.go b/test/device_generic_modbus_device_test.go index 53431c25d..c032b1cd9 100644 --- a/test/device_generic_modbus_device_test.go +++ b/test/device_generic_modbus_device_test.go @@ -3,8 +3,8 @@ package test import ( "context" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" mbserver "github.com/tbrandon/mbserver" "testing" diff --git a/test/device_generic_opcua_device_test.go b/test/device_generic_opcua_device_test.go index 45b310bc7..7dc732748 100644 --- a/test/device_generic_opcua_device_test.go +++ b/test/device_generic_opcua_device_test.go @@ -4,9 +4,9 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/device" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" ) diff --git a/test/device_generic_snmp_device_test.go b/test/device_generic_snmp_device_test.go index 7b22ced18..d128f7ad1 100644 --- a/test/device_generic_snmp_device_test.go +++ b/test/device_generic_snmp_device_test.go @@ -1,8 +1,8 @@ package test import ( + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" "time" diff --git a/test/device_generic_uart_device_test.go b/test/device_generic_uart_device_test.go index bfd65a4fa..b5151a71c 100644 --- a/test/device_generic_uart_device_test.go +++ b/test/device_generic_uart_device_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "testing" diff --git a/test/device_gos7_plc_data_parse_test.go b/test/device_gos7_plc_data_parse_test.go index e6ae39077..e9f588ed3 100644 --- a/test/device_gos7_plc_data_parse_test.go +++ b/test/device_gos7_plc_data_parse_test.go @@ -5,9 +5,9 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/device_icmp_sender_test.go b/test/device_icmp_sender_test.go index 46a0142a9..ac858d6fd 100644 --- a/test/device_icmp_sender_test.go +++ b/test/device_icmp_sender_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "testing" diff --git a/test/device_modbus_wite_with_app_test.go b/test/device_modbus_wite_with_app_test.go index 46a3a5a41..5d3e75fdc 100644 --- a/test/device_modbus_wite_with_app_test.go +++ b/test/device_modbus_wite_with_app_test.go @@ -5,7 +5,7 @@ import ( "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/component/appstack" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "testing" diff --git a/test/device_th_485_sensor_data_parse_test.go b/test/device_th_485_sensor_data_parse_test.go index e0cae2fff..6ac7a1ec8 100644 --- a/test/device_th_485_sensor_data_parse_test.go +++ b/test/device_th_485_sensor_data_parse_test.go @@ -6,8 +6,8 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/device_tss200_test.go b/test/device_tss200_test.go index 3062b1505..f76162e55 100644 --- a/test/device_tss200_test.go +++ b/test/device_tss200_test.go @@ -1,8 +1,8 @@ package test import ( + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "testing" "time" diff --git a/test/device_yk8_with_rulex_test.go b/test/device_yk8_with_rulex_test.go index ebb6d431b..b7be8a148 100644 --- a/test/device_yk8_with_rulex_test.go +++ b/test/device_yk8_with_rulex_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "testing" diff --git a/test/fully_test.go b/test/fully_test.go index 96aac572a..bd7a2fa57 100644 --- a/test/fully_test.go +++ b/test/fully_test.go @@ -3,9 +3,9 @@ package test import ( "context" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "testing" diff --git a/test/http_api_device_snmp_curd_test.go b/test/http_api_device_snmp_curd_test.go index 29c1adea6..007bd82d7 100644 --- a/test/http_api_device_snmp_curd_test.go +++ b/test/http_api_device_snmp_curd_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/go-playground/assert/v2" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/model" ) /* diff --git a/test/init_data_test.go b/test/init_data_test.go index 40732c4ac..32db1312c 100644 --- a/test/init_data_test.go +++ b/test/init_data_test.go @@ -4,12 +4,12 @@ import ( "encoding/json" "testing" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" - "github.com/hootrhino/rulex/plugin/rulex_api_server/service" "github.com/hootrhino/rulex/typex" ) diff --git a/test/jq_test.go b/test/jq_test.go index 1916538ce..c600629fe 100644 --- a/test/jq_test.go +++ b/test/jq_test.go @@ -5,9 +5,9 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/modbus_parse_test.go b/test/modbus_parse_test.go index 5edaaaa9a..f18b0b9c6 100644 --- a/test/modbus_parse_test.go +++ b/test/modbus_parse_test.go @@ -8,12 +8,12 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/plugin/demo_plugin" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/rpc_codec_test.go b/test/rpc_codec_test.go index d8b638921..50bb11ce3 100644 --- a/test/rpc_codec_test.go +++ b/test/rpc_codec_test.go @@ -6,9 +6,9 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/rule_id_get_test.go b/test/rule_id_get_test.go index a712d517b..3f7ea419c 100644 --- a/test/rule_id_get_test.go +++ b/test/rule_id_get_test.go @@ -5,9 +5,9 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/rulex_snapshot_dump_test.go b/test/rulex_snapshot_dump_test.go index 771274163..16ab8fbf2 100644 --- a/test/rulex_snapshot_dump_test.go +++ b/test/rulex_snapshot_dump_test.go @@ -8,12 +8,12 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/engine" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/plugin/demo_plugin" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/source_http_source_test.go b/test/source_http_source_test.go index 56cd4bef0..e05362ae4 100644 --- a/test/source_http_source_test.go +++ b/test/source_http_source_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/utils" "github.com/hootrhino/rulex/typex" diff --git a/test/suorce_txiothub_test.go b/test/suorce_txiothub_test.go index da782e79a..903e4e03a 100644 --- a/test/suorce_txiothub_test.go +++ b/test/suorce_txiothub_test.go @@ -3,7 +3,7 @@ package test import ( "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "testing" diff --git a/test/target_data_to_mongodb_test.go b/test/target_data_to_mongodb_test.go index 90277d978..07df91b4f 100644 --- a/test/target_data_to_mongodb_test.go +++ b/test/target_data_to_mongodb_test.go @@ -7,9 +7,9 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/target_data_tohttp_test.go b/test/target_data_tohttp_test.go index 216f1d9b6..08f20c8a1 100644 --- a/test/target_data_tohttp_test.go +++ b/test/target_data_tohttp_test.go @@ -10,8 +10,8 @@ import ( "time" "github.com/go-playground/assert/v2" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/typex" ) diff --git a/test/target_data_toudp_test.go b/test/target_data_toudp_test.go index 7da3deb4d..baecd45f6 100644 --- a/test/target_data_toudp_test.go +++ b/test/target_data_toudp_test.go @@ -10,8 +10,8 @@ import ( "time" "github.com/go-playground/assert/v2" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" - "github.com/hootrhino/rulex/plugin/rulex_api_server/model" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/typex" ) diff --git a/test/target_tdengine_test.go b/test/target_tdengine_test.go index 5974d393f..344d7ffcf 100644 --- a/test/target_tdengine_test.go +++ b/test/target_tdengine_test.go @@ -7,8 +7,8 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/rulexrpc" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "github.com/hootrhino/rulex/typex" "google.golang.org/grpc" diff --git a/test/test_utils.go b/test/test_utils.go index 0a1d0662b..a3cfd771b 100644 --- a/test/test_utils.go +++ b/test/test_utils.go @@ -10,7 +10,7 @@ import ( "testing" "time" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/engine" diff --git a/test/trailer_test.go b/test/trailer_test.go index c87e14487..700def8a3 100644 --- a/test/trailer_test.go +++ b/test/trailer_test.go @@ -7,9 +7,9 @@ import ( "testing" "time" + httpserver "github.com/hootrhino/rulex/component/rulex_api_server" "github.com/hootrhino/rulex/component/trailer" "github.com/hootrhino/rulex/glogger" - httpserver "github.com/hootrhino/rulex/plugin/rulex_api_server" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) diff --git a/typex/version.go b/typex/version.go index a6a510d41..9ec43a7c1 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-05 22:28:39", + ReleaseTime: "2023-12-05 23:37:46", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-197287bd39f45e9 +** Version: v0.6.4-c36c563c96bd80a ** Document: https://hootrhino.github.io ` From cb00bdc4b5de751f8866d9637c33ccf89c80915d Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 6 Dec 2023 16:27:45 +0800 Subject: [PATCH 094/138] dev: remove api path --- component/rulex_api_server/http_api_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 85fd195b6..18ec1bedf 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -406,7 +406,7 @@ func (hs *ApiServerPlugin) LoadRoute() { userLuaApi.GET("/listByGroup", server.AddRoute(apis.ListUserLuaTemplateByGroup)) userLuaApi.GET("/detail", server.AddRoute(apis.UserLuaTemplateDetail)) userLuaApi.GET("/group", server.AddRoute(apis.ListUserLuaTemplateGroup)) - userLuaApi.DELETE("/delete", server.AddRoute(apis.DeleteUserLuaTemplate)) + userLuaApi.DELETE("/del", server.AddRoute(apis.DeleteUserLuaTemplate)) } /* * From 4959ee5a7ac722a0640a7f21bc38b088e7e0f86d Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 6 Dec 2023 18:21:51 +0800 Subject: [PATCH 095/138] dev: add detail filed to UserLuaTemplate --- .../apis/user_lua_template_api.go | 56 ++++++++++--------- .../model/user_lua_template.go | 9 +-- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/component/rulex_api_server/apis/user_lua_template_api.go b/component/rulex_api_server/apis/user_lua_template_api.go index 8c51638fb..e5f0f0571 100644 --- a/component/rulex_api_server/apis/user_lua_template_api.go +++ b/component/rulex_api_server/apis/user_lua_template_api.go @@ -10,11 +10,12 @@ import ( ) type UserLuaTemplateVo struct { - Gid string `json:"gid,omitempty"` // 分组ID - UUID string `json:"uuid,omitempty"` // 名称 - Label string `json:"label"` //快捷代码名称 - Apply string `json:"apply"` //快捷代码 - Type string `json:"type"` // 类型 固定为function类型detail + Gid string `json:"gid,omitempty"` // 分组ID + UUID string `json:"uuid,omitempty"` // 名称 + Label string `json:"label"` //快捷代码名称 + Apply string `json:"apply"` //快捷代码 + Type string `json:"type"` // 类型 固定为function类型detail + Detail string `json:"detail"` } /* @@ -35,10 +36,11 @@ func CreateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { return } MUserLuaTemplate := model.MUserLuaTemplate{ - UUID: utils.UserLuaUuid(), - Label: form.Label, - Type: "function", - Apply: form.Apply, + UUID: utils.UserLuaUuid(), + Label: form.Label, + Type: "function", + Apply: form.Apply, + Detail: form.Detail, } if err := service.InsertUserLuaTemplate(MUserLuaTemplate); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) @@ -68,10 +70,11 @@ func UpdateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { return } MUserLuaTemplate := model.MUserLuaTemplate{ - UUID: form.UUID, - Label: form.Label, - Type: form.Type, - Apply: form.Apply, + UUID: form.UUID, + Label: form.Label, + Type: form.Type, + Apply: form.Apply, + Detail: form.Detail, } if err := service.UpdateUserLuaTemplate(MUserLuaTemplate); err != nil { @@ -131,10 +134,11 @@ func ListUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { UserLuaTemplates := []UserLuaTemplateVo{} for _, vv := range service.AllUserLuaTemplate() { Vo := UserLuaTemplateVo{ - UUID: vv.UUID, - Label: vv.Label, - Type: vv.Type, - Apply: vv.Apply, + UUID: vv.UUID, + Label: vv.Label, + Type: vv.Type, + Apply: vv.Apply, + Detail: vv.Detail, } Group := service.GetUserLuaTemplateGroup(vv.UUID) if Group.UUID != "" { @@ -159,10 +163,11 @@ func ListUserLuaTemplateByGroup(c *gin.Context, ruleEngine typex.RuleX) { MUserLuaTemplates := service.FindUserTemplateByGroup(Gid) for _, vv := range MUserLuaTemplates { Vo := UserLuaTemplateVo{ - UUID: vv.UUID, - Label: vv.Label, - Type: vv.Type, - Apply: vv.Apply, + UUID: vv.UUID, + Label: vv.Label, + Type: vv.Type, + Apply: vv.Apply, + Detail: vv.Detail, } Group := service.GetUserLuaTemplateGroup(vv.UUID) Vo.Gid = Group.UUID @@ -184,10 +189,11 @@ func UserLuaTemplateDetail(c *gin.Context, ruleEngine typex.RuleX) { return } Vo := UserLuaTemplateVo{ - UUID: mUserLuaTemplate.UUID, - Label: mUserLuaTemplate.Label, - Type: mUserLuaTemplate.Type, - Apply: mUserLuaTemplate.Apply, + UUID: mUserLuaTemplate.UUID, + Label: mUserLuaTemplate.Label, + Type: mUserLuaTemplate.Type, + Apply: mUserLuaTemplate.Apply, + Detail: mUserLuaTemplate.Detail, } Group := service.GetUserLuaTemplateGroup(mUserLuaTemplate.UUID) if Group.UUID != "" { diff --git a/component/rulex_api_server/model/user_lua_template.go b/component/rulex_api_server/model/user_lua_template.go index 20c7cc466..ad43def69 100644 --- a/component/rulex_api_server/model/user_lua_template.go +++ b/component/rulex_api_server/model/user_lua_template.go @@ -21,8 +21,9 @@ package model */ type MUserLuaTemplate struct { RulexModel - UUID string - Type string // 类型 固定为 'function' - Label string //快捷代码名称 - Apply string //快捷代码 + UUID string + Type string // 类型 固定为 'function' + Label string //快捷代码名称 + Apply string //快捷代码 + Detail string } From 7444ac64fcab256799493388e917b19cae3942d1 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 7 Dec 2023 13:10:55 +0800 Subject: [PATCH 096/138] dev: add UserLuaTemplateDetail --- .../apis/user_lua_template_api.go | 20 +++++++++++++++++++ component/rulex_api_server/http_api_server.go | 1 + .../service/user_lua_template_service.go | 16 +++++++++++++++ typex/version.go | 4 ++-- 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/component/rulex_api_server/apis/user_lua_template_api.go b/component/rulex_api_server/apis/user_lua_template_api.go index e5f0f0571..22c9154b3 100644 --- a/component/rulex_api_server/apis/user_lua_template_api.go +++ b/component/rulex_api_server/apis/user_lua_template_api.go @@ -125,6 +125,26 @@ func ListUserLuaTemplateGroup(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.OkWithData(visuals)) } +/* +* +* 模糊查询 +* + */ +func SearchUserLuaTemplateGroup(c *gin.Context, ruleEngine typex.RuleX) { + visuals := []UserLuaTemplateVo{} + keyword, _ := c.GetQuery("keyword") + for _, vv := range service.SearchUserLuaTemplate(keyword, keyword) { + visuals = append(visuals, UserLuaTemplateVo{ + UUID: vv.UUID, + Label: vv.Label, + Type: vv.Type, + Apply: vv.Apply, + Detail: vv.Detail, + }) + } + c.JSON(common.HTTP_OK, common.OkWithData(visuals)) +} + /* * * 用户模板列表 diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 18ec1bedf..c8becddb0 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -407,6 +407,7 @@ func (hs *ApiServerPlugin) LoadRoute() { userLuaApi.GET("/detail", server.AddRoute(apis.UserLuaTemplateDetail)) userLuaApi.GET("/group", server.AddRoute(apis.ListUserLuaTemplateGroup)) userLuaApi.DELETE("/del", server.AddRoute(apis.DeleteUserLuaTemplate)) + userLuaApi.GET("/search", server.AddRoute(apis.SearchUserLuaTemplateGroup)) } /* * diff --git a/component/rulex_api_server/service/user_lua_template_service.go b/component/rulex_api_server/service/user_lua_template_service.go index 8788f26ee..928fbc5e0 100644 --- a/component/rulex_api_server/service/user_lua_template_service.go +++ b/component/rulex_api_server/service/user_lua_template_service.go @@ -16,6 +16,8 @@ package service import ( + "fmt" + "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/component/rulex_api_server/model" ) @@ -28,6 +30,20 @@ func AllUserLuaTemplate() []model.MUserLuaTemplate { } +// 模糊查询 +// SELECT * FROM m_user_lua_templates +// WHERE label like "%%" +// OR detail like "%%" +func SearchUserLuaTemplate(label, detail string) []model.MUserLuaTemplate { + m := []model.MUserLuaTemplate{} + sql := ` +SELECT * FROM m_user_lua_templates +WHERE label like "%%%s%%" +OR detail like "%%%s%%"` + interdb.DB().Raw(fmt.Sprintf(sql, label, detail)).Scan(&m) + return m +} + /* * * 获取分组 diff --git a/typex/version.go b/typex/version.go index 9ec43a7c1..9760373fd 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-05 23:37:46", + ReleaseTime: "2023-12-07 13:05:36", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-c36c563c96bd80a +** Version: v0.6.4-4959ee5a7ac722a ** Document: https://hootrhino.github.io ` From c453e9cd189b5e6eebd95cba2de3b25cda6d2f7d Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 7 Dec 2023 20:01:09 +0800 Subject: [PATCH 097/138] feat: add s7-1200 support --- common/siemens_config.go | 39 ++++++-------- device/s1200plc_device.go | 52 ++++++++++++------- device/s1200plc_device.md | 75 ++++++++++++++++++++++++++- driver/siemens_s1200_driver.go | 72 +++++++++++++++++-------- test/lua/siemens_s1200_data_parse.lua | 52 +++++++++++++++++++ 5 files changed, 222 insertions(+), 68 deletions(-) create mode 100644 test/lua/siemens_s1200_data_parse.lua diff --git a/common/siemens_config.go b/common/siemens_config.go index d0b70af9d..9f2882212 100644 --- a/common/siemens_config.go +++ b/common/siemens_config.go @@ -6,30 +6,21 @@ package common * */ type S1200Config struct { - Host string `json:"host" validate:"required" title:"IP地址"` // 127.0.0.1 - Port *int `json:"port" validate:"required" title:"端口号"` // 0 - Rack *int `json:"rack" validate:"required" title:"架号"` // 0 - Slot *int `json:"slot" validate:"required" title:"槽号"` // 1 - Model string `json:"model" validate:"required" title:"型号"` // s7-200 s7 1500 - Timeout *int `json:"timeout" validate:"required" title:"连接超时时间"` // 5s - IdleTimeout *int `json:"idleTimeout" validate:"required" title:"心跳超时时间"` // 5s - // - // Weather allow AutoRequest? - AutoRequest bool `json:"autoRequest" title:"启动轮询"` - // Request Frequency, default 5 second - Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` - Blocks []S1200Block `json:"blocks" validate:"required" title:"采集配置"` // Db + Host string `json:"host" validate:"required" title:"IP地址:端口号"` // 127.0.0.1 + Model string `json:"model" validate:"required" title:"型号"` // s7-200 s7 1500 + Rack *int `json:"rack" validate:"required" title:"架号"` // 0 + Slot *int `json:"slot" validate:"required" title:"槽号"` // 1 + Timeout *int `json:"timeout" validate:"required" title:"连接超时时间"` // 5s + IdleTimeout *int `json:"idleTimeout" validate:"required" title:"心跳超时时间"` // 5s + AutoRequest *bool `json:"autoRequest" title:"启动轮询"` + Blocks []S1200Block `json:"blocks" validate:"required" title:"采集配置"` // Db } type S1200Block struct { - Tag string `json:"tag" title:"数据tag"` // 数据tag - Address int `json:"address" title:"地址"` // 地址 - Start int `json:"start" title:"起始地址"` // 起始地址 - Size int `json:"size" title:"数据长度"` // 数据长度 -} -type S1200BlockValue struct { - Tag string `json:"tag" title:"数据tag"` // 数据tag - Address int `json:"address" title:"地址"` // 地址 - Start int `json:"start" title:"起始地址"` // 起始地址 - Size int `json:"size" title:"服务地址"` // 数据长度 - Value []byte `json:"value" title:"数据长度"` // 值 + Tag string `json:"tag" validate:"required" title:"数据tag"` // 数据tag + Type string `json:"type" validate:"required" title:"地址"` // MB | DB |FB + Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` + Address int `json:"address" validate:"required" title:"地址"` // 地址 + Start int `json:"start" validate:"required" title:"起始地址"` // 起始地址 + Size int `json:"size" validate:"required" title:"服务地址"` // 数据长度 + Value string `json:"value,omitempty" validate:"required" title:"数据Hex"` // 值 } diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index c20a84c71..fcd1dec97 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "sync" "time" @@ -16,6 +15,7 @@ import ( "github.com/robinson/gos7" ) +// https://www.ad.siemens.com.cn/productportal/prods/s7-1200_plc_easy_plus/07-Program/02-basic/01-Data_Type/01-basic.html type s1200plc struct { typex.XStatus status typex.DeviceState @@ -23,7 +23,6 @@ type s1200plc struct { driver typex.XExternalDriver mainConfig common.S1200Config client gos7.Client - block []common.S1200Block // PLC 的DB块 lock sync.Mutex } @@ -36,7 +35,18 @@ func NewS1200plc(e typex.RuleX) typex.XDevice { s1200 := new(s1200plc) s1200.RuleEngine = e s1200.lock = sync.Mutex{} - s1200.mainConfig = common.S1200Config{} + Rack := 0 + Slot := 1 + Timeout := 1000 + IdleTimeout := 3000 + AutoRequest := false + s1200.mainConfig = common.S1200Config{ + Rack: &Rack, + Slot: &Slot, + Timeout: &Timeout, + IdleTimeout: &IdleTimeout, + AutoRequest: &AutoRequest, + } return s1200 } @@ -64,8 +74,8 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { s1200.CancelCTX = cctx.CancelCTX // handler := gos7.NewTCPClientHandler( - // 127.0.0.1:8080 - fmt.Sprintf("%s:%d", s1200.mainConfig.Host, *s1200.mainConfig.Port), + // 127.0.0.1:1500 + s1200.mainConfig.Host, *s1200.mainConfig.Rack, *s1200.mainConfig.Slot) handler.Timeout = 5 * time.Second @@ -75,13 +85,13 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { handler.Timeout = time.Duration(*s1200.mainConfig.Timeout) * time.Second handler.IdleTimeout = time.Duration(*s1200.mainConfig.IdleTimeout) * time.Second s1200.client = gos7.NewClient(handler) - s1200.driver = driver.NewS1200Driver(s1200.Details(), s1200.RuleEngine, s1200.client, s1200.block) - if !s1200.mainConfig.AutoRequest { + s1200.driver = driver.NewS1200Driver(s1200.Details(), + s1200.RuleEngine, s1200.client, s1200.mainConfig.Blocks) + if !*s1200.mainConfig.AutoRequest { s1200.status = typex.DEV_UP return nil } go func(ctx context.Context) { - ticker := time.NewTicker(time.Duration(s1200.mainConfig.Frequency) * time.Millisecond) // 数据缓冲区,最大4KB dataBuffer := make([]byte, common.T_4KB) s1200.driver.Read([]byte{}, dataBuffer) //清理缓存 @@ -89,22 +99,18 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { select { case <-ctx.Done(): { - ticker.Stop() - if s1200.driver != nil { - s1200.driver.Stop() - } return } default: { - // Do nothing } } if s1200.driver == nil { return } s1200.lock.Lock() - n, err := s1200.driver.Read([]byte{}, dataBuffer) + // CMD 参数无用 + n, err := s1200.driver.Read([]byte(""), dataBuffer) s1200.lock.Unlock() if err != nil { glogger.GLogger.Error(err) @@ -114,10 +120,10 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { s1200.RuleEngine.GetDevice(s1200.PointId), string(dataBuffer[:n]), ) + // glogger.GLogger.Debug(string(dataBuffer[:n])) if !ok { glogger.GLogger.Error(err) } - <-ticker.C } }(cctx.Ctx) @@ -144,7 +150,7 @@ func (s1200 *s1200plc) OnRead(cmd []byte, data []byte) (int, error) { // // ] func (s1200 *s1200plc) OnWrite(cmd []byte, data []byte) (int, error) { - blocks := []common.S1200BlockValue{} + blocks := []common.S1200Block{} if err := json.Unmarshal(data, &blocks); err != nil { return 0, err } @@ -153,8 +159,10 @@ func (s1200 *s1200plc) OnWrite(cmd []byte, data []byte) (int, error) { // 设备当前状态 func (s1200 *s1200plc) Status() typex.DeviceState { - if s1200.driver.State() == typex.DRIVER_UP { - return typex.DEV_UP + if s1200.driver != nil { + if s1200.driver.State() == typex.DRIVER_UP { + return typex.DEV_UP + } } return typex.DEV_DOWN @@ -163,8 +171,12 @@ func (s1200 *s1200plc) Status() typex.DeviceState { // 停止设备 func (s1200 *s1200plc) Stop() { s1200.status = typex.DEV_DOWN - s1200.CancelCTX() - + if s1200.CancelCTX != nil { + s1200.CancelCTX() + } + if s1200.driver != nil { + s1200.driver.Stop() + } } // 设备属性,是一系列属性描述 diff --git a/device/s1200plc_device.md b/device/s1200plc_device.md index 350c891e5..ac7760c18 100644 --- a/device/s1200plc_device.md +++ b/device/s1200plc_device.md @@ -7,4 +7,77 @@ PLC S1200系列设备通常用于控制和监视各种工业过程,例如生 PLC S1200系列设备提供了丰富的输入输出接口、通信接口和编程功能,以满足各种自动化控制需求。通过编程,用户可以定义逻辑控制规则、配置输入输出映射、实现数据处理和通信功能等。 -需要注意的是,PLC S1200是西门子(Siemens)公司的商标产品,更详细的信息和技术规格可以参考西门子官方文档或与其联系。 \ No newline at end of file +需要注意的是,PLC S1200是西门子(Siemens)公司的商标产品,更详细的信息和技术规格可以参考西门子官方文档或与其联系。 + +## 参数 +```json +{ + "name": "S1200PLC", + "type": "S1200PLC", + "gid": "DROOT", + "config": { + "host": "127.0.0.1:1500", + "rack": 0, + "slot": 1, + "model": "S1200PLC", + "timeout": 1000, + "autoRequest": true, + "idleTimeout": 1000, + "frequency": 1000, + "blocks": [ + { + "tag": "Value", + "frequency": 1000, + "type": "DB", + "address": 1, + "start": 100, + "size": 16 + } + ] + }, + "description": "S1200PLC" +} +``` +## 脚本示例 +```lua + +-- Actions +-- 采集到的数据: +-- { +-- "tag":"Value", +-- "type":"DB", +-- "frequency":0, +-- "address":1, +-- "start":100, +-- "size":16, +-- "value":"00000001000000020000000300000004" +-- } +Actions = +{ + function(args) + local dataT, err = json:J2T(args) + if (err ~= nil) then + stdlib:Debug('parse json error:' .. err) + return true, args + end + for key, value in pairs(dataT) do + --data: 00000001000000020000000300000004 + local MatchHexS = hex:MatchUInt("a:[0,3];b:[4,7];c:[8,11];d:[12,15]", value['value']) + local ts = time:Time() + local Json = json:T2J( + { + tag = key, + ts = ts, + a = MatchHexS['a'], + b = MatchHexS['b'], + c = MatchHexS['c'], + d = MatchHexS['d'], + } + ) + stdlib:Debug(Json) + end + return true, args + end +} + +``` \ No newline at end of file diff --git a/driver/siemens_s1200_driver.go b/driver/siemens_s1200_driver.go index 23cdd5f8c..5b539cf04 100644 --- a/driver/siemens_s1200_driver.go +++ b/driver/siemens_s1200_driver.go @@ -1,8 +1,9 @@ package driver import ( + "encoding/hex" "encoding/json" - "sync" + "time" "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/glogger" @@ -22,7 +23,6 @@ type siemens_s1200_driver struct { device *typex.Device RuleEngine typex.RuleX dbs []common.S1200Block // PLC 的DB块 - lock sync.Mutex } func NewS1200Driver(d *typex.Device, @@ -35,7 +35,6 @@ func NewS1200Driver(d *typex.Device, RuleEngine: e, s7client: s7client, dbs: dbs, - lock: sync.Mutex{}, } } @@ -68,24 +67,53 @@ func (s1200 *siemens_s1200_driver) State() typex.DriverState { // 字节格式:[dbNumber1, start1, size1, dbNumber2, start2, size2] // 读: db --> dbNumber, start, size, buffer[] +var rData = [common.T_2KB]byte{} // 一次最大接受2KB数据 + func (s1200 *siemens_s1200_driver) Read(cmd []byte, data []byte) (int, error) { - values := []common.S1200BlockValue{} + values := []common.S1200Block{} for _, db := range s1200.dbs { - rData := []byte{} - s1200.lock.Lock() - if err := s1200.s7client.AGReadDB(db.Address, db.Start, db.Size, rData); err != nil { - s1200.lock.Unlock() - return 0, err + //DB 4字节 + if db.Type == "DB" { + // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 + if err := s1200.s7client.AGReadDB(db.Address, db.Start, db.Size, rData[:]); err != nil { + return 0, err + } + count := db.Size + if db.Size*2 > 2000 { + count = 2000 + } + values = append(values, common.S1200Block{ + Tag: db.Tag, + Address: db.Address, + Type: db.Type, + Start: db.Start, + Size: db.Size, + Value: hex.EncodeToString(rData[:count]), + }) } - s1200.lock.Unlock() - values = append(values, common.S1200BlockValue{ - Tag: db.Tag, - Address: db.Address, - Start: db.Start, - Size: db.Size, - Value: rData, - }) - + // + if db.Type == "MB" { + // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 + if err := s1200.s7client.AGReadMB(db.Start, db.Size, rData[:]); err != nil { + return 0, err + } + count := db.Size + if db.Size*2 > 2000 { + count = 2000 + } + values = append(values, common.S1200Block{ + Tag: db.Tag, + Type: db.Type, + Address: db.Address, + Start: db.Start, + Size: db.Size, + Value: hex.EncodeToString(rData[:count]), + }) + } + if db.Frequency < 100 { + db.Frequency = 100 // 不能太快 + } + time.Sleep(time.Duration(db.Frequency) * time.Millisecond) } bytes, _ := json.Marshal(values) copy(data, bytes) @@ -105,23 +133,21 @@ func (s1200 *siemens_s1200_driver) Read(cmd []byte, data []byte) (int, error) { // // ] func (s1200 *siemens_s1200_driver) Write(cmd []byte, data []byte) (int, error) { - blocks := []common.S1200BlockValue{} + blocks := []common.S1200Block{} if err := json.Unmarshal(data, &blocks); err != nil { return 0, err } // for _, block := range blocks { - s1200.lock.Lock() + hexV, _ := hex.DecodeString(block.Value) if err := s1200.s7client.AGWriteDB( block.Address, block.Start, block.Size, - block.Value, + hexV, ); err != nil { - s1200.lock.Unlock() return 0, err } - s1200.lock.Unlock() } return 0, nil } diff --git a/test/lua/siemens_s1200_data_parse.lua b/test/lua/siemens_s1200_data_parse.lua new file mode 100644 index 000000000..5c00b4320 --- /dev/null +++ b/test/lua/siemens_s1200_data_parse.lua @@ -0,0 +1,52 @@ +-- Copyright (C) 2023 wwhai +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU Affero 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 Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + +-- Actions +-- { +-- "tag":"Value", +-- "type":"DB", +-- "frequency":0, +-- "address":1, +-- "start":100, +-- "size":16, +-- "value":"00000001000000020000000300000004" +-- } +Actions = +{ + function(args) + local dataT, err = json:J2T(args) + if (err ~= nil) then + stdlib:Debug('parse json error:' .. err) + return true, args + end + for key, value in pairs(dataT) do + --data: 00000001000000020000000300000004 + local MatchHexS = hex:MatchUInt("a:[0,3];b:[4,7];c:[8,11];d:[12,15]", value['value']) + local ts = time:Time() + local Json = json:T2J( + { + tag = key, + ts = ts, + a = MatchHexS['a'], + b = MatchHexS['b'], + c = MatchHexS['c'], + d = MatchHexS['d'], + } + ) + stdlib:Debug(Json) + end + return true, args + end +} From 09052b8521cb3ce674b05b4491d525661ce795d4 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 8 Dec 2023 15:20:00 +0800 Subject: [PATCH 098/138] dev: enhance s1200 driver --- device/s1200plc_device.go | 170 ++++++++++++++++++++++++--------- driver/siemens_s1200_driver.go | 165 -------------------------------- engine/load_device.go | 6 +- typex/version.go | 4 +- 4 files changed, 129 insertions(+), 216 deletions(-) delete mode 100644 driver/siemens_s1200_driver.go diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index fcd1dec97..0d8d8322b 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -2,26 +2,48 @@ package device import ( "context" + "encoding/hex" "encoding/json" "errors" "sync" "time" "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/driver" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "github.com/robinson/gos7" ) +type S1200Block struct { + Tag string `json:"tag" validate:"required"` // 数据tag + Type string `json:"type" validate:"required"` // 块类型 MB | DB |FB + Frequency *int64 `json:"frequency" validate:"required"` // 采集频率 + Address *int `json:"address" validate:"required"` // 块地址 + Start *int `json:"start" validate:"required"` // 起始地址 + Size *int `json:"size" validate:"required"` // 采集长度 + Value string `json:"value,omitempty"` // 值 +} +type S1200CommonConfig struct { + Host string `json:"host" validate:"required"` // 127.0.0.1:502 + Model string `json:"model" validate:"required"` // s7-200 s7-1500 + Rack *int `json:"rack" validate:"required"` // 0 + Slot *int `json:"slot" validate:"required"` // 1 + Timeout *int `json:"timeout" validate:"required"` // 5s + IdleTimeout *int `json:"idleTimeout" validate:"required"` // 5s + AutoRequest *bool `json:"autoRequest" validate:"required"` // false +} +type S1200Config struct { + CommonConfig S1200CommonConfig `json:"commonConfig" validate:"required"` // 通用配置 + Blocks []S1200Block `json:"blocks" validate:"required"` //点位表 +} + // https://www.ad.siemens.com.cn/productportal/prods/s7-1200_plc_easy_plus/07-Program/02-basic/01-Data_Type/01-basic.html type s1200plc struct { typex.XStatus status typex.DeviceState RuleEngine typex.RuleX - driver typex.XExternalDriver - mainConfig common.S1200Config + mainConfig S1200Config client gos7.Client lock sync.Mutex } @@ -40,12 +62,14 @@ func NewS1200plc(e typex.RuleX) typex.XDevice { Timeout := 1000 IdleTimeout := 3000 AutoRequest := false - s1200.mainConfig = common.S1200Config{ - Rack: &Rack, - Slot: &Slot, - Timeout: &Timeout, - IdleTimeout: &IdleTimeout, - AutoRequest: &AutoRequest, + s1200.mainConfig = S1200Config{ + CommonConfig: S1200CommonConfig{ + Rack: &Rack, + Slot: &Slot, + Timeout: &Timeout, + IdleTimeout: &IdleTimeout, + AutoRequest: &AutoRequest, + }, } return s1200 } @@ -74,27 +98,25 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { s1200.CancelCTX = cctx.CancelCTX // handler := gos7.NewTCPClientHandler( - // 127.0.0.1:1500 - s1200.mainConfig.Host, - *s1200.mainConfig.Rack, - *s1200.mainConfig.Slot) - handler.Timeout = 5 * time.Second + s1200.mainConfig.CommonConfig.Host, // 127.0.0.1:1500 + *s1200.mainConfig.CommonConfig.Rack, // 0 + *s1200.mainConfig.CommonConfig.Slot) // 1 + handler.Timeout = time.Duration( + *s1200.mainConfig.CommonConfig.Timeout) * time.Millisecond + handler.IdleTimeout = time.Duration( + *s1200.mainConfig.CommonConfig.IdleTimeout) * time.Millisecond if err := handler.Connect(); err != nil { return err } - handler.Timeout = time.Duration(*s1200.mainConfig.Timeout) * time.Second - handler.IdleTimeout = time.Duration(*s1200.mainConfig.IdleTimeout) * time.Second + s1200.client = gos7.NewClient(handler) - s1200.driver = driver.NewS1200Driver(s1200.Details(), - s1200.RuleEngine, s1200.client, s1200.mainConfig.Blocks) - if !*s1200.mainConfig.AutoRequest { + if !*s1200.mainConfig.CommonConfig.AutoRequest { s1200.status = typex.DEV_UP return nil } go func(ctx context.Context) { // 数据缓冲区,最大4KB dataBuffer := make([]byte, common.T_4KB) - s1200.driver.Read([]byte{}, dataBuffer) //清理缓存 for { select { case <-ctx.Done(): @@ -105,12 +127,9 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { { } } - if s1200.driver == nil { - return - } s1200.lock.Lock() // CMD 参数无用 - n, err := s1200.driver.Read([]byte(""), dataBuffer) + n, err := s1200.Read([]byte(""), dataBuffer) s1200.lock.Unlock() if err != nil { glogger.GLogger.Error(err) @@ -132,37 +151,25 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { // 从设备里面读数据出来 func (s1200 *s1200plc) OnRead(cmd []byte, data []byte) (int, error) { - return s1200.driver.Read(cmd, data) + return s1200.Read(cmd, data) } // 把数据写入设备 // // db.Address:int, db.Start:int, db.Size:int, rData[] -// [ -// -// { -// "tag":"V", -// "address":1, -// "start":1, -// "size":1, -// "value":"AAECAwQ=" -// } -// -// ] + func (s1200 *s1200plc) OnWrite(cmd []byte, data []byte) (int, error) { - blocks := []common.S1200Block{} + blocks := []S1200Block{} if err := json.Unmarshal(data, &blocks); err != nil { return 0, err } - return s1200.driver.Write(cmd, data) + return s1200.Write(cmd, data) } // 设备当前状态 func (s1200 *s1200plc) Status() typex.DeviceState { - if s1200.driver != nil { - if s1200.driver.State() == typex.DRIVER_UP { - return typex.DEV_UP - } + if s1200.client != nil { + return typex.DEV_UP } return typex.DEV_DOWN @@ -174,9 +181,6 @@ func (s1200 *s1200plc) Stop() { if s1200.CancelCTX != nil { s1200.CancelCTX() } - if s1200.driver != nil { - s1200.driver.Stop() - } } // 设备属性,是一系列属性描述 @@ -196,7 +200,7 @@ func (s1200 *s1200plc) SetState(status typex.DeviceState) { // 驱动 func (s1200 *s1200plc) Driver() typex.XExternalDriver { - return s1200.driver + return nil } func (s1200 *s1200plc) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { @@ -205,3 +209,77 @@ func (s1200 *s1200plc) OnDCACall(UUID string, Command string, Args interface{}) func (s1200 *s1200plc) OnCtrl(cmd []byte, args []byte) ([]byte, error) { return []byte{}, nil } +func (s1200 *s1200plc) Write(cmd []byte, data []byte) (int, error) { + blocks := []S1200Block{} + if err := json.Unmarshal(data, &blocks); err != nil { + return 0, err + } + // + for _, block := range blocks { + hexV, _ := hex.DecodeString(block.Value) + if err := s1200.client.AGWriteDB( + *block.Address, + *block.Start, + *block.Size, + hexV, + ); err != nil { + return 0, err + } + } + return 0, nil +} + +// 字节格式:[dbNumber1, start1, size1, dbNumber2, start2, size2] +// 读: db --> dbNumber, start, size, buffer[] +var rData = [common.T_2KB]byte{} // 一次最大接受2KB数据 + +func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { + values := []S1200Block{} + for _, db := range s1200.mainConfig.Blocks { + //DB 4字节 + if db.Type == "DB" { + // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 + if err := s1200.client.AGReadDB(*db.Address, *db.Start, *db.Size, rData[:]); err != nil { + return 0, err + } + count := db.Size + if *db.Size*2 > 2000 { + *count = 2000 + } + values = append(values, S1200Block{ + Tag: db.Tag, + Address: db.Address, + Type: db.Type, + Start: db.Start, + Size: db.Size, + Value: hex.EncodeToString(rData[:*count]), + }) + } + // + if db.Type == "MB" { + // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 + if err := s1200.client.AGReadMB(*db.Start, *db.Size, rData[:]); err != nil { + return 0, err + } + count := db.Size + if *db.Size*2 > 2000 { + *count = 2000 + } + values = append(values, S1200Block{ + Tag: db.Tag, + Type: db.Type, + Address: db.Address, + Start: db.Start, + Size: db.Size, + Value: hex.EncodeToString(rData[:*count]), + }) + } + if *db.Frequency < 100 { + *db.Frequency = 100 // 不能太快 + } + time.Sleep(time.Duration(*db.Frequency) * time.Millisecond) + } + bytes, _ := json.Marshal(values) + copy(data, bytes) + return len(bytes), nil +} diff --git a/driver/siemens_s1200_driver.go b/driver/siemens_s1200_driver.go deleted file mode 100644 index 5b539cf04..000000000 --- a/driver/siemens_s1200_driver.go +++ /dev/null @@ -1,165 +0,0 @@ -package driver - -import ( - "encoding/hex" - "encoding/json" - "time" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/typex" - - "github.com/robinson/gos7" -) - -/* -* -* 西门子s1200驱动 -* - */ -type siemens_s1200_driver struct { - state typex.DriverState - s7client gos7.Client - device *typex.Device - RuleEngine typex.RuleX - dbs []common.S1200Block // PLC 的DB块 -} - -func NewS1200Driver(d *typex.Device, - e typex.RuleX, - s7client gos7.Client, - dbs []common.S1200Block) typex.XExternalDriver { - return &siemens_s1200_driver{ - state: typex.DRIVER_STOP, - device: d, - RuleEngine: e, - s7client: s7client, - dbs: dbs, - } -} - -func (s1200 *siemens_s1200_driver) Test() error { - _, err := s1200.s7client.GetCPUInfo() - if err != nil { - glogger.GLogger.Error(err) - return err - } - return nil -} - -// 读取配置 -func (s1200 *siemens_s1200_driver) Init(_ map[string]string) error { - return nil -} - -func (s1200 *siemens_s1200_driver) Work() error { - return nil -} - -func (s1200 *siemens_s1200_driver) State() typex.DriverState { - _, err := s1200.s7client.PLCGetStatus() - if err != nil { - glogger.GLogger.Error(err) - return typex.DRIVER_STOP - } - return typex.DRIVER_UP -} - -// 字节格式:[dbNumber1, start1, size1, dbNumber2, start2, size2] -// 读: db --> dbNumber, start, size, buffer[] -var rData = [common.T_2KB]byte{} // 一次最大接受2KB数据 - -func (s1200 *siemens_s1200_driver) Read(cmd []byte, data []byte) (int, error) { - values := []common.S1200Block{} - for _, db := range s1200.dbs { - //DB 4字节 - if db.Type == "DB" { - // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 - if err := s1200.s7client.AGReadDB(db.Address, db.Start, db.Size, rData[:]); err != nil { - return 0, err - } - count := db.Size - if db.Size*2 > 2000 { - count = 2000 - } - values = append(values, common.S1200Block{ - Tag: db.Tag, - Address: db.Address, - Type: db.Type, - Start: db.Start, - Size: db.Size, - Value: hex.EncodeToString(rData[:count]), - }) - } - // - if db.Type == "MB" { - // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 - if err := s1200.s7client.AGReadMB(db.Start, db.Size, rData[:]); err != nil { - return 0, err - } - count := db.Size - if db.Size*2 > 2000 { - count = 2000 - } - values = append(values, common.S1200Block{ - Tag: db.Tag, - Type: db.Type, - Address: db.Address, - Start: db.Start, - Size: db.Size, - Value: hex.EncodeToString(rData[:count]), - }) - } - if db.Frequency < 100 { - db.Frequency = 100 // 不能太快 - } - time.Sleep(time.Duration(db.Frequency) * time.Millisecond) - } - bytes, _ := json.Marshal(values) - copy(data, bytes) - return len(bytes), nil -} - -// db.Address:int, db.Start:int, db.Size:int, rData[] -// [ -// -// { -// "tag":"V", -// "address":1, -// "start":1, -// "size":1, -// "value":"AAECAwQ=" -// } -// -// ] -func (s1200 *siemens_s1200_driver) Write(cmd []byte, data []byte) (int, error) { - blocks := []common.S1200Block{} - if err := json.Unmarshal(data, &blocks); err != nil { - return 0, err - } - // - for _, block := range blocks { - hexV, _ := hex.DecodeString(block.Value) - if err := s1200.s7client.AGWriteDB( - block.Address, - block.Start, - block.Size, - hexV, - ); err != nil { - return 0, err - } - } - return 0, nil -} - -func (s1200 *siemens_s1200_driver) DriverDetail() typex.DriverDetail { - return typex.DriverDetail{ - Name: "SIEMENS_s1200", - Type: "TCP", - Description: "SIEMENS s1200 系列 PLC 驱动", - } -} - -func (s1200 *siemens_s1200_driver) Stop() error { - return nil -} diff --git a/engine/load_device.go b/engine/load_device.go index 8222188a8..caea9cbc2 100644 --- a/engine/load_device.go +++ b/engine/load_device.go @@ -95,7 +95,7 @@ func (e *RuleEngine) loadDevices(abstractDevice typex.XDevice, deviceInfo *typex config := e.GetDevice(deviceInfo.UUID).Config if config == nil { e.RemoveDevice(deviceInfo.UUID) - err := fmt.Errorf("device [%v] config is nil", deviceInfo.Name) + err := fmt.Errorf("Device [%v] config is nil", deviceInfo.Name) return err } if err := abstractDevice.Init(deviceInfo.UUID, config); err != nil { @@ -103,14 +103,14 @@ func (e *RuleEngine) loadDevices(abstractDevice typex.XDevice, deviceInfo *typex return err } startDevice(abstractDevice, e, ctx, cancelCTX) - glogger.GLogger.Infof("device [%v, %v] load successfully", deviceInfo.Name, deviceInfo.UUID) + glogger.GLogger.Infof("Device [%v, %v] load successfully", deviceInfo.Name, deviceInfo.UUID) return nil } func startDevice(abstractDevice typex.XDevice, e *RuleEngine, ctx context.Context, cancelCTX context.CancelFunc) error { if err := abstractDevice.Start(typex.CCTX{Ctx: ctx, CancelCTX: cancelCTX}); err != nil { - glogger.GLogger.Error("abstractDevice start error:", err) + glogger.GLogger.Error("Device start error:", err) return err } // LoadNewestDevice diff --git a/typex/version.go b/typex/version.go index 9760373fd..7a7a8eb4d 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-07 13:05:36", + ReleaseTime: "2023-12-08 15:06:29", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-4959ee5a7ac722a +** Version: v0.6.4-c453e9cd189b5e6 ** Document: https://hootrhino.github.io ` From 1678a59515cc7dc62b0f21025df2b59821114e87 Mon Sep 17 00:00:00 2001 From: Jane Date: Sat, 9 Dec 2023 12:44:39 +0800 Subject: [PATCH 099/138] Bugfix/jane/crontask (#213) * fix: process may cause NPE Co-authored-by: liyexin --- component/cron_task/constant.go | 15 +++++-- component/cron_task/cron_manager.go | 38 +----------------- component/cron_task/docs/docs.go | 39 +++++-------------- component/cron_task/docs/swagger.json | 39 +++++-------------- component/cron_task/docs/swagger.yaml | 35 +++++------------ component/cron_task/process_manager.go | 10 ++--- .../rulex_api_server/apis/crontask_api.go | 6 +-- .../rulex_api_server/dto/crontask_dto.go | 10 ++--- component/rulex_api_server/model/model.go | 14 +++---- .../service/crontask_service.go | 16 +++++--- main.go | 8 ++++ 11 files changed, 79 insertions(+), 151 deletions(-) diff --git a/component/cron_task/constant.go b/component/cron_task/constant.go index 92338b5de..5a908cfe1 100644 --- a/component/cron_task/constant.go +++ b/component/cron_task/constant.go @@ -2,12 +2,19 @@ package cron_task // CRON_TASK_TYPE const ( - CRON_TASK_TYPE_LINUX_SHELL = 1 - CRON_TASK_TYPE_WINDOWS_CMD = CRON_TASK_TYPE_LINUX_SHELL + 1 + CRON_TASK_TYPE_LINUX_SHELL = "LINUX_SHELL" ) +// CRON +const LINUX_SHELL = "/bin/bash" + const PERM_0777 = 0777 -const CRON_ASSETS = "cron_assets" +// CRON_RESULT_STATUS +const ( + CRON_RESULT_STATUS_RUNNING = "RUNNING" + CRON_RESULT_STATUS_END = "END" +) -const CRON_LOGS = "cron_logs" +var CRON_TASK_EANBLE = true +var CRON_TASK_DISABLE = false diff --git a/component/cron_task/cron_manager.go b/component/cron_task/cron_manager.go index 02b0ea089..78702ffa5 100644 --- a/component/cron_task/cron_manager.go +++ b/component/cron_task/cron_manager.go @@ -4,7 +4,6 @@ import ( "os" "os/exec" "path" - "path/filepath" "strconv" "sync" "time" @@ -46,39 +45,6 @@ func NewCronManager() *CronManager { processManager: NewProcessManager(), mtx: sync.Mutex{}, } - // 每天0点10分清理日志 - engine.AddFunc("0 10 0 * * *", func() { - thirtyDaysAgo := time.Now().AddDate(0, 0, -30) - // 指定文件夹路径 - folderPath := "cron_logs" - // 遍历文件夹下的所有文件 - err := filepath.Walk(folderPath, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - // 检查是否为文件夹 - if info.IsDir() { - // 解析文件夹名称为日期 - dirName := filepath.Base(path) - date, err := time.Parse("2006-01-02", dirName) - if err != nil { - return err - } - - // 检查是否为 30 天前的文件夹 - if date.Before(thirtyDaysAgo) { - // 删除文件夹及其内容 - err := os.RemoveAll(path) - if err != nil { - return err - } - glogger.GLogger.Info("Deleted folder: %s", path) - } - } - return nil - }) - glogger.GLogger.Error("clean cron logs failed, err=", err) - }) engine.Start() return &manager } @@ -102,7 +68,7 @@ func (m *CronManager) AddTask(task model.MCronTask) error { // create a task execute log record result := model.MCronResult{ TaskUuid: task.UUID, - Status: "1", + Status: CRON_RESULT_STATUS_RUNNING, StartTime: time.Now(), } saveResults(&result) @@ -127,7 +93,7 @@ func (m *CronManager) AddTask(task model.MCronTask) error { taskLogger.Info("---------------End task---------------") result.EndTime = time.Now() - result.Status = "2" + result.Status = CRON_RESULT_STATUS_END result.ExitCode = strconv.Itoa(exitCode) saveResults(&result) }) diff --git a/component/cron_task/docs/docs.go b/component/cron_task/docs/docs.go index 4a3d48a67..85dd34328 100644 --- a/component/cron_task/docs/docs.go +++ b/component/cron_task/docs/docs.go @@ -9,15 +9,9 @@ const docTemplate = `{ "info": { "description": "{{escape .Description}}", "title": "{{.Title}}", - "termsOfService": "http://swagger.io/terms/", "contact": { "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "support@swagger.io" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + "url": "https://github.com/hootrhino/rulex" }, "version": "{{.Version}}" }, @@ -262,19 +256,16 @@ const docTemplate = `{ "type": "string" } }, - "isRoot": { - "description": "0-false 1-true", - "type": "string" - }, "name": { "type": "string" }, "script": { + "description": "脚本内容,base64编码", "type": "string" }, "taskType": { - "description": "1-shell 2-cmd", - "type": "integer" + "description": "CRON_TASK_TYPE", + "type": "string" } } }, @@ -298,19 +289,16 @@ const docTemplate = `{ "type": "string" } }, - "isRoot": { - "description": "0-false 1-true", - "type": "string" - }, "name": { "type": "string" }, "script": { + "description": "脚本内容,base64编码", "type": "string" }, "taskType": { - "description": "1-shell 2-cmd", - "type": "integer" + "description": "CRON_TASK_TYPE", + "type": "string" }, "uuid": { "type": "string" @@ -333,15 +321,6 @@ const docTemplate = `{ } } } - }, - "securityDefinitions": { - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" } }` @@ -351,8 +330,8 @@ var SwaggerInfo = &swag.Spec{ Host: "", BasePath: "/api/v1", Schemes: []string{}, - Title: "Swagger Example API", - Description: "This is a sample server celler server.", + Title: "Rulex API", + Description: "Rulex Swagger API", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, LeftDelim: "{{", diff --git a/component/cron_task/docs/swagger.json b/component/cron_task/docs/swagger.json index 32c10c07c..7b46b0c7a 100644 --- a/component/cron_task/docs/swagger.json +++ b/component/cron_task/docs/swagger.json @@ -1,17 +1,11 @@ { "swagger": "2.0", "info": { - "description": "This is a sample server celler server.", - "title": "Swagger Example API", - "termsOfService": "http://swagger.io/terms/", + "description": "Rulex Swagger API", + "title": "Rulex API", "contact": { "name": "API Support", - "url": "http://www.swagger.io/support", - "email": "support@swagger.io" - }, - "license": { - "name": "Apache 2.0", - "url": "http://www.apache.org/licenses/LICENSE-2.0.html" + "url": "https://github.com/hootrhino/rulex" }, "version": "1.0" }, @@ -255,19 +249,16 @@ "type": "string" } }, - "isRoot": { - "description": "0-false 1-true", - "type": "string" - }, "name": { "type": "string" }, "script": { + "description": "脚本内容,base64编码", "type": "string" }, "taskType": { - "description": "1-shell 2-cmd", - "type": "integer" + "description": "CRON_TASK_TYPE", + "type": "string" } } }, @@ -291,19 +282,16 @@ "type": "string" } }, - "isRoot": { - "description": "0-false 1-true", - "type": "string" - }, "name": { "type": "string" }, "script": { + "description": "脚本内容,base64编码", "type": "string" }, "taskType": { - "description": "1-shell 2-cmd", - "type": "integer" + "description": "CRON_TASK_TYPE", + "type": "string" }, "uuid": { "type": "string" @@ -326,14 +314,5 @@ } } } - }, - "securityDefinitions": { - "BasicAuth": { - "type": "basic" - } - }, - "externalDocs": { - "description": "OpenAPI", - "url": "https://swagger.io/resources/open-api/" } } \ No newline at end of file diff --git a/component/cron_task/docs/swagger.yaml b/component/cron_task/docs/swagger.yaml index 3e85b6c4a..dd11b16d1 100644 --- a/component/cron_task/docs/swagger.yaml +++ b/component/cron_task/docs/swagger.yaml @@ -12,16 +12,14 @@ definitions: items: type: string type: array - isRoot: - description: 0-false 1-true - type: string name: type: string script: + description: 脚本内容,base64编码 type: string taskType: - description: 1-shell 2-cmd - type: integer + description: CRON_TASK_TYPE + type: string required: - cronExpr - name @@ -39,16 +37,14 @@ definitions: items: type: string type: array - isRoot: - description: 0-false 1-true - type: string name: type: string script: + description: 脚本内容,base64编码 type: string taskType: - description: 1-shell 2-cmd - type: integer + description: CRON_TASK_TYPE + type: string uuid: type: string required: @@ -65,20 +61,12 @@ definitions: - code - msg type: object -externalDocs: - description: OpenAPI - url: https://swagger.io/resources/open-api/ info: contact: - email: support@swagger.io name: API Support - url: http://www.swagger.io/support - description: This is a sample server celler server. - license: - name: Apache 2.0 - url: http://www.apache.org/licenses/LICENSE-2.0.html - termsOfService: http://swagger.io/terms/ - title: Swagger Example API + url: https://github.com/hootrhino/rulex + description: Rulex Swagger API + title: Rulex API version: "1.0" paths: /crontask/create: @@ -102,7 +90,7 @@ paths: summary: 创建定时任务 tags: - crontask - /crontask/delete: + /crontask/del: delete: consumes: - application/json @@ -218,7 +206,4 @@ paths: summary: 更新定时任务 tags: - crontask -securityDefinitions: - BasicAuth: - type: basic swagger: "2.0" diff --git a/component/cron_task/process_manager.go b/component/cron_task/process_manager.go index 083a0484f..439e131fd 100644 --- a/component/cron_task/process_manager.go +++ b/component/cron_task/process_manager.go @@ -31,25 +31,22 @@ func (pm *ProcessManager) RunProcess(file io.Writer, task model.MCronTask) error var command *exec.Cmd args := make([]string, 0) - var name string script, err := base64.StdEncoding.DecodeString(task.Script) if err != nil { glogger.GLogger.Error("parse script failed", err) return err } if task.TaskType == CRON_TASK_TYPE_LINUX_SHELL { - name = "/bin/bash" args = append(args, "-c") args = append(args, string(script)) args = append(args, "bash") // 占据$0位置 if task.Args != nil { args = append(args, *task.Args) // 占据$1位置,此时$@与$1相同 } - } else { return errors.New("unknown taskType") } - command = exec.Command(name, args...) + command = exec.Command(task.Command, args...) command.SysProcAttr = GetSysProcAttr() command.Stderr = file command.Stdout = file @@ -61,10 +58,13 @@ func (pm *ProcessManager) RunProcess(file io.Writer, task model.MCronTask) error } command.Env = envSlice + if err = command.Start(); err != nil { + return err + } pm.runningProcess.Store(task.ID, command) defer pm.runningProcess.Delete(task.ID) - err = command.Run() + err = command.Wait() if err != nil { return err } diff --git a/component/rulex_api_server/apis/crontask_api.go b/component/rulex_api_server/apis/crontask_api.go index db5f599d3..666e3712c 100644 --- a/component/rulex_api_server/apis/crontask_api.go +++ b/component/rulex_api_server/apis/crontask_api.go @@ -47,7 +47,7 @@ func CreateCronTask(c *gin.Context, ruleEngine typex.RuleX) (any, error) { // @Accept json // @Produce json // @Success 200 {object} httpserver.R -// @Router /crontask/delete [delete] +// @Router /crontask/del [delete] func DeleteCronTask(c *gin.Context, ruleEngine typex.RuleX) (any, error) { uuid := c.Query("uuid") err := service.DeleteScheduleTask(uuid) @@ -109,7 +109,7 @@ func StartTask(c *gin.Context, ruleEngine typex.RuleX) (any, error) { // 0. 更新数据库 db := interdb.DB() task := model.MCronTask{} - task.Enable = "1" + task.Enable = &cron_task.CRON_TASK_EANBLE tx := db.Where("uuid = ?", uuid).Updates(&task) if tx.Error != nil { return nil, tx.Error @@ -148,7 +148,7 @@ func StopTask(c *gin.Context, ruleEngine typex.RuleX) (any, error) { // 0. 更新数据库 db := interdb.DB() task := model.MCronTask{} - task.Enable = "0" + task.Enable = &cron_task.CRON_TASK_DISABLE tx := db.Where("uuid = ?", uuid).Updates(&task) if tx.Error != nil { return nil, tx.Error diff --git a/component/rulex_api_server/dto/crontask_dto.go b/component/rulex_api_server/dto/crontask_dto.go index 6bd54f628..9c0615dab 100644 --- a/component/rulex_api_server/dto/crontask_dto.go +++ b/component/rulex_api_server/dto/crontask_dto.go @@ -3,20 +3,18 @@ package dto type CronTaskCreateDTO struct { Name string `form:"name" binding:"required" json:"name"` CronExpr string `form:"cronExpr" binding:"required" json:"cronExpr"` - TaskType int `form:"taskType" binding:"required" json:"taskType"` // 1-shell 2-cmd + TaskType string `form:"taskType" binding:"required" json:"taskType"` // CRON_TASK_TYPE Args *string `form:"args" json:"args"` // "param1 param2 param3" - IsRoot string `form:"isRoot" json:"isRoot"` // 0-false 1-true Env []string `form:"env" json:"env"` // ["A=e1", "B=e2", "C=e3"] - Script string `form:"script" json:"script"` + Script string `form:"script" json:"script"` // 脚本内容,base64编码 } type CronTaskUpdateDTO struct { UUID string `form:"uuid" binding:"required" json:"uuid"` Name string `form:"name" json:"name"` CronExpr string `form:"cronExpr" json:"cronExpr"` - TaskType int `form:"taskType" json:"taskType"` // 1-shell 2-cmd + TaskType string `form:"taskType" json:"taskType"` // CRON_TASK_TYPE Args *string `form:"args" json:"args"` // "param1 param2 param3" - IsRoot string `form:"isRoot" json:"isRoot"` // 0-false 1-true Env []string `form:"env" json:"env"` // ["A=e1", "B=e2", "C=e3"] - Script string `form:"script" json:"script"` + Script string `form:"script" json:"script"` // 脚本内容,base64编码 } diff --git a/component/rulex_api_server/model/model.go b/component/rulex_api_server/model/model.go index 53569b339..4b6ddf02e 100644 --- a/component/rulex_api_server/model/model.go +++ b/component/rulex_api_server/model/model.go @@ -258,15 +258,15 @@ type MCronTask struct { RulexModel UUID string `gorm:"not null; default:''" json:"uuid"` Name string `gorm:"not null;" json:"name"` - CronExpr string `gorm:"not null" json:"cronExpr"` // linux cron standard - Enable string `json:"enable"` // 0-disable 1-enable - TaskType int `json:"taskType"` // 1-shell 目前 - Command string `json:"command"` // 目前不使用,默认都是linux shell + CronExpr string `gorm:"not null" json:"cronExpr"` // quartz cron expr + Enable *bool `json:"enable"` // 是否启用定时任务 + TaskType string `json:"taskType"` // CRON_TASK_TYPE,目前只有LINUX_SHELL + Command string `json:"command"` // 根据TaskType而定,TaskType=LINUX_SHELL时Command=/bin/bash Args *string `json:"args"` // "-param1 -param2 -param3" - IsRoot string `json:"isRoot"` // 0-false 1-true + IsRoot *bool `json:"isRoot"` // 是否使用root用户运行,目前不使用,默认和rulex用户一致 WorkDir string `json:"workDir"` // 目前不使用,默认工作路径和网关工作路径保持一致 Env string `json:"env"` // ["A=e1", "B=e2", "C=e3"] - Script string `json:"script"` // 脚本内容 + Script string `json:"script"` // 脚本内容,base64编码 UpdatedAt time.Time `json:"updatedAt"` } @@ -276,7 +276,7 @@ type MCronTask struct { type MCronResult struct { RulexModel TaskUuid string `gorm:"not null; default:''" json:"taskUuid,omitempty"` - Status string `json:"status"` // 1-running 2-end + Status string `json:"status"` // CRON_RESULT_STATUS ExitCode string `json:"exitCode,omitempty"` // 0-success other-failed LogPath string `json:"logPath,omitempty"` StartTime time.Time `json:"startTime"` diff --git a/component/rulex_api_server/service/crontask_service.go b/component/rulex_api_server/service/crontask_service.go index 2bee589c4..757e71bba 100644 --- a/component/rulex_api_server/service/crontask_service.go +++ b/component/rulex_api_server/service/crontask_service.go @@ -17,10 +17,9 @@ func CreateScheduleTask(data *dto.CronTaskCreateDTO) (*model.MCronTask, error) { UUID: utils.CronTaskUuid(), Name: data.Name, CronExpr: data.CronExpr, - Enable: "0", + Enable: &cron_task.CRON_TASK_DISABLE, TaskType: data.TaskType, Args: data.Args, - IsRoot: data.IsRoot, Script: data.Script, } if data.Env != nil { @@ -30,6 +29,10 @@ func CreateScheduleTask(data *dto.CronTaskCreateDTO) (*model.MCronTask, error) { task.Env = "[]" } + if data.TaskType == cron_task.CRON_TASK_TYPE_LINUX_SHELL { + task.Command = cron_task.LINUX_SHELL + } + tx := db.Create(&task) if tx.Error != nil { return nil, tx.Error @@ -51,7 +54,7 @@ func DeleteScheduleTask(uuid string) error { func ListScheduleTask(task model.MCronTask) (any, error) { db := interdb.DB() var records []model.MCronTask - tx := db.Find(&records) + tx := db.Order("created_at desc").Find(&records) if tx.Error != nil { return nil, tx.Error } @@ -69,17 +72,20 @@ func UpdateScheduleTask(data *dto.CronTaskUpdateDTO) (*model.MCronTask, error) { if tx.RowsAffected == 0 { return nil, errors.New("定时任务不存在") } - if cronTask.Enable == "1" { + if cronTask.Enable != nil && *cronTask.Enable == cron_task.CRON_TASK_DISABLE { return nil, errors.New("请先暂停任务") } task := &model.MCronTask{ Name: data.Name, CronExpr: data.CronExpr, TaskType: data.TaskType, - IsRoot: data.IsRoot, Args: data.Args, } + if data.TaskType == cron_task.CRON_TASK_TYPE_LINUX_SHELL { + task.Command = cron_task.LINUX_SHELL + } + tx = db.Model(&task) if data.Env != nil { marshal, _ := json.Marshal(data.Env) diff --git a/main.go b/main.go index c034cd9ff..6594e28d1 100644 --- a/main.go +++ b/main.go @@ -52,6 +52,14 @@ func init() { typex.DefaultVersion.Arch = arch } +// @title Rulex API +// @version 1.0 +// @description Rulex Swagger API + +// @contact.name API Support +// @contact.url https://github.com/hootrhino/rulex +// @BasePath /api/v1 +// //go:generate bash ./gen_info.sh func main() { app := &cli.App{ From fdd7edcb278fdb477c56489e112c13a8c86a7fee Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 9 Dec 2023 23:45:35 +0800 Subject: [PATCH 100/138] dev: add modbus table api --- component/rulex_api_server/apis/device_api.go | 154 +-------- .../apis/device_data_sheet_api.go | 256 ++++++++++++++ component/rulex_api_server/apis/group_api.go | 5 +- .../apis/user_lua_template_api.go | 9 +- component/rulex_api_server/dto/pager_dto.go | 29 ++ component/rulex_api_server/http_api_server.go | 17 +- .../model/modebus_data_point.go | 30 ++ component/rulex_api_server/model/model.go | 15 +- .../model/siemons_data_point.go | 29 ++ .../model/user_lua_template.go | 1 + component/rulex_api_server/service/dao.go | 47 --- .../service/modbus_data_sheet_service.go | 59 ++++ .../service/siemons_data_sheet_service.go | 58 ++++ .../service/table_count_service.go | 40 +++ device/generic_modbus_device.go | 72 ++-- device/generic_modbus_excel_device.go | 315 ------------------ device/generic_modbus_excel_device.md | 115 ------- device/s1200plc_device.go | 63 ++-- driver/modbus_rtu_driver.go | 3 +- driver/modbus_tcp_driver.go | 3 +- test/apps/http_post_demo.lua | 2 +- test/data/test-modbus-sheet.xlsx | Bin 0 -> 11914 bytes typex/version.go | 4 +- 23 files changed, 623 insertions(+), 703 deletions(-) create mode 100644 component/rulex_api_server/apis/device_data_sheet_api.go create mode 100644 component/rulex_api_server/dto/pager_dto.go create mode 100644 component/rulex_api_server/model/modebus_data_point.go create mode 100644 component/rulex_api_server/model/siemons_data_point.go create mode 100644 component/rulex_api_server/service/modbus_data_sheet_service.go create mode 100644 component/rulex_api_server/service/siemons_data_sheet_service.go create mode 100644 component/rulex_api_server/service/table_count_service.go delete mode 100644 device/generic_modbus_excel_device.go delete mode 100644 device/generic_modbus_excel_device.md create mode 100644 test/data/test-modbus-sheet.xlsx diff --git a/component/rulex_api_server/apis/device_api.go b/component/rulex_api_server/apis/device_api.go index fd1588fca..8096845f7 100644 --- a/component/rulex_api_server/apis/device_api.go +++ b/component/rulex_api_server/apis/device_api.go @@ -1,18 +1,13 @@ package apis import ( - "errors" "fmt" - "io" - "strconv" common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/component/rulex_api_server/server" "github.com/hootrhino/rulex/component/rulex_api_server/service" - "github.com/xuri/excelize/v2" - "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" @@ -116,18 +111,18 @@ func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { } // 检查是否通用Modbus设备.需要同步删除点位表记录 - if Mdev.Type == "GENERIC_MODBUS_POINT_EXCEL" { - if err := service.DeleteModbusPointAndDevice(uuid); err != nil { + if Mdev.Type == "GENERIC_MODBUS" { + if err := service.DeleteAllModbusPointByDevice(uuid); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } - } else { - if err := service.DeleteDevice(uuid); err != nil { + } + if Mdev.Type == "S1200PLC" { + if err := service.DeleteAllModbusPointByDevice(uuid); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } } - old := ruleEngine.GetDevice(uuid) if old != nil { if old.Device.Status() == typex.DEV_UP { @@ -246,142 +241,3 @@ func UpdateDevice(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Ok()) } - -// ModbusPoints 获取modbus_excel类型的点位数据 -func ModbusPoints(c *gin.Context, ruleEngine typex.RuleX) { - deviceUuid := c.GetString("deviceUuid") - list, err := service.AllModbusPointByDeviceUuid(deviceUuid) - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - c.JSON(common.HTTP_OK, common.OkWithData(list)) -} - -// UpdateModbusPoint 更新modbus_excel类型的点位数据 -func UpdateModbusPoint(c *gin.Context, ruleEngine typex.RuleX) { - type Form struct { - Id uint - DeviceUuid string `json:"deviceUuid" gorm:"not null"` - Tag string `json:"tag" gorm:"not null"` - Function int `json:"function" gorm:"not null"` - SlaverId byte `json:"slaverId" gorm:"not null"` - StartAddress uint16 `json:"startAddress" gorm:"not null"` - Quality uint16 `json:"quality" gorm:"not null"` - } - - form := Form{} - if err := c.ShouldBindJSON(&form); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - - err := service.UpdateModbusPoint(model.MModbusPointPosition{ - RulexModel: model.RulexModel{ - ID: form.Id, - }, - DeviceUuid: form.DeviceUuid, - Tag: form.Tag, - Function: form.Function, - SlaverId: form.SlaverId, - StartAddress: form.StartAddress, - Quality: form.Quality, - }) - - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - - c.JSON(common.HTTP_OK, common.Ok()) - -} - -// ModbusSheetImport 上传Excel文件 -func ModbusSheetImport(c *gin.Context, ruleEngine typex.RuleX) { - // 解析 multipart/form-data 类型的请求体 - err := c.Request.ParseMultipartForm(32 << 20) // 限制上传文件大小为 512MB - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - - // 获取上传的文件 - file, header, err := c.Request.FormFile("file") - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - defer file.Close() - - deviceUuid := c.Request.Form.Get("deviceUuid") - - // 检查文件类型是否为 Excel - contentType := header.Header.Get("Content-Type") - if contentType != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" && - contentType != "application/vnd.ms-excel" { - c.JSON(common.HTTP_OK, common.Error("上传的文件必须是 Excel 格式")) - return - } - - // 判断文件大小是否符合要求(1MB) - if header.Size > 1024*1024 { - c.JSON(common.HTTP_OK, common.Error("Excel file size cannot be greater than 1MB")) - return - } - - list, err := parseModbusPointExcel(file, "Sheet1", deviceUuid) - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - - err = service.InsertModbusPointPosition(list) - if err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - c.JSON(common.HTTP_OK, common.Ok()) -} - -func parseModbusPointExcel(r io.Reader, - sheetName string, - deviceUuid string) (list []model.MModbusPointPosition, err error) { - excelFile, err := excelize.OpenReader(r) - if err != nil { - return nil, err - } - defer func() { - excelFile.Close() - }() - // 读取表格 - rows, err := excelFile.GetRows(sheetName) - if err != nil { - return nil, err - } - // 判断首行标头 - // |Tag|Function|SlaverId|StartAddress|Quality| - if rows[0][0] != "Tag" || rows[0][1] != "Function" || rows[0][2] != "SlaverId" || rows[0][3] != "StartAddress" || rows[0][4] != "Quality" { - return nil, errors.New("表头不符合要求") - } - - list = make([]model.MModbusPointPosition, 0) - - for i := 1; i < len(rows); i++ { - row := rows[i] - function, _ := strconv.Atoi(row[1]) - slaverId, _ := strconv.ParseInt(row[2], 10, 8) - address, _ := strconv.ParseUint(row[3], 10, 16) - quantity, _ := strconv.ParseUint(row[3], 10, 16) - model := model.MModbusPointPosition{ - DeviceUuid: deviceUuid, - Tag: row[0], - Function: function, - SlaverId: byte(slaverId), - StartAddress: uint16(address), - Quality: uint16(quantity), - } - list = append(list, model) - } - return list, nil -} diff --git a/component/rulex_api_server/apis/device_data_sheet_api.go b/component/rulex_api_server/apis/device_data_sheet_api.go new file mode 100644 index 000000000..c7b73b8a2 --- /dev/null +++ b/component/rulex_api_server/apis/device_data_sheet_api.go @@ -0,0 +1,256 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package apis + +import ( + "errors" + "io" + "strconv" + + "github.com/gin-gonic/gin" + "github.com/hootrhino/rulex/component/interdb" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" + "github.com/jinzhu/copier" + "github.com/xuri/excelize/v2" +) + +type ModbusPointVo struct { + UUID string `json:"uuid,omitempty"` + DeviceUUID string `json:"device_uuid"` + Tag string `json:"tag"` + Alias string `json:"alias"` + Function int `json:"function"` + SlaverId byte `json:"slaverId"` + Address uint16 `json:"address"` + Frequency int64 `json:"frequency"` + Quantity uint16 `json:"quantity"` +} + +/* +* +* 特殊设备需要和外界交互,这里主要就是一些设备的点位表导入导出等支持 +* + */ + +// ModbusPoints 获取modbus_excel类型的点位数据 +func ModbusPointsExport(c *gin.Context, ruleEngine typex.RuleX) { + c.JSON(common.HTTP_OK, common.Ok()) +} + +// 分页获取 +// SELECT * FROM `m_modbus_data_points` WHERE +// `m_modbus_data_points`.`device_uuid` = "DEVICEDQNLO8" +// ORDER BY +// created_at DESC LIMIT 2 OFFSET 10 +func ModbusSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { + pager, err := service.ReadPageRequest(c) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + deviceUuid, _ := c.GetQuery("device_uuid") + db := interdb.DB() + tx := db.Scopes(service.Paginate(*pager)) + var count int64 + err1 := interdb.DB().Model(&model.MModbusDataPoint{}).Count(&count).Error + if err1 != nil { + c.JSON(common.HTTP_OK, common.Error400(err1)) + return + } + var records []model.MModbusDataPoint + result := tx.Order("created_at DESC").Find(&records, + &model.MModbusDataPoint{DeviceUuid: deviceUuid}) + if result.Error != nil { + c.JSON(common.HTTP_OK, common.Error400(result.Error)) + return + } + Result := service.WrapPageResult(*pager, records, count) + c.JSON(common.HTTP_OK, common.OkWithData(Result)) +} + +/* +* +* 删除单行 +* + */ +func ModbusSheetDelete(c *gin.Context, ruleEngine typex.RuleX) { + type Form struct { + UUIDs []string `json:"uuids"` + DeviceUUID string `json:"device_uuid"` + } + form := Form{} + if Error := c.ShouldBindJSON(&form); Error != nil { + c.JSON(common.HTTP_OK, common.Error400(Error)) + return + } + err := service.DeleteModbusPointByDevice(form.UUIDs, form.DeviceUUID) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) + +} + +/* +* +* 更新点位表 +* + */ +func ModbusSheetUpdate(c *gin.Context, ruleEngine typex.RuleX) { + ModbusDataPoints := []ModbusPointVo{} + err := c.ShouldBindJSON(&ModbusDataPoints) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + for _, ModbusDataPoint := range ModbusDataPoints { + if ModbusDataPoint.UUID == "" { + NewRow := model.MModbusDataPoint{} + copier.Copy(&NewRow, &ModbusDataPoint) + service.InsertModbusPointPosition(NewRow) + } else { + OldRow := model.MModbusDataPoint{ + DeviceUuid: ModbusDataPoint.DeviceUUID, + UUID: ModbusDataPoint.UUID, + } + copier.Copy(&OldRow, &ModbusDataPoint) + service.UpdateModbusPoint(OldRow) + } + } + c.JSON(common.HTTP_OK, common.Ok()) + +} + +// ModbusSheetImport 上传Excel文件 +func ModbusSheetImport(c *gin.Context, ruleEngine typex.RuleX) { + // 解析 multipart/form-data 类型的请求体 + err := c.Request.ParseMultipartForm(1024 * 1024 * 10) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + + // 获取上传的文件 + file, header, err := c.Request.FormFile("file") + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + defer file.Close() + deviceUuid := c.Request.Form.Get("device_uuid") + type DeviceDto struct { + UUID string + Name string + Type string + } + Device := DeviceDto{} + errDb := interdb.DB().Table("m_devices"). + Where("uuid=?", deviceUuid).Find(&Device).Error + if errDb != nil { + c.JSON(common.HTTP_OK, common.Error400(errDb)) + return + } + if Device.Type != typex.GENERIC_MODBUS.String() { + c.JSON(common.HTTP_OK, + common.Error("Invalid Device Type, Only Support Import Modbus Device")) + return + } + contentType := header.Header.Get("Content-Type") + if contentType != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" && + contentType != "application/vnd.ms-excel" { + c.JSON(common.HTTP_OK, common.Error("File Must be Excel Sheet")) + return + } + // 判断文件大小是否符合要求(10MB) + if header.Size > 1024*1024*10 { + c.JSON(common.HTTP_OK, common.Error("Excel file size cannot be greater than 10MB")) + return + } + list, err := parseModbusPointExcel(file, "Sheet1", deviceUuid) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + if err = service.InsertModbusPointPositions(list); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) +} + +func parseModbusPointExcel( + r io.Reader, + sheetName string, + deviceUuid string) (list []model.MModbusDataPoint, err error) { + excelFile, err := excelize.OpenReader(r) + if err != nil { + return nil, err + } + defer func() { + excelFile.Close() + }() + // 读取表格 + rows, err := excelFile.GetRows(sheetName) + if err != nil { + return nil, err + } + // 判断首行标头 + // tag, alias, function, frequency, slaverId, startAddress, quality + err1 := errors.New("invalid Sheet Header") + if len(rows[0]) < 7 { + return nil, err1 + } + if rows[0][0] != "tag" || + rows[0][1] != "alias" || + rows[0][2] != "function" || + rows[0][3] != "frequency" || + rows[0][4] != "slaverId" || + rows[0][5] != "startAddress" || + rows[0][6] != "quality" { + return nil, err1 + } + + list = make([]model.MModbusDataPoint, 0) + // tag, alias, function, frequency, slaverId, startAddress, quality + for i := 1; i < len(rows); i++ { + row := rows[i] + tag := row[0] + alias := row[1] + function, _ := strconv.ParseInt(row[2], 10, 8) + frequency, _ := strconv.ParseInt(row[3], 10, 8) + slaverId, _ := strconv.ParseInt(row[4], 10, 8) + address, _ := strconv.ParseUint(row[5], 10, 16) + quantity, _ := strconv.ParseUint(row[6], 10, 16) + model := model.MModbusDataPoint{ + UUID: utils.MakeUUID("MDTB"), + DeviceUuid: deviceUuid, + Tag: tag, + Alias: alias, + Function: int(function), + SlaverId: byte(slaverId), + Address: uint16(address), + Frequency: frequency, //ms + Quantity: uint16(quantity), + } + list = append(list, model) + } + return list, nil +} diff --git a/component/rulex_api_server/apis/group_api.go b/component/rulex_api_server/apis/group_api.go index 364383d1a..18771e785 100644 --- a/component/rulex_api_server/apis/group_api.go +++ b/component/rulex_api_server/apis/group_api.go @@ -33,8 +33,9 @@ func CreateGroup(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } - if !utils.SContains([]string{"VISUAL", "DEVICE"}, vvo.Type) { - c.JSON(common.HTTP_OK, common.Error400(fmt.Errorf("invalid type [%s]", vvo.Type))) + if !utils.SContains([]string{"VISUAL", "DEVICE", "USER_LUA_TEMPLATE"}, vvo.Type) { + c.JSON(common.HTTP_OK, common.Error400(fmt.Errorf("invalid group type [%s]", vvo.Type))) + return } Model := model.MGenericGroup{ UUID: utils.GroupUuid(), diff --git a/component/rulex_api_server/apis/user_lua_template_api.go b/component/rulex_api_server/apis/user_lua_template_api.go index 22c9154b3..3fbe1f7a4 100644 --- a/component/rulex_api_server/apis/user_lua_template_api.go +++ b/component/rulex_api_server/apis/user_lua_template_api.go @@ -12,8 +12,8 @@ import ( type UserLuaTemplateVo struct { Gid string `json:"gid,omitempty"` // 分组ID UUID string `json:"uuid,omitempty"` // 名称 - Label string `json:"label"` //快捷代码名称 - Apply string `json:"apply"` //快捷代码 + Label string `json:"label"` // 快捷代码名称 + Apply string `json:"apply"` // 快捷代码 Type string `json:"type"` // 类型 固定为function类型detail Detail string `json:"detail"` } @@ -41,6 +41,7 @@ func CreateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { Type: "function", Apply: form.Apply, Detail: form.Detail, + Gid: form.Gid, } if err := service.InsertUserLuaTemplate(MUserLuaTemplate); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) @@ -75,6 +76,7 @@ func UpdateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { Type: form.Type, Apply: form.Apply, Detail: form.Detail, + Gid: form.Gid, } if err := service.UpdateUserLuaTemplate(MUserLuaTemplate); err != nil { @@ -140,6 +142,7 @@ func SearchUserLuaTemplateGroup(c *gin.Context, ruleEngine typex.RuleX) { Type: vv.Type, Apply: vv.Apply, Detail: vv.Detail, + Gid: vv.Gid, }) } c.JSON(common.HTTP_OK, common.OkWithData(visuals)) @@ -159,6 +162,7 @@ func ListUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { Type: vv.Type, Apply: vv.Apply, Detail: vv.Detail, + Gid: vv.Gid, } Group := service.GetUserLuaTemplateGroup(vv.UUID) if Group.UUID != "" { @@ -188,6 +192,7 @@ func ListUserLuaTemplateByGroup(c *gin.Context, ruleEngine typex.RuleX) { Type: vv.Type, Apply: vv.Apply, Detail: vv.Detail, + Gid: vv.Gid, } Group := service.GetUserLuaTemplateGroup(vv.UUID) Vo.Gid = Group.UUID diff --git a/component/rulex_api_server/dto/pager_dto.go b/component/rulex_api_server/dto/pager_dto.go new file mode 100644 index 000000000..a20a7a52e --- /dev/null +++ b/component/rulex_api_server/dto/pager_dto.go @@ -0,0 +1,29 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package dto + +type PageRequest struct { + Current int `json:"current,omitempty"` + Size int `json:"size,omitempty"` + SearchCount int `json:"searchCount,omitempty"` +} + +type PageResult struct { + Current int `json:"current"` + Size int `json:"size"` + Total int `json:"total"` + Records any `json:"records"` +} diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index c8becddb0..1c1e54d5b 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -199,8 +199,6 @@ func (hs *ApiServerPlugin) Init(config *ini.Section) error { &model.MDevice{}, &model.MGoods{}, &model.MApp{}, - &model.MAiBase{}, - &model.MModbusPointPosition{}, &model.MVisual{}, &model.MGenericGroup{}, &model.MGenericGroupRelation{}, @@ -214,6 +212,8 @@ func (hs *ApiServerPlugin) Init(config *ini.Section) error { &model.MHwPort{}, &model.MInternalNotify{}, &model.MUserLuaTemplate{}, + &model.MModbusDataPoint{}, + &model.MSiemensDataPoint{}, ) // 初始化所有预制参数 server.DefaultApiServer.InitializeGenericOSData() @@ -332,13 +332,20 @@ func (hs *ApiServerPlugin) LoadRoute() { deviceApi.PUT(("/update"), server.AddRoute(apis.UpdateDevice)) deviceApi.DELETE(("/del"), server.AddRoute(apis.DeleteDevice)) deviceApi.GET(("/detail"), server.AddRoute(apis.DeviceDetail)) - deviceApi.POST(("/modbus/sheetImport"), server.AddRoute(apis.ModbusSheetImport)) - deviceApi.PUT(("/modbus/point"), server.AddRoute(apis.UpdateModbusPoint)) - deviceApi.GET(("/modbus"), server.AddRoute(apis.ModbusPoints)) deviceApi.GET("/group", server.AddRoute(apis.ListDeviceGroup)) deviceApi.GET("/listByGroup", server.AddRoute(apis.ListDeviceByGroup)) } + // Modbus 点位表 + modbusApi := server.RouteGroup(server.ContextUrl("/modbus_data_sheet")) + { + modbusApi.POST(("/import"), server.AddRoute(apis.ModbusSheetImport)) + modbusApi.GET(("/export"), server.AddRoute(apis.ModbusPointsExport)) + modbusApi.GET(("/list"), server.AddRoute(apis.ModbusSheetPageList)) + modbusApi.POST(("/update"), server.AddRoute(apis.ModbusSheetUpdate)) + modbusApi.DELETE(("/delIds"), server.AddRoute(apis.ModbusSheetDelete)) + modbusApi.DELETE(("/delAll"), server.AddRoute(apis.ModbusSheetDelete)) + } // ---------------------------------------------------------------------------------------------- // APP diff --git a/component/rulex_api_server/model/modebus_data_point.go b/component/rulex_api_server/model/modebus_data_point.go new file mode 100644 index 000000000..266abcbc8 --- /dev/null +++ b/component/rulex_api_server/model/modebus_data_point.go @@ -0,0 +1,30 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package model + +// modbus数据点位表 +type MModbusDataPoint struct { + RulexModel + UUID string `gorm:"not null" json:"uuid"` + DeviceUuid string `gorm:"not null" json:"device_uuid"` + Tag string `gorm:"not null" json:"tag"` + Alias string `gorm:"not null" json:"alias"` + Function int `gorm:"not null" json:"function"` + SlaverId byte `gorm:"not null" json:"slaver_id"` + Address uint16 `gorm:"not null" json:"address"` + Frequency int64 `gorm:"not null" json:"frequency"` + Quantity uint16 `gorm:"not null" json:"quantity"` +} diff --git a/component/rulex_api_server/model/model.go b/component/rulex_api_server/model/model.go index 4b6ddf02e..4d224fa13 100644 --- a/component/rulex_api_server/model/model.go +++ b/component/rulex_api_server/model/model.go @@ -8,8 +8,8 @@ import ( ) type RulexModel struct { - ID uint `gorm:"primarykey"` - CreatedAt time.Time + ID uint `gorm:"primarykey" json:"id"` + CreatedAt time.Time `json:"created_at"` } type StringList []string @@ -168,17 +168,6 @@ type MAiBase struct { Description string `gorm:"not null"` } -// MModbusPointPosition modbus数据点位 -type MModbusPointPosition struct { - RulexModel - DeviceUuid string `json:"deviceUuid" gorm:"not null"` - Tag string `json:"tag" gorm:"not null"` - Function int `json:"function" gorm:"not null"` - SlaverId byte `json:"slaverId" gorm:"not null"` - StartAddress uint16 `json:"startAddress" gorm:"not null"` - Quality uint16 `json:"quality" gorm:"not null"` -} - //-------------------------------------------------------------------------------------------------- // 0.6.0 //-------------------------------------------------------------------------------------------------- diff --git a/component/rulex_api_server/model/siemons_data_point.go b/component/rulex_api_server/model/siemons_data_point.go new file mode 100644 index 000000000..a9e83a2b0 --- /dev/null +++ b/component/rulex_api_server/model/siemons_data_point.go @@ -0,0 +1,29 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package model + +// 西门子数据点位表 +type MSiemensDataPoint struct { + RulexModel + UUID string `gorm:"not null"` + DeviceUuid string `gorm:"not null"` + Tag string `gorm:"not null"` + Type string `gorm:"not null"` + Frequency int64 `gorm:"not null"` + Address int `gorm:"not null"` + Start int `gorm:"not null"` + Size int `gorm:"not null"` +} diff --git a/component/rulex_api_server/model/user_lua_template.go b/component/rulex_api_server/model/user_lua_template.go index ad43def69..b764f9c9c 100644 --- a/component/rulex_api_server/model/user_lua_template.go +++ b/component/rulex_api_server/model/user_lua_template.go @@ -22,6 +22,7 @@ package model type MUserLuaTemplate struct { RulexModel UUID string + Gid string // 分组 Type string // 类型 固定为 'function' Label string //快捷代码名称 Apply string //快捷代码 diff --git a/component/rulex_api_server/service/dao.go b/component/rulex_api_server/service/dao.go index f9beeccdc..f721c5f58 100644 --- a/component/rulex_api_server/service/dao.go +++ b/component/rulex_api_server/service/dao.go @@ -3,8 +3,6 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/component/rulex_api_server/model" - - "gorm.io/gorm" ) // ----------------------------------------------------------------------------------- @@ -201,51 +199,6 @@ func UpdateDevice(uuid string, o *model.MDevice) error { } } -// ------------------------------------------------------------------------------------- -// ModbusPointPositions -// ------------------------------------------------------------------------------------- - -// InsertModbusPointPosition 插入modbus点位表 -func InsertModbusPointPosition(list []model.MModbusPointPosition) error { - m := model.MModbusPointPosition{} - return interdb.DB().Model(m).Create(list).Error -} - -// DeleteModbusPointAndDevice 删除modbus点位与设备 -func DeleteModbusPointAndDevice(deviceUuid string) error { - return interdb.DB().Transaction(func(tx *gorm.DB) (err error) { - - err = tx.Where("device_uuid = ?", deviceUuid).Delete(&model.MModbusPointPosition{}).Error - if err != nil { - return err - } - - err = tx.Where("uuid = ?", deviceUuid).Delete(&model.MDevice{}).Error - if err != nil { - return err - } - return nil - }) -} - -// UpdateModbusPoint 更新modbus点位 -func UpdateModbusPoint(mm model.MModbusPointPosition) error { - m := model.MDevice{} - if err := interdb.DB().Where("id = ?", mm.ID).First(&m).Error; err != nil { - return err - } else { - interdb.DB().Model(m).Updates(&m) - return nil - } -} - -// AllModbusPointByDeviceUuid 根据设备UUID查询设备点位 -func AllModbusPointByDeviceUuid(deviceUuid string) (list []model.MModbusPointPosition, err error) { - - err = interdb.DB().Where("device_uuid = ?", deviceUuid).Find(&list).Error - return -} - // ------------------------------------------------------------------------------------- // Goods // ------------------------------------------------------------------------------------- diff --git a/component/rulex_api_server/service/modbus_data_sheet_service.go b/component/rulex_api_server/service/modbus_data_sheet_service.go new file mode 100644 index 000000000..e07187978 --- /dev/null +++ b/component/rulex_api_server/service/modbus_data_sheet_service.go @@ -0,0 +1,59 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package service + +import ( + "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/rulex_api_server/model" +) + +/* +* +* Modbus点位表管理 +* + */ +// InsertModbusPointPosition 插入modbus点位表 +func InsertModbusPointPositions(list []model.MModbusDataPoint) error { + m := model.MModbusDataPoint{} + return interdb.DB().Model(m).Create(list).Error +} + +// InsertModbusPointPosition 插入modbus点位表 +func InsertModbusPointPosition(P model.MModbusDataPoint) error { + return interdb.DB().Model(P).Create(P).Error +} + +// DeleteModbusPointByDevice 删除modbus点位与设备 +func DeleteModbusPointByDevice(uuids []string, deviceUuid string) error { + return interdb.DB(). + Where("uuid IN ? AND device_uuid=?", uuids, deviceUuid). + Delete(&model.MModbusDataPoint{}).Error +} + +// DeleteAllModbusPointByDevice 删除modbus点位与设备 +func DeleteAllModbusPointByDevice(deviceUuid string) error { + return interdb.DB(). + Where("device_uuid=?", deviceUuid). + Delete(&model.MModbusDataPoint{}).Error +} + +// 更新DataSchema +func UpdateModbusPoint(MModbusDataPoint model.MModbusDataPoint) error { + return interdb.DB().Model(model.MModbusDataPoint{}). + Where("device_uuid=? AND uuid=?", + MModbusDataPoint.DeviceUuid, MModbusDataPoint.UUID). + Updates(MModbusDataPoint).Error +} diff --git a/component/rulex_api_server/service/siemons_data_sheet_service.go b/component/rulex_api_server/service/siemons_data_sheet_service.go new file mode 100644 index 000000000..4cd5edd35 --- /dev/null +++ b/component/rulex_api_server/service/siemons_data_sheet_service.go @@ -0,0 +1,58 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package service + +import ( + "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/rulex_api_server/model" +) + +/* +* +* 西门子点位表管理 +* + */ +// InsertSiemensPoint 插入modbus点位表 +func InsertSiemensPoint(list []model.MModbusDataPoint) error { + m := model.MModbusDataPoint{} + return interdb.DB().Model(m).Create(list).Error +} + +// DeleteSiemensPointAndDevice 删除modbus点位与设备 +func DeleteSiemensPointByDevice(deviceUuid string) error { + return interdb.DB(). + Where("device_uuid=?", deviceUuid). + Delete(&model.MModbusDataPoint{}).Error +} + +// AllSiemensPointByDeviceUuid 根据设备UUID查询设备点位 +func AllSiemensPointByDeviceUuid(deviceUuid string, + page, pageSize int) (list []model.MModbusDataPoint, err error) { + switch { + case pageSize > 100: + pageSize = 100 + case pageSize <= 0: + pageSize = 10 + } + err = interdb.DB().Where("device_uuid=?", deviceUuid). + Find(&list).Offset(int(page)).Limit(pageSize).Error + return +} + +// 更新DataSchema +func UpdateSiemensPoint(MModbusDataPoint model.MModbusDataPoint) error { + return interdb.DB().Model(MModbusDataPoint).Updates(&MModbusDataPoint).Error +} diff --git a/component/rulex_api_server/service/table_count_service.go b/component/rulex_api_server/service/table_count_service.go new file mode 100644 index 000000000..2f0a8b498 --- /dev/null +++ b/component/rulex_api_server/service/table_count_service.go @@ -0,0 +1,40 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package service + +import "github.com/hootrhino/rulex/component/interdb" + +/* +* +* 计算 Count +* + */ +func CountModel(m any) int64 { + var count int64 + interdb.DB().Model(m).Count(&count) + return count +} + +/* +* +* 计算 Count +* + */ +func CountTable(table string) int64 { + var count int64 + interdb.DB().Table(table).Count(&count) + return count +} diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index 0cc227ccf..eb715056d 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -25,6 +25,7 @@ import ( "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/component/hwportmanager" + "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/driver" "github.com/hootrhino/rulex/glogger" @@ -58,13 +59,28 @@ import ( type _GMODCommonConfig struct { Mode string `json:"mode" title:"工作模式" info:"UART/TCP"` AutoRequest *bool `json:"autoRequest" title:"启动轮询"` - Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` } type _GMODConfig struct { - CommonConfig _GMODCommonConfig `json:"commonConfig" validate:"required"` - PortUuid string `json:"portUuid"` - HostConfig common.HostConfig `json:"hostConfig"` - Registers []common.RegisterRW `json:"registers" validate:"required" title:"寄存器配置"` + CommonConfig _GMODCommonConfig `json:"commonConfig" validate:"required"` + PortUuid string `json:"portUuid"` + HostConfig common.HostConfig `json:"hostConfig"` +} + +/* +* +* 点位表 +* + */ +type ModbusPoint struct { + UUID string `json:"uuid,omitempty"` // 当UUID为空时新建 + Tag string `json:"tag"` + Alias string `json:"alias"` + Function int `json:"function"` + SlaverId byte `json:"slaverId"` + Address uint16 `json:"address"` + Frequency int64 `json:"frequency"` + Quantity uint16 `json:"quantity"` + Value string `json:"value,omitempty"` } type generic_modbus_device struct { typex.XStatus @@ -76,6 +92,7 @@ type generic_modbus_device struct { mainConfig _GMODConfig retryTimes int hwPortConfig hwportmanager.UartConfig + Registers []common.RegisterRW } /* @@ -107,22 +124,33 @@ func (mdev *generic_modbus_device) Init(devId string, configMap map[string]inter if err := utils.BindSourceConfig(configMap, &mdev.mainConfig); err != nil { return err } - // 频率不能太快 - if mdev.mainConfig.CommonConfig.Frequency < 50 { - return errors.New("'frequency' must grate than 50 millisecond") - - } - // 检查Tag有没有重复 - tags := []string{} - for _, register := range mdev.mainConfig.Registers { - tags = append(tags, register.Tag) - } - if utils.IsListDuplicated(tags) { - return errors.New("tag duplicated") - } if !utils.SContains([]string{"UART", "TCP"}, mdev.mainConfig.CommonConfig.Mode) { return errors.New("unsupported mode, only can be one of 'TCP' or 'UART'") } + // 合并数据库里面的点位表 + var list []ModbusPoint + errDb := interdb.DB().Table("m_modbus_data_points"). + Where("device_uuid=?", devId).Find(&list).Error + if errDb != nil { + return errDb + } + for _, v := range list { + // 频率不能太快 + if v.Frequency < 50 { + return errors.New("'frequency' must grate than 50 millisecond") + } + mdev.Registers = append(mdev.Registers, + common.RegisterRW{ + Tag: v.Tag, + Alias: v.Alias, + Function: v.Function, + SlaverId: v.SlaverId, + Address: v.Address, + Quantity: v.Quantity, + Frequency: v.Frequency, + }) + } + if mdev.mainConfig.CommonConfig.Mode == "UART" { hwPort, err := hwportmanager.GetHwPort(mdev.mainConfig.PortUuid) if err != nil { @@ -181,8 +209,9 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { }) client := modbus.NewClient(mdev.rtuHandler) mdev.driver = driver.NewModBusRtuDriver(mdev.Details(), - mdev.RuleEngine, mdev.mainConfig.Registers, mdev.rtuHandler, - client, mdev.mainConfig.CommonConfig.Frequency) + mdev.RuleEngine, + mdev.Registers, mdev.rtuHandler, + client) } if mdev.mainConfig.CommonConfig.Mode == "TCP" { mdev.tcpHandler = modbus.NewTCPClientHandler( @@ -197,8 +226,7 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { } client := modbus.NewClient(mdev.tcpHandler) mdev.driver = driver.NewModBusTCPDriver(mdev.Details(), - mdev.RuleEngine, mdev.mainConfig.Registers, mdev.tcpHandler, client, - mdev.mainConfig.CommonConfig.Frequency) + mdev.RuleEngine, mdev.Registers, mdev.tcpHandler, client) } //--------------------------------------------------------------------------------- // Start diff --git a/device/generic_modbus_excel_device.go b/device/generic_modbus_excel_device.go deleted file mode 100644 index 275489966..000000000 --- a/device/generic_modbus_excel_device.go +++ /dev/null @@ -1,315 +0,0 @@ -package device - -import ( - "context" - "errors" - "fmt" - golog "log" - "sync" - "time" - - "github.com/plgd-dev/kit/v2/log" - modbus "github.com/wwhai/gomodbus" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/core" - "github.com/hootrhino/rulex/driver" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" - - _ "github.com/mattn/go-sqlite3" -) - -// 这是个通用Modbus采集器, 主要用来在通用场景下采集数据,因此需要配合规则引擎来使用 -// -// Modbus 采集到的数据如下, LUA 脚本可做解析, 示例脚本可参照 generic_modbus_parse.lua -// -// { -// "d1":{ -// "tag":"d1", -// "function":3, -// "slaverId":1, -// "address":0, -// "quantity":2, -// "value":"..." -// }, -// "d2":{ -// "tag":"d2", -// "function":3, -// "slaverId":2, -// "address":0, -// "quantity":2, -// "value":"..." -// } -// } - -const ( - DEFAULT_DB_PATH string = "./rulex.db" -) - -type modbusPointPosition struct { - DeviceUuid string `json:"deviceUuid" ` - Tag string `json:"tag" ` - Function int `json:"function" ` - SlaverId byte `json:"slaverId" ` - StartAddress uint16 `json:"startAddress"` - Quality uint16 `json:"quality" ` -} - -type _GMODExcelCommonConfig struct { - Mode string `json:"mode" title:"工作模式" info:"UART/TCP"` - Timeout int `json:"timeout" validate:"required" title:"连接超时"` - AutoRequest bool `json:"autoRequest" title:"启动轮询"` - Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` -} -type _GMODExcelHostConfig struct { - Host string `json:"host" title:"服务地址"` - Port int `json:"port" title:"服务端口"` -} - -type _GMODExcelConfig struct { - CommonConfig _GMODExcelCommonConfig `json:"commonConfig" validate:"required"` - RtuConfig common.CommonUartConfig `json:"rtuConfig" validate:"required"` - TcpConfig _GMODExcelHostConfig `json:"tcpConfig" validate:"required"` - Registers []common.RegisterRW `json:"registers" validate:"required" title:"寄存器配置"` -} -type generic_modbus_excel_device struct { - typex.XStatus `` - status typex.DeviceState - RuleEngine typex.RuleX - driver typex.XExternalDriver - rtuHandler *modbus.RTUClientHandler - tcpHandler *modbus.TCPClientHandler - mainConfig _GMODExcelConfig - locker sync.Locker - retryTimes int -} - -/* -* -* 温湿度传感器 -* - */ -func NewGenericModbusExcelDevice(e typex.RuleX) typex.XDevice { - - var ( - err error - ) - - mdev := new(generic_modbus_excel_device) - mdev.RuleEngine = e - mdev.locker = &sync.Mutex{} - mdev.mainConfig = _GMODExcelConfig{ - CommonConfig: _GMODExcelCommonConfig{}, - TcpConfig: _GMODExcelHostConfig{Host: "127.0.0.1", Port: 502}, - RtuConfig: common.CommonUartConfig{}, - } - mdev.Busy = false - mdev.status = typex.DEV_DOWN - if err != nil { - log.Panic(err) - return nil - } - return mdev -} - -//  初始化 -func (mdev *generic_modbus_excel_device) Init(devId string, configMap map[string]interface{}) (err error) { - mdev.PointId = devId - if err := utils.BindSourceConfig(configMap, &mdev.mainConfig); err != nil { - return err - } - - // 超时大于30秒无意义 - if mdev.mainConfig.CommonConfig.Timeout > 30000 { - return errors.New("'timeout' must less than 30 second") - } - // 频率不能太快 - if mdev.mainConfig.CommonConfig.Frequency < 50 { - return errors.New("'frequency' must grate than 50 millisecond") - - } - - var list []modbusPointPosition - err = interdb.DB().Table("m_modbus_point_position").Where("device_uuid = ?", devId).Find(&list).Error - if err != nil { - return err - } - - if len(list) > 0 { - for _, v := range list { - mdev.mainConfig.Registers = append(mdev.mainConfig.Registers, common.RegisterRW{ - Tag: v.Tag, - Function: v.Function, - SlaverId: v.SlaverId, - Address: v.StartAddress, - Quantity: v.Quality, - }) - } - } - - // 检查Tag有没有重复 - tags := []string{} - for _, register := range mdev.mainConfig.Registers { - tags = append(tags, register.Tag) - } - if utils.IsListDuplicated(tags) { - return errors.New("tag duplicated") - } - if !utils.SContains([]string{"UART", "TCP"}, mdev.mainConfig.CommonConfig.Mode) { - return errors.New("unsupported mode, only can be one of 'TCP' or 'RTU'") - } - - return nil -} - -// 启动 -func (mdev *generic_modbus_excel_device) Start(cctx typex.CCTX) error { - mdev.Ctx = cctx.Ctx - mdev.CancelCTX = cctx.CancelCTX - - if mdev.mainConfig.CommonConfig.Mode == "UART" { - mdev.rtuHandler = modbus.NewRTUClientHandler(mdev.mainConfig.RtuConfig.Uart) - mdev.rtuHandler.BaudRate = mdev.mainConfig.RtuConfig.BaudRate - mdev.rtuHandler.DataBits = mdev.mainConfig.RtuConfig.DataBits - mdev.rtuHandler.Parity = mdev.mainConfig.RtuConfig.Parity - mdev.rtuHandler.StopBits = mdev.mainConfig.RtuConfig.StopBits - // timeout 最大不能超过20, 不然无意义 - mdev.rtuHandler.Timeout = time.Duration(mdev.mainConfig.RtuConfig.Timeout) * time.Microsecond - if core.GlobalConfig.AppDebugMode { - mdev.rtuHandler.Logger = golog.New(glogger.GLogger.Writer(), - "Modbus: ", golog.LstdFlags) - } - - if err := mdev.rtuHandler.Connect(); err != nil { - return err - } - client := modbus.NewClient(mdev.rtuHandler) - mdev.driver = driver.NewModBusRtuDriver(mdev.Details(), - mdev.RuleEngine, mdev.mainConfig.Registers, mdev.rtuHandler, - client, mdev.mainConfig.CommonConfig.Frequency) - } - if mdev.mainConfig.CommonConfig.Mode == "TCP" { - mdev.tcpHandler = modbus.NewTCPClientHandler( - fmt.Sprintf("%s:%v", mdev.mainConfig.TcpConfig.Host, mdev.mainConfig.TcpConfig.Port), - ) - if core.GlobalConfig.AppDebugMode { - mdev.tcpHandler.Logger = golog.New(glogger.GLogger.Writer(), "Modbus: ", golog.LstdFlags) - } - - if err := mdev.tcpHandler.Connect(); err != nil { - return err - } - client := modbus.NewClient(mdev.tcpHandler) - mdev.driver = driver.NewModBusTCPDriver(mdev.Details(), - mdev.RuleEngine, mdev.mainConfig.Registers, mdev.tcpHandler, client, - mdev.mainConfig.CommonConfig.Frequency) - } - // --------------------------------------------------------------------------------- - // Start - // --------------------------------------------------------------------------------- - if !mdev.mainConfig.CommonConfig.AutoRequest { - mdev.status = typex.DEV_UP - return nil - } - mdev.retryTimes = 0 - go func(ctx context.Context, Driver typex.XExternalDriver) { - - mdev.status = typex.DEV_UP - buffer := make([]byte, common.T_64KB) - for { - select { - case <-ctx.Done(): - { - return - } - default: - { - } - } - // if mdev.Busy { - // glogger.GLogger.Warn("Modbus device is busing now") - // continue - // } - - mdev.Busy = true - n, err := Driver.Read([]byte{}, buffer) - mdev.Busy = false - if err != nil { - glogger.GLogger.Error(err) - mdev.retryTimes++ - } else { - mdev.RuleEngine.WorkDevice(mdev.Details(), string(buffer[:n])) - } - } - - }(mdev.Ctx, mdev.driver) - return nil -} - -// 从设备里面读数据出来 -func (mdev *generic_modbus_excel_device) OnRead(cmd []byte, data []byte) (int, error) { - - n, err := mdev.driver.Read(cmd, data) - if err != nil { - glogger.GLogger.Error(err) - mdev.retryTimes++ - } - return n, err -} - -// 把数据写入设备 -func (mdev *generic_modbus_excel_device) OnWrite(cmd []byte, data []byte) (int, error) { - if mdev.Busy { - return 0, fmt.Errorf("device busing now") - } - return mdev.driver.Write(cmd, data) -} - -// 设备当前状态 -func (mdev *generic_modbus_excel_device) Status() typex.DeviceState { - // 容错5次 - if mdev.retryTimes > 5 { - return typex.DEV_DOWN - } - return typex.DEV_UP -} - -// 停止设备 -func (mdev *generic_modbus_excel_device) Stop() { - mdev.status = typex.DEV_DOWN - if mdev.CancelCTX != nil { - mdev.CancelCTX() - } - if mdev.driver != nil { - mdev.driver.Stop() - } -} - -// 设备属性,是一系列属性描述 -func (mdev *generic_modbus_excel_device) Property() []typex.DeviceProperty { - return []typex.DeviceProperty{} -} - -// 真实设备 -func (mdev *generic_modbus_excel_device) Details() *typex.Device { - return mdev.RuleEngine.GetDevice(mdev.PointId) -} - -// 状态 -func (mdev *generic_modbus_excel_device) SetState(status typex.DeviceState) { - mdev.status = status -} - -// 驱动 -func (mdev *generic_modbus_excel_device) Driver() typex.XExternalDriver { - return mdev.driver -} -func (mdev *generic_modbus_excel_device) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { - return typex.DCAResult{} -} -func (mdev *generic_modbus_excel_device) OnCtrl(cmd []byte, args []byte) ([]byte, error) { - return []byte{}, nil -} diff --git a/device/generic_modbus_excel_device.md b/device/generic_modbus_excel_device.md deleted file mode 100644 index 940c5a658..000000000 --- a/device/generic_modbus_excel_device.md +++ /dev/null @@ -1,115 +0,0 @@ -# Modbus点表导入支持 - -## 1. Modbus上传Excel点位文件 - -### 接口说明 - -| URL | request | version | status | -| :--------------------------------------------- | :------ | :------ | :----- | -| http://server_ip/v1/devices/modbus/sheetImport | POST | 1.0 | true | - -### 请求参数说明 - -注意:请求content-type是multipart/form-data - -| 请求参数 | 类型 | 必填 | 必填 | -| :--------- | :----- | :--- | :-------------------------- | -| deviceUuid | String | true | 设备UUID | -| file | file | true | 点位excel文件(具体看模板) | - -Excel 模板 -![excel](image/generic_modbus_excel_device/1692706230355.png) -### 请求响应示例JSON -响应示例 - -```json -{ - "code": 200, - "msg": "Success", - "data": {} -} -``` - -## 2. 更新点位数据 -### 接口说明 - -| URL | request | version | status | -| :----------------------------------------------- | :------ | :------ | :----- | -| http://192.168.2.58:8080/v1/devices/modbus/point | PUT | 1.0 | true | - -### 请求参数说明 - -注意:请求content-type是multipart/form-data - -| 请求参数 | 类型 | 必填 | 备注 | -| :----------- | :----- | :--- | :-------------------- | -| Id | int | true | 点位ID | -| DeviceUuid | file | true | 设备UUID | -| Tag | String | true | 数据标签 | -| Function | int | true | Modbus功能 | -| SlaverId | int | true | 从设备ID (1-255) | -| StartAddress | int | true | 起始地址 | -| Quality | int | true | 偏移量(双字节) | - -### 请求示例JSON -```json -{ - "id": 1, - "deviceUuid": "uuid", - "tag": "tag", - "function": "1", - "slaverId": 1, - "StartAddress": 2, - "Quality": 1 -} -``` - -### 返回示例JSON -```json -{ - "code": 200, - "msg": "Success", - "data": {} -} -``` - -## 3. 获取点位数据 - -### 接口说明 - -| URL | request | version | status | -| :----------------------------------------------- | :------ | :------ | :----- | -| http://192.168.2.58:8080/v1/devices/modbus/point | GET | 1.0 | true | - -### 请求参数说明 - -注意:请求content-type是multipart/form-data - -| 请求参数 | 类型 | 必填 | 必填 | -| :--------- | :--- | :--- | :------- | -| DeviceUuid | file | true | 设备UUID | - -### 请求示例JSON -```json -{ - "deviceUuid": "uuid" -} -``` - -### 返回示例JSON -```json -{ - "code": 200, - "msg": "Success", - "data": [{ - "id": 1, - "deviceUuid": "uuid", - "tag": "tag", - "function": "1", - "slaverId": 1, - "startAddress": 2, - "quality": 1, - "createdAt": "2023-08-22 18:00:00" - }] -} -``` \ No newline at end of file diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index 0d8d8322b..c9316dc40 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -9,21 +9,26 @@ import ( "time" "github.com/hootrhino/rulex/common" + "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "github.com/robinson/gos7" ) -type S1200Block struct { - Tag string `json:"tag" validate:"required"` // 数据tag - Type string `json:"type" validate:"required"` // 块类型 MB | DB |FB - Frequency *int64 `json:"frequency" validate:"required"` // 采集频率 - Address *int `json:"address" validate:"required"` // 块地址 - Start *int `json:"start" validate:"required"` // 起始地址 - Size *int `json:"size" validate:"required"` // 采集长度 - Value string `json:"value,omitempty"` // 值 +// 点位表 +type SiemensDataPoint struct { + UUID string `json:"uuid"` // 当UUID为空时新建 + DeviceUuid string `json:"device_uuid"` + Tag string `json:"tag,omitempty"` + Type string `json:"type,omitempty"` + Frequency *int64 `json:"frequency,omitempty"` + Address *int `json:"address,omitempty"` + Start *int `json:"start,omitempty"` + Size *int `json:"size,omitempty"` + Value string `json:"value"` // 采集到的值 } + type S1200CommonConfig struct { Host string `json:"host" validate:"required"` // 127.0.0.1:502 Model string `json:"model" validate:"required"` // s7-200 s7-1500 @@ -35,17 +40,17 @@ type S1200CommonConfig struct { } type S1200Config struct { CommonConfig S1200CommonConfig `json:"commonConfig" validate:"required"` // 通用配置 - Blocks []S1200Block `json:"blocks" validate:"required"` //点位表 } // https://www.ad.siemens.com.cn/productportal/prods/s7-1200_plc_easy_plus/07-Program/02-basic/01-Data_Type/01-basic.html type s1200plc struct { typex.XStatus - status typex.DeviceState - RuleEngine typex.RuleX - mainConfig S1200Config - client gos7.Client - lock sync.Mutex + status typex.DeviceState + RuleEngine typex.RuleX + mainConfig S1200Config + client gos7.Client + lock sync.Mutex + SiemensDataPoints []SiemensDataPoint } /* @@ -81,13 +86,19 @@ func (s1200 *s1200plc) Init(devId string, configMap map[string]interface{}) erro glogger.GLogger.Error(err) return err } - // 检查Tag有没有重复 - tags := []string{} - for _, block := range s1200.mainConfig.Blocks { - tags = append(tags, block.Tag) + // 合并数据库里面的点位表 + var list []SiemensDataPoint + errDb := interdb.DB().Table("m_siemens_data_points"). + Where("device_uuid=?", devId).Find(&list).Error + if errDb != nil { + return errDb } - if utils.IsListDuplicated(tags) { - return errors.New("tag duplicated") + for _, v := range list { + // 频率不能太快 + if *v.Frequency < 50 { + return errors.New("'frequency' must grate than 50 millisecond") + } + s1200.SiemensDataPoints = append(s1200.SiemensDataPoints, v) } return nil } @@ -159,7 +170,7 @@ func (s1200 *s1200plc) OnRead(cmd []byte, data []byte) (int, error) { // db.Address:int, db.Start:int, db.Size:int, rData[] func (s1200 *s1200plc) OnWrite(cmd []byte, data []byte) (int, error) { - blocks := []S1200Block{} + blocks := []SiemensDataPoint{} if err := json.Unmarshal(data, &blocks); err != nil { return 0, err } @@ -210,7 +221,7 @@ func (s1200 *s1200plc) OnCtrl(cmd []byte, args []byte) ([]byte, error) { return []byte{}, nil } func (s1200 *s1200plc) Write(cmd []byte, data []byte) (int, error) { - blocks := []S1200Block{} + blocks := []SiemensDataPoint{} if err := json.Unmarshal(data, &blocks); err != nil { return 0, err } @@ -234,8 +245,8 @@ func (s1200 *s1200plc) Write(cmd []byte, data []byte) (int, error) { var rData = [common.T_2KB]byte{} // 一次最大接受2KB数据 func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { - values := []S1200Block{} - for _, db := range s1200.mainConfig.Blocks { + values := []SiemensDataPoint{} + for _, db := range s1200.SiemensDataPoints { //DB 4字节 if db.Type == "DB" { // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 @@ -246,7 +257,7 @@ func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { if *db.Size*2 > 2000 { *count = 2000 } - values = append(values, S1200Block{ + values = append(values, SiemensDataPoint{ Tag: db.Tag, Address: db.Address, Type: db.Type, @@ -265,7 +276,7 @@ func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { if *db.Size*2 > 2000 { *count = 2000 } - values = append(values, S1200Block{ + values = append(values, SiemensDataPoint{ Tag: db.Tag, Type: db.Type, Address: db.Address, diff --git a/driver/modbus_rtu_driver.go b/driver/modbus_rtu_driver.go index 6f372f95e..c73f0c4aa 100644 --- a/driver/modbus_rtu_driver.go +++ b/driver/modbus_rtu_driver.go @@ -31,7 +31,7 @@ func NewModBusRtuDriver( e typex.RuleX, Registers []common.RegisterRW, handler *modbus.RTUClientHandler, - client modbus.Client, frequency int64) typex.XExternalDriver { + client modbus.Client) typex.XExternalDriver { return &modBusRtuDriver{ state: typex.DRIVER_UP, device: d, @@ -39,7 +39,6 @@ func NewModBusRtuDriver( client: client, handler: handler, Registers: Registers, - frequency: frequency, } } diff --git a/driver/modbus_tcp_driver.go b/driver/modbus_tcp_driver.go index 20788b898..562caa037 100644 --- a/driver/modbus_tcp_driver.go +++ b/driver/modbus_tcp_driver.go @@ -31,7 +31,7 @@ func NewModBusTCPDriver( e typex.RuleX, Registers []common.RegisterRW, handler *modbus.TCPClientHandler, - client modbus.Client, frequency int64) typex.XExternalDriver { + client modbus.Client) typex.XExternalDriver { return &modBusTCPDriver{ state: typex.DRIVER_UP, device: d, @@ -39,7 +39,6 @@ func NewModBusTCPDriver( client: client, handler: handler, Registers: Registers, - frequency: frequency, } } diff --git a/test/apps/http_post_demo.lua b/test/apps/http_post_demo.lua index 4a90944db..5d0283445 100644 --- a/test/apps/http_post_demo.lua +++ b/test/apps/http_post_demo.lua @@ -15,7 +15,7 @@ function Main(arg) local dataTable = { - device_id = 1, + device_uuid = 1, recv_time = "2023-11-28T11=11=36+08=00", bat_voltage = 0, longitude = 0, diff --git a/test/data/test-modbus-sheet.xlsx b/test/data/test-modbus-sheet.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..0f6bcf0808eefcd55f199d981a171193381c57c4 GIT binary patch literal 11914 zcma)CbzD_j(?(ipq`Ra$q`RcMOB(6sfFMYBcS%UMbR#X@AV?!A-Tj>d_o~kg%rmpsUTfr~ARwQCfvy1A6#>xSzptmj4@NeI^7b~i4h-@@F*M*0un%I5 z>|e_mpMZg}f`fq}|1PF)YfBHXvP_HmED6DcCVK9DkNnAog^om#naVqm8%EO!pT%aj zO&T?NW8{jC-jVnM#`?rY`39cl`A9*Xy^G%7_m*SW4>rlkRZBiKv!!}Jqp{o7G{Ozh_9I1D3gX~Ud zOo}9FI4ZVtpZHiN8wbF@gw6G}Uu%JTW1d=lu{btX7|x(gUrP@T_wI*wNn9r&r;Zw9 z?Ra@>_0F$ynVTQt>%7jZU7sboAx(KR-ltbDb@_7EG@&lz!`nT0x8 zxxGBxJ*B5#roGxKN$A*=-+^G-f>8JY-RRwk5~kCh(~Z;as`4tr6HLy(jaRr`h9iUx zEH_QKR+lDhPdR8TeAs z$wypb7KY}*73&t1NoU2vnszD$(b#X5u}iT%jj)%zB3ZP(^}VtEwKBAjM5@G}@e%D% zs5pXsWY7K=;cu(i5zd+UW~^MJOn&fBn@`PhG0;_uYh zhG9({v3*HG049-eeW6FT_|Fi8StGGf14DoU48ik%guuzc(Z&iCgq$cHsSZXo|9z-? z;V&M^5v7&bR^sDG$P8$yjd5eSTA31(F|q*{i-U5LY4DKhh* zZtv`cb;-Bf@tEQg+&ug-ooV*0kwIF&Pk{zaB7>I2@wPYZ?^$e|$~{GE8aTfu?XGih z&9mP55;n`uw#c+;p{$FdtRRm?e~*0KP7F7L(23F=JKkiVaf#S;h?d)?RP8uvb6jGG z|HB+hFEni|S{XjUSBzDimLmdy28lhajzO={g}KZ^%ybprvzc`$m$^jZcn;Wit8p;A z{D!ovD$RdGiAY5@;Uae`(TjCA2%T2ybZ30^1O)BBmly~jv;fP8;_~kTh>rp;Hue?{ zX2!;je-CcoXhLOccM>-jQd}_u`q37 zk(eZ}jvE|ilM%$QkPsr)?@!4ahR+~yBs{@7=o)M1G+VM5$cSiOpO07!59pe{a{tPn zcWrFv)T}*`r*mA#@6n=nxAS2y;Jm*pXFi>vHeg+Ok>Ng{p`VcO?k2Bsdj015dwuDg zXufU3H--;$XWu)_oxbu;_w0TzbS;n*bTuF9vBG`F z)I3AyOWl|-OHV&*yfUo3wl9{m(p%Fetg))Q??1l#E;QM~J5+cMSZIM(Z6I_GA$V||RLTCH)tZrjF6+O@F(J+)^(KXR;i_3Y+4A%Re6IRWhajpt0Qr(>O? zuoL%$tA|Ikn@7F&uB?sAXB_1wt;v#G`!^}8Jywl6eBYepmZp!lm-p-l8?Xp(SG4)( z89b@^E>d=kk-7R?&rf&!Zr_bs^WUlxZtH0A`&WO`zA1YX-nv^8P);8_S8hKx>=_|< zd*IAk8Y?Gr{Fe57+IGdM$*)wp>A-n?hPpah*l1pE8`@9XsG!=QqsKVh$#pmGe)wPU!6j zb1c7eeV*hpNUV%-uY-4P$3TnOvs=4&TwQi?S4e5?ueTo`qBA{J3x{DNdNmFq>Ed?r zalCb>Y~g14c+m5$la7DN?GW3P&4%xAtwV6R&sW}e_ZY&5dl(%QY41E#TFU(O7MrgI z=eCw(WRd1Q@)nK?ZLH5JSE=3WxY^4>%7uj!7#QX*?kM@1;NT1~k?znUoHYSP3AQIY z9jEi#7J$1(_5f_|XItfl;#ByAJ>imE?+Cc3#+JLo!yGRvR>?V4GvNx*?G7WfP$K$N zo22qw2De`hy5Pr~cZz|ph?k;IkF0<2qb}R2gWhm0MXR52clRfW;0SN%)qb?QB%Qb87;X@3*gr2`CQuT=#w|7ycrx_DX~#_8@h zZ9mMIRUFn12RaBmlMryc2=D{jclRyHHR_+t+O%;Y9Gn2dXWWSvBk({M{JWlqO8{=( zg^NGIQjJLZDT7Y#^S2GuSdb0IVuIg17=Z3!GxOijgsy|dRwdp;gkUZvWa%)B5%0oYqU{ z`%sP=#w(0at-x=-5UVtp1$r!+2M&^v2g*DNI}{qs>`~6nP@2)-EYE**CkyCKL!^Ek zheEwqHz0F;#IOZu;f(PlQ;2Z-H;3R?yMp?lSi9kz>g?*5499>%U`&qc%DIVWAXf?m zpmll~^-}Xg9j4*f0ti?lyk!*vGdr@FyQ+G~BZ6h2m^X#|FIPm2@tSn=u}>5u?C13_ z&*=3PlCTL{>W7 zF-EW$Ch*)srB|W!6r&9`%jX8*A7G=87TmCZdJJ@P28&@5?R}R;X=s#$U>;f52ym1= z0KjV5q<&W4n7(4#|H=y0_ZkNUUvRjJHhk!K3TNdP~HOu#(plZ|WI|Hc% zoJe7|np^S?V*h6q{p1u78#CeTQrCS!1{D3e0R<)_r>trUBL;H#&M6OU1wwI>M?dU$ zx#AlfcBnX*vGb-h3xrnfLrkc-bjW;$zCT+JiHQRRrQ=%TW4)xD!@R!wL3#dPp!cvD ze|D(H*=v<^_{0oi2Zu`5qnUKBA1@!0Ml>(PD4i>TCXqo_m0k>m+hQn$@T zFc8%ie^KMVVjKnkmze(}6O9x{s3aapmi#x#()u~{Qj6gqsoeW9LkY+LVZXcm^}=76 zYkzjP`@{^d%P_Ir{oOm_7YEFLW(2(&kgI=~0cHdnC_zCP@tYqeBhwGCF4z3!sM)3v z9uhk-$im-b9W0?TtH?tP=^OYfFRzp^H&)#3gt{Ika>`np`^Z8N*Z;zm?Jt7KJ8Zfo zYk}tR6I2kBkKF3+`34`jJh7~N=&uJvl^g!;&)6N;<^FJ@FVk;%2);5GR zSC0TicQ)~hh$5cbE83|HviZQ&p1^BJUw;|<5$kt?jnp^2e@sQ72Rd>NxRQ$S_!x12 z^BkD+3-ITQk16lRl}f#EfXh4R6rf)QOr}RH2&QA3hrT2H9+f%yXq@ybgxvbS!*)FJ zZ^QgbC*UyMKfT};%RSUylz$*7-{9cSicN3x`mdmIeXIMn1FSBakCUlP`o(fwV74fC z|04}%tV~#b@ss_b*n+~A5wQQwd=ms{>t|MW&|^v%bL9eoVGT4F6*K7@RfqcsofRjP z=6hAU`|62=-Hj`ox#Nx7txp^ia?5)6dU{=DRq5CJNay@jgHqEWax%CrD)YBzobHv) zh&y9jU4~7eXNTT-j>UVG+GvCdH3CUyEPVU&=^VCenW^*T?J_7uV1;!z3HTB8?E}t7gBGgK#)o@3oCdYn09&yfenrJ^eG{Z{zuQ{ zp}RQzssuQNdcmpaoozk(1h~*#V_u36@WB!^appPB@|)9O)YEopZh2D$=vS;@2mwpE z6jkF!C8hiMsK z@`ra`@;ODxBL}*L?i+6V9^xcR#9k<$DG2R)5fWoxhyED69O-uQ^_7-mG!``V^*i|T zZEdM6?qp|#@8%7E?s2E6y+kfwns^`+?pKp>)zIjHfZZt8nhL@|DtR<03hAq*o`DkN zQ$$yRt!~Ff;u(qaGcj9St~{%;Xrk@@(6{!k2rL1u&7An8#f|WePI-D1Wb?C4gYf&a z&ZIm`omxBrG=px>_dI8^=FH;LU*`v(zS!0YcsHHdQQIPHQ~2Gpg@Hkf$?;7!HtU>K z^QG*~+kK|YDvAv>!l%u*80A-?4UGA|CxXv0VJc|-#Z|g9=0D4DP#ckxOtYd0c0=MJ zb%Yg8z;H=fhxe=lGz!(S&6wWvMYsF9H3ab$&@0Ce1UY2u8fHa5k%IGiO^V!hmWdL- zBSs(#6Sxw^%#=`mTmC_BJP+Ux_kljP$QJEBqAtg*BHA{2b}R3VEwl?7wU9oehz2QM z$9s5!82A;k2@|N%r`m?_FW6l@p0^lj_r64}_|lLYt$~k9!h}RAfwNrtB}xKbhD~LG zdi73rlmoKJ>>VA4_Qa1?dG;4_^GyoY?-S^e4gsM7V5K8w;s zE$;P!@=aQr0=lh4^!{Z7rulZ~{zB0}{nOeK=2XbpHbAHt$GISz?J5NAp%fv>WJwcW zoki1VVH~|PxO1!;cund6lZ-|a>__8S`w2FyWg^?p2xS(tHM>2MWae)vpWnOzXV(u08eR${n>l|;SK-QYoCV)+)F?(aYY@sZ= z7BXr^pG2w-9K{f)tj+m|1g~3;ZT_o#fn`V3o;1lz0Za~LHT>xX{_&5EA1*KfCf#QP zovR7f$1BaH6C6W4$4$5CuInDheWPtr)|v}5&H*LS_8RmOQ{_8nKb8fHPMUYb>NTRf zTR49tg>zSF<``ONH+(uhEwc*0HSC$?ucFoSruJV|-5NO;$BpZ&duxU;aA@pegs_~@ zvV$N^*y08gci3Awuz-bvkQz+gf7;hp74Sl_qdOxdFZ%t~tr0V|%lzlwlil#$nLDP^ zA~J*q+%iIVo#7uGMB7n$0c;(H#oO=aPrp^noihllpw}+eHmXVs<>($3r@Z_Wt~)!6 zCkx%(MkuA@!hE9jg3j$ll%DSXXQ>=Al$<$hq|Q2G52=QeU8#gM+%b#IOL60~IrhcW zx;qQwqxVwo8~)0LzQr?clb3E!NAFwQUlFLktoWc_T0!_FL|aIC!w{=%u(L?3sQI-1;8zhghoPeNm7F!F^g(;W3{;LX z{ft&^S_iHOrLr2!Qx5AH$9`7wo-ig8WEVJRooCcVVv}YQQFfT<;1Y#U9D?vg{T)vY z`@J$N=4awCan`VLa4r@}WRh1}C*PbaQW2X5<^dlql*Sd-Qu?{I#LsD2pD89yTJ%rT z+D;3-XHYb+C~uqhV>*$x>Qpavl%){i8d8jpQ$@J|^WjO8T%W1pe{Pw^!wNBS? zeGBL?sm3r?9jG#At!cGRDYhjWwx$}3P2hd@lsCJ%7Dv}Bw0j${ySv%ntv^z;gr!OH zjr64gBfF!H4fUx>Wr2l?@#&34n_k(=(}rgTz5V{?+V|AuHWTK9$yr6opMH=NEwz%c zSyT<`hNNKMS=h03c+y#S&li6eckmdrHn}M48ic>EuB)$DOT}cx31e$aT5iQ)XStbP zSvPih3&Gyu?lCi}E0sNXp!aCtIJg090ANn{x2~Ea3&B*oK*OpVuR2VOcQrng%yo>5 zR!aEfxjxa>SD1j!aTjqj^{p$uVmvFWGt1*P{A5HPRiWU6=L+rMIK^?*l6S<#PJT+m z>zyt>#y-!e(I(P0F#5ejdug8;_$!*kzvxR4$0{b9oK9zB(2i-3w!gIx&E?FtDs*Z3W-qv_88IXyYw5X%9 zAds+{RtZAN*eb=nHZ0}T67uPqL970R*`J$V(X5WzakC2*gOy9-hYF!NX4_wl(BDNj zkcF--ln90@341{oh!8{OyG~r|TQmrke~sG7ml#!(hpbP9%77WfDERy-l)Zc=QQ#B> zTFg9W=9D=V`FkI`{2ZdhY14v_@UWv%B(W9kHHh(*q`psP^5=>0f=Ni0s6(X>$kCaa z>Aq^*Ey0VLGV-V-RzWY&C=Ox%Jienr_+dVFia8> z<)C>nEle33OG{t>LtCAy-cg5=N+SZ3{kUAQ-9gYWwaeJf0g3cQY7liH9d<-f*C20k zEa=t~lJZua3UmVspO-6Q0B-~g)_eLnkc}9uz|Sy2Aq>XA&4|)m{x=@ z@~{fb_G291a8M37Z_l&0VqAp5jh;w)A!QF7yB_wKwi%tB2R?1b$oWh`v;HPG)RI5e z6VG1Q13@x~eP>t+^$-gu_L2%=;SxXlayYH>df24(9oCVcYvNes_>O}~;=8l0tuG0t zNV2-_2Mb#~ynT_e1p9Jn8=TkEdc%7ygv=sef>GOeV%qfbBJP=Q2d^s^7t=g0Y9kSI zko?2(7}H}M&qn7fBkqwEmpEztMa=HT#Xor2R%%56tN|uLV^h8tL_a=K;-C?bFtSjM z&=GlOk@=z#kOq%fJwZW32m}Bqg<7FRO-#|KmwJApXtvcw2vu4tUd8{jr3(@sk}OOxG4|*fx=$6J=re?R zmBS-$*m~o(*?z2KH+=00o#0tvPL~oqaAHdlv|ckRzW2Vnz}uxkyeH)dE?9wZ!3vsm zGB!m5wF2^{!*C>3I;&sEAlfM=6d#A^Fc70h$~MrOTc86y{6qRHdKwO)NNo-t0ozTt zvpFy1aS8rxWYNr}NNqpWc06svT^CswQRxKKtIWATDqX?bk@!o2+hF9oz8Ny6RQ08$ z8k&l=WS&GyIq4&9E2n&@P8%-R>?sx`1BGSf*BH#?8gLl8Z8t&agT?6-dL`sDEblRc zh|O;t^3okpVcq8KECj?sO#HZ0$kKc`^a)su(sV=5++?{Urs0Q)r9n;n+ z)wmfphJ+t|CZebG7;M?Psw)KkCuYoCIoTL{AUjW)SIB84Tm17E09HhsM<4EUTv>v< zs@(m(i4^lj?QzGF;@#c7xY`~2O4@!ak1~^9|5DY(_Z5&T_QUVt9F{q3AJ-pImP={G~K0RmQ%BHZ^Fa4gQaVf>|BXDd2&8-z5EjGddqDp znYa=#kV1xQQp3O1X)JwuHnZK(kse7uw+j0r2JsV#c9(3Fw?{e|g+66&XAG8vFX?d` zvt|F54jXqoOZd!kL5y_Pe##JJsUH$4wA`FBB{~j|SP52@%T$!76FjNGMJ#zbLRjyD ztnlJI%Y?ns!khT&LKT{w>NFiQrCILAMt}Mu`)hnKiU!kntFK0fToM|K)g0{?dGK6S ztHLTE*jwHTcHpvRT%YI^b-LFFTi+3pIw9k-K8wo_&3=1O`?v-6t3##L#2-=;c!2)_ zxW5JZ6}Y$MV5VkL7jPxa2}vZ;|5ZAUQ|uy`;l0U{+Z& zlB*RHe0?V79L3wilevH0pL4oriW6ef+NqBi78wyo>At!C4mLo{-J^xyQWPZyt{Hb@ z3D@pW;m7QCBUiWbnvJk!CsWS2lt%a7CIu$pMhw!W2|q)O)MXuBA3(EdXLaRfI4~<^I`T-@ShT`_x#_Cb;;W^IR!?S$Qp&eXdL^v{&mIf=)uk1yZ)KTMm)M&j z!w$kO_056V{S5b;qcK`z7K;pg247qU8=s4Dx^j0?p@kX9)Am7se`*|Z6iPxvUiji` zw6#RtN9}0(Hwm3m+vumkZlcXux(a3aY7;aMUuBweb(P8rrY9`6*-n$)fL|BnZSvVC zaJLao{oRC{GeKW#C$zTdPUGFAnsXKuZ3=29<~*;M?_ba9{quG4L{?O(ABg=T@OU5T z5qr=9zJZO6#lu;=l8#LZBbvvDs{7ZMX;`n!Af72_LY62hsl17|mWzQQSBC;_vwTcG zTQn8k4B(RC(OFz|h}ch1Q_E`rZw-u$twiQx!3A$;PFHe9?7bmM1UlqluiC#q#kV)c|vW_^-wXXyv=$A9Q zrX0oN>#%zi-ULnnnPs&SuX;80VUAv8R4VFRh&y){;zgQ!R~Q^upZx;wn06eoBg3s< zJWe@-FM(9f+;&5{>B$IgSPP0~QLWdh24CVjN5g9O!luZH2Bb1!r_A2TGedR%q93|o zhHhE=Go?0IYagw1w&~2E5SI66w7So}xs-@*f1GMRw4w=Tz=%)y=&(N~QOd4+Ws2AF zg%X3%L}6Uo_6r!% zZS;aYyY;_sJ3|BGu4iv-`Deq%TMp-@d*J^TfsHkAKV|4ak|oi@lAVmm-TU7A$m=aK zF6by<9T`Y|$QXHeB}(6qkUx*s*llSRRG^(`fQd-DTu)haH)_P4C(>og4R7*xQt%eA z>2+>VIB*B3&wIZrZk~j2Rkm%1Y}`IFxc2o~=ZT%ACyUZ?R~%su;HHXsGrFZLFYtkz zO*D^_-;mVjWwW)sb>ER#_Xh%b8J?~M>cF>+&~_YtO_w${g*!t_yh+)@!z?tw$fr43 zMxuxMxM$C_BA<#vLvs$>JMs1JyGRBUmzdBYh-&*KDg}T0uH9-!o7AH%OBnnjWAIX7 ze0-z*bJVC-RsSn4-xpas_higHoon%~d~ABJ?2qV*T>d+je{JFa8=T({vaoi6Fg5_; z!~y;Vmbpi<-xKa{bj>>$;k);Jntet+?8d^F#L{%TGp0-4f*I0yni;@IX{FSD=*`r~ za7@sK|KQuYPtiX&U%x+rL~d@#C~w3`2~U6Zass*qaUY2xBhc!gCgcf1=&N#?{rwuk z8I5?Ui7E&xyQfAO`UJYw>}6hn+;W}5f`(r_m~diU}eH&Hu*Wf0LZ#uPWD1$e3uRs)C+LcM)&WL)pf{C zJSn*tOg^OLZs+ufcH;`sg6~R(&r1xSAUYbbql&VW;=;sgzOeiL$2mv-p{9c=upS`* zp9P?E4lQ9DYe!>iM?Ga%TVn?uP)#a{?Uw~-Li0Z-Z|V4`#iC@ZAFBU)*|>mg1!Cf? zjrAlx-TUAyo$58X;QP=N39jAC*87`gcrhA_;1?nj3zNlqr|M5+-E!uOO$cKWj?&Q+ zeU;h)Fl<^7pGFU^%o#Oc+Pn+#r-~)0cx=NzJ)tQ-dV)77?NLQC$~Xi-wx>5~vw7Rh zP2ViFq?n|M@Dh*bvoftTb-LQg+f_1eK~)}WjGE%)Amq?^k|?DX$89e~>!;`{>ufWd zUhGCbhuOZ)>n?3Idtq5Ynu1IiOwG@vUe+Di<9P_k`WLpUgwLFe7sLzTz)7JfkJJ;z3i@td0E1Uh*0I2A!=}{%Ok*ALpugub@BDbEyrYWhwC~yO(9#B- z(5y${*1~B^R81>w)A8qH!+lorje9UxR^i^6>%<2D*N0mHp>Tg4gdfMF z_+9O<*4aNH`m-7Im$n~}(mx0NyEXJr^*dpUB_$Nw1!1?|xP=7l5XC(uT^N3RU?`r>1*Z#Eg=fdxooi8N+z6|`+!k@d{zbs&2 zJX-j<_x=B$dpB?)1f2Wd$FToo$e#zXzee2sUG3Mg?4K_Gx#Id|K$PrZ+}~mQUrvMi zEgvsXgnb_)3{w8tefdw%|Lng6>HZb9|Iq!_jVUh$^^mM6!1iVspqv#oNbmmu7js{N literal 0 HcmV?d00001 diff --git a/typex/version.go b/typex/version.go index 7a7a8eb4d..dd4a8b642 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-08 15:06:29", + ReleaseTime: "2023-12-09 23:44:50", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-c453e9cd189b5e6 +** Version: v0.6.4-1678a59515cc7dc ** Document: https://hootrhino.github.io ` From ff933e6c0c52fc41ab52b657a084dc58938944ec Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 10 Dec 2023 14:54:01 +0800 Subject: [PATCH 101/138] dev: add modbus_data_sheet export api --- .../apis/device_data_sheet_api.go | 16 ++++++++++++++-- typex/version.go | 4 ++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/component/rulex_api_server/apis/device_data_sheet_api.go b/component/rulex_api_server/apis/device_data_sheet_api.go index c7b73b8a2..484585c98 100644 --- a/component/rulex_api_server/apis/device_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_data_sheet_api.go @@ -16,9 +16,12 @@ package apis import ( + "encoding/csv" "errors" + "fmt" "io" "strconv" + "time" "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/interdb" @@ -46,12 +49,21 @@ type ModbusPointVo struct { /* * * 特殊设备需要和外界交互,这里主要就是一些设备的点位表导入导出等支持 -* +* http://127.0.0.1:2580/api/v1/modbus_data_sheet/export */ // ModbusPoints 获取modbus_excel类型的点位数据 func ModbusPointsExport(c *gin.Context, ruleEngine typex.RuleX) { - c.JSON(common.HTTP_OK, common.Ok()) + c.Header("Content-Type", "text/csv") + c.Header("Content-Disposition", fmt.Sprintf("attachment;filename=%v.csv", time.Now().UnixMilli())) + csvWriter := csv.NewWriter(c.Writer) + csvWriter.WriteAll([][]string{ + {"h1", "h2", "h3"}, + {"11", "12", "13"}, + {"21", "22", "23"}, + {"31", "32", "33"}, + }) + csvWriter.Flush() } // 分页获取 diff --git a/typex/version.go b/typex/version.go index dd4a8b642..f062d4ec3 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-09 23:44:50", + ReleaseTime: "2023-12-10 11:58:20", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-1678a59515cc7dc +** Version: v0.6.4-fdd7edcb278fdb4 ** Document: https://hootrhino.github.io ` From 8a05dcd3ed576640f781f6436b47a0fae7111739 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 10 Dec 2023 16:20:23 +0800 Subject: [PATCH 102/138] dev: modbus del All Api support --- .../apis/device_data_sheet_api.go | 18 ++++++++++++++++++ component/rulex_api_server/http_api_server.go | 2 +- typex/version.go | 4 ++-- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/component/rulex_api_server/apis/device_data_sheet_api.go b/component/rulex_api_server/apis/device_data_sheet_api.go index 484585c98..08263028e 100644 --- a/component/rulex_api_server/apis/device_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_data_sheet_api.go @@ -102,6 +102,24 @@ func ModbusSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { * 删除单行 * */ +func ModbusSheetDeleteAll(c *gin.Context, ruleEngine typex.RuleX) { + type Form struct { + UUIDs []string `json:"uuids"` + DeviceUUID string `json:"device_uuid"` + } + form := Form{} + if Error := c.ShouldBindJSON(&form); Error != nil { + c.JSON(common.HTTP_OK, common.Error400(Error)) + return + } + err := service.DeleteAllModbusPointByDevice(form.DeviceUUID) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) + +} func ModbusSheetDelete(c *gin.Context, ruleEngine typex.RuleX) { type Form struct { UUIDs []string `json:"uuids"` diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 1c1e54d5b..ebcc051b6 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -344,7 +344,7 @@ func (hs *ApiServerPlugin) LoadRoute() { modbusApi.GET(("/list"), server.AddRoute(apis.ModbusSheetPageList)) modbusApi.POST(("/update"), server.AddRoute(apis.ModbusSheetUpdate)) modbusApi.DELETE(("/delIds"), server.AddRoute(apis.ModbusSheetDelete)) - modbusApi.DELETE(("/delAll"), server.AddRoute(apis.ModbusSheetDelete)) + modbusApi.DELETE(("/delAll"), server.AddRoute(apis.ModbusSheetDeleteAll)) } // ---------------------------------------------------------------------------------------------- diff --git a/typex/version.go b/typex/version.go index f062d4ec3..1ffa0aeba 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-10 11:58:20", + ReleaseTime: "2023-12-10 15:21:34", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-fdd7edcb278fdb4 +** Version: v0.6.4-ff933e6c0c52fc4 ** Document: https://hootrhino.github.io ` From 65a786b1c8d475d7a040a2d596f4179f50a00c36 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 10 Dec 2023 17:33:47 +0800 Subject: [PATCH 103/138] fix: fix ModbusPoint create failed --- .../rulex_api_server/apis/device_data_sheet_api.go | 11 ++++++----- .../service/modbus_data_sheet_service.go | 2 +- typex/version.go | 4 ++-- utils/uuid_util.go | 7 ++++++- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/component/rulex_api_server/apis/device_data_sheet_api.go b/component/rulex_api_server/apis/device_data_sheet_api.go index 08263028e..65fca1940 100644 --- a/component/rulex_api_server/apis/device_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_data_sheet_api.go @@ -155,13 +155,14 @@ func ModbusSheetUpdate(c *gin.Context, ruleEngine typex.RuleX) { if ModbusDataPoint.UUID == "" { NewRow := model.MModbusDataPoint{} copier.Copy(&NewRow, &ModbusDataPoint) + NewRow.DeviceUuid = ModbusDataPoint.DeviceUUID + NewRow.UUID = utils.ModbusPointUUID() service.InsertModbusPointPosition(NewRow) } else { - OldRow := model.MModbusDataPoint{ - DeviceUuid: ModbusDataPoint.DeviceUUID, - UUID: ModbusDataPoint.UUID, - } + OldRow := model.MModbusDataPoint{} copier.Copy(&OldRow, &ModbusDataPoint) + OldRow.DeviceUuid = ModbusDataPoint.DeviceUUID + OldRow.UUID = ModbusDataPoint.UUID service.UpdateModbusPoint(OldRow) } } @@ -270,7 +271,7 @@ func parseModbusPointExcel( address, _ := strconv.ParseUint(row[5], 10, 16) quantity, _ := strconv.ParseUint(row[6], 10, 16) model := model.MModbusDataPoint{ - UUID: utils.MakeUUID("MDTB"), + UUID: utils.ModbusPointUUID(), DeviceUuid: deviceUuid, Tag: tag, Alias: alias, diff --git a/component/rulex_api_server/service/modbus_data_sheet_service.go b/component/rulex_api_server/service/modbus_data_sheet_service.go index e07187978..2488529ca 100644 --- a/component/rulex_api_server/service/modbus_data_sheet_service.go +++ b/component/rulex_api_server/service/modbus_data_sheet_service.go @@ -33,7 +33,7 @@ func InsertModbusPointPositions(list []model.MModbusDataPoint) error { // InsertModbusPointPosition 插入modbus点位表 func InsertModbusPointPosition(P model.MModbusDataPoint) error { - return interdb.DB().Model(P).Create(P).Error + return interdb.DB().Model(P).Create(&P).Error } // DeleteModbusPointByDevice 删除modbus点位与设备 diff --git a/typex/version.go b/typex/version.go index 1ffa0aeba..e8e0b1745 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-10 15:21:34", + ReleaseTime: "2023-12-10 17:25:49", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-ff933e6c0c52fc4 +** Version: v0.6.4-8a05dcd3ed57664 ** Document: https://hootrhino.github.io ` diff --git a/utils/uuid_util.go b/utils/uuid_util.go index 7c17e7e45..1009c9344 100644 --- a/utils/uuid_util.go +++ b/utils/uuid_util.go @@ -55,9 +55,14 @@ func UserLuaUuid() string { return MakeUUID("USERLUA") } +// MakeUUID +func ModbusPointUUID() string { + return MakeUUID("MDTB") +} + // MakeUUID func MakeUUID(prefix string) string { - return prefix + strings.ToUpper(shortuuid.New()[:6]) + return prefix + strings.ToUpper(shortuuid.New()[:8]) } func MakeLongUUID(prefix string) string { return prefix + strings.ToUpper(shortuuid.New()) From e9984f7f7097e56f027f8cb59648717360b8821f Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 10 Dec 2023 21:47:53 +0800 Subject: [PATCH 104/138] fix: fix slaverid save failed --- .../apis/device_data_sheet_api.go | 45 ++++++++++++------- .../model/modebus_data_point.go | 18 ++++---- .../service/modbus_data_sheet_service.go | 7 +++ typex/version.go | 4 +- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/component/rulex_api_server/apis/device_data_sheet_api.go b/component/rulex_api_server/apis/device_data_sheet_api.go index 65fca1940..7a365cac6 100644 --- a/component/rulex_api_server/apis/device_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_data_sheet_api.go @@ -35,15 +35,15 @@ import ( ) type ModbusPointVo struct { - UUID string `json:"uuid,omitempty"` - DeviceUUID string `json:"device_uuid"` - Tag string `json:"tag"` - Alias string `json:"alias"` - Function int `json:"function"` - SlaverId byte `json:"slaverId"` - Address uint16 `json:"address"` - Frequency int64 `json:"frequency"` - Quantity uint16 `json:"quantity"` + UUID string `json:"uuid,omitempty"` + DeviceUUID string `json:"device_uuid"` + Tag string `json:"tag"` + Alias string `json:"alias"` + Function *int `json:"function"` + SlaverId *byte `json:"slaver_id"` + Address *uint16 `json:"address"` + Frequency *int64 `json:"frequency"` + Quantity *uint16 `json:"quantity"` } /* @@ -157,13 +157,21 @@ func ModbusSheetUpdate(c *gin.Context, ruleEngine typex.RuleX) { copier.Copy(&NewRow, &ModbusDataPoint) NewRow.DeviceUuid = ModbusDataPoint.DeviceUUID NewRow.UUID = utils.ModbusPointUUID() - service.InsertModbusPointPosition(NewRow) + err0 := service.InsertModbusPointPosition(NewRow) + if err0 != nil { + c.JSON(common.HTTP_OK, common.Error400(err0)) + return + } } else { OldRow := model.MModbusDataPoint{} copier.Copy(&OldRow, &ModbusDataPoint) OldRow.DeviceUuid = ModbusDataPoint.DeviceUUID OldRow.UUID = ModbusDataPoint.UUID - service.UpdateModbusPoint(OldRow) + err0 := service.UpdateModbusPoint(OldRow) + if err0 != nil { + c.JSON(common.HTTP_OK, common.Error400(err0)) + return + } } } c.JSON(common.HTTP_OK, common.Ok()) @@ -270,16 +278,21 @@ func parseModbusPointExcel( slaverId, _ := strconv.ParseInt(row[4], 10, 8) address, _ := strconv.ParseUint(row[5], 10, 16) quantity, _ := strconv.ParseUint(row[6], 10, 16) + Function := int(function) + SlaverId := byte(slaverId) + Address := uint16(address) + Frequency := int64(frequency) + Quantity := uint16(quantity) model := model.MModbusDataPoint{ UUID: utils.ModbusPointUUID(), DeviceUuid: deviceUuid, Tag: tag, Alias: alias, - Function: int(function), - SlaverId: byte(slaverId), - Address: uint16(address), - Frequency: frequency, //ms - Quantity: uint16(quantity), + Function: &Function, + SlaverId: &SlaverId, + Address: &Address, + Frequency: &Frequency, //ms + Quantity: &Quantity, } list = append(list, model) } diff --git a/component/rulex_api_server/model/modebus_data_point.go b/component/rulex_api_server/model/modebus_data_point.go index 266abcbc8..946305059 100644 --- a/component/rulex_api_server/model/modebus_data_point.go +++ b/component/rulex_api_server/model/modebus_data_point.go @@ -18,13 +18,13 @@ package model // modbus数据点位表 type MModbusDataPoint struct { RulexModel - UUID string `gorm:"not null" json:"uuid"` - DeviceUuid string `gorm:"not null" json:"device_uuid"` - Tag string `gorm:"not null" json:"tag"` - Alias string `gorm:"not null" json:"alias"` - Function int `gorm:"not null" json:"function"` - SlaverId byte `gorm:"not null" json:"slaver_id"` - Address uint16 `gorm:"not null" json:"address"` - Frequency int64 `gorm:"not null" json:"frequency"` - Quantity uint16 `gorm:"not null" json:"quantity"` + UUID string `gorm:"not null" json:"uuid"` + DeviceUuid string `gorm:"not null" json:"device_uuid"` + Tag string `gorm:"not null" json:"tag"` + Alias string `gorm:"not null" json:"alias"` + Function *int `gorm:"not null" json:"function"` + SlaverId *byte `gorm:"not null" json:"slaver_id"` + Address *uint16 `gorm:"not null" json:"address"` + Frequency *int64 `gorm:"not null" json:"frequency"` + Quantity *uint16 `gorm:"not null" json:"quantity"` } diff --git a/component/rulex_api_server/service/modbus_data_sheet_service.go b/component/rulex_api_server/service/modbus_data_sheet_service.go index 2488529ca..d93d17447 100644 --- a/component/rulex_api_server/service/modbus_data_sheet_service.go +++ b/component/rulex_api_server/service/modbus_data_sheet_service.go @@ -16,6 +16,8 @@ package service import ( + "fmt" + "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/component/rulex_api_server/model" ) @@ -33,6 +35,11 @@ func InsertModbusPointPositions(list []model.MModbusDataPoint) error { // InsertModbusPointPosition 插入modbus点位表 func InsertModbusPointPosition(P model.MModbusDataPoint) error { + Count := int64(0) + interdb.DB().Model(P).Count(&Count) + if Count > 0 { + return fmt.Errorf("already exists same record:%s", P.UUID) + } return interdb.DB().Model(P).Create(&P).Error } diff --git a/typex/version.go b/typex/version.go index e8e0b1745..55a5765ac 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-10 17:25:49", + ReleaseTime: "2023-12-10 21:44:39", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-8a05dcd3ed57664 +** Version: v0.6.4-65a786b1c8d475d ** Document: https://hootrhino.github.io ` From d739c102281e20c1302ab74e8f39e5d932daee14 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 10 Dec 2023 22:12:04 +0800 Subject: [PATCH 105/138] fix: fix slaverid error --- component/rulex_api_server/apis/device_data_sheet_api.go | 2 +- component/rulex_api_server/model/modebus_data_point.go | 2 +- typex/version.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/component/rulex_api_server/apis/device_data_sheet_api.go b/component/rulex_api_server/apis/device_data_sheet_api.go index 7a365cac6..217ab60ec 100644 --- a/component/rulex_api_server/apis/device_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_data_sheet_api.go @@ -40,7 +40,7 @@ type ModbusPointVo struct { Tag string `json:"tag"` Alias string `json:"alias"` Function *int `json:"function"` - SlaverId *byte `json:"slaver_id"` + SlaverId *byte `json:"slaverId"` Address *uint16 `json:"address"` Frequency *int64 `json:"frequency"` Quantity *uint16 `json:"quantity"` diff --git a/component/rulex_api_server/model/modebus_data_point.go b/component/rulex_api_server/model/modebus_data_point.go index 946305059..cafdc0701 100644 --- a/component/rulex_api_server/model/modebus_data_point.go +++ b/component/rulex_api_server/model/modebus_data_point.go @@ -17,7 +17,7 @@ package model // modbus数据点位表 type MModbusDataPoint struct { - RulexModel + RulexModel `json:"-"` UUID string `gorm:"not null" json:"uuid"` DeviceUuid string `gorm:"not null" json:"device_uuid"` Tag string `gorm:"not null" json:"tag"` diff --git a/typex/version.go b/typex/version.go index 55a5765ac..45177ee34 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-10 21:44:39", + ReleaseTime: "2023-12-10 22:11:46", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-65a786b1c8d475d +** Version: v0.6.4-e9984f7f7097e56 ** Document: https://hootrhino.github.io ` From 0084a74fa8fb716b9fa06caf3b448dd4d7c014a2 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 10 Dec 2023 22:46:25 +0800 Subject: [PATCH 106/138] dev: rename SlaverId --- component/rulex_api_server/model/modebus_data_point.go | 2 +- typex/version.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/component/rulex_api_server/model/modebus_data_point.go b/component/rulex_api_server/model/modebus_data_point.go index cafdc0701..e416088e6 100644 --- a/component/rulex_api_server/model/modebus_data_point.go +++ b/component/rulex_api_server/model/modebus_data_point.go @@ -23,7 +23,7 @@ type MModbusDataPoint struct { Tag string `gorm:"not null" json:"tag"` Alias string `gorm:"not null" json:"alias"` Function *int `gorm:"not null" json:"function"` - SlaverId *byte `gorm:"not null" json:"slaver_id"` + SlaverId *byte `gorm:"not null" json:"slaverId"` Address *uint16 `gorm:"not null" json:"address"` Frequency *int64 `gorm:"not null" json:"frequency"` Quantity *uint16 `gorm:"not null" json:"quantity"` diff --git a/typex/version.go b/typex/version.go index 45177ee34..14c1f3fa7 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-10 22:11:46", + ReleaseTime: "2023-12-10 22:25:13", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-e9984f7f7097e56 +** Version: v0.6.4-d739c102281e20c ** Document: https://hootrhino.github.io ` From a4c602b67fb543ded975975d9a357f97fa0e981b Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 10 Dec 2023 23:00:28 +0800 Subject: [PATCH 107/138] fix: fix duplicate UUID --- .../rulex_api_server/service/modbus_data_sheet_service.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/component/rulex_api_server/service/modbus_data_sheet_service.go b/component/rulex_api_server/service/modbus_data_sheet_service.go index d93d17447..899660388 100644 --- a/component/rulex_api_server/service/modbus_data_sheet_service.go +++ b/component/rulex_api_server/service/modbus_data_sheet_service.go @@ -35,11 +35,14 @@ func InsertModbusPointPositions(list []model.MModbusDataPoint) error { // InsertModbusPointPosition 插入modbus点位表 func InsertModbusPointPosition(P model.MModbusDataPoint) error { + IgnoreUUID := P.UUID Count := int64(0) - interdb.DB().Model(P).Count(&Count) + P.UUID = "" + interdb.DB().Model(P).Where(P).Count(&Count) if Count > 0 { - return fmt.Errorf("already exists same record:%s", P.UUID) + return fmt.Errorf("already exists same record:%s", IgnoreUUID) } + P.UUID = IgnoreUUID return interdb.DB().Model(P).Create(&P).Error } From 1a37424877fa9e49f854f43ccb884bcba3bc44c9 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 11 Dec 2023 17:07:36 +0800 Subject: [PATCH 108/138] dev: add Siemens data sheet support --- ...api.go => device_modbus_data_sheet_api.go} | 41 ++- .../apis/device_s1200_data_sheet_api.go | 321 ++++++++++++++++++ component/rulex_api_server/http_api_server.go | 14 +- .../model/siemons_data_point.go | 9 +- .../device_modbus_data_sheet_service.go | 69 ++++ ...go => device_s1200_data_import_service.go} | 0 .../service/siemons_data_sheet_service.go | 58 ---- test/data/test-siemens-sheet.xlsx | Bin 0 -> 11892 bytes typex/version.go | 4 +- utils/uuid_util.go | 4 + 10 files changed, 444 insertions(+), 76 deletions(-) rename component/rulex_api_server/apis/{device_data_sheet_api.go => device_modbus_data_sheet_api.go} (86%) create mode 100644 component/rulex_api_server/apis/device_s1200_data_sheet_api.go create mode 100644 component/rulex_api_server/service/device_modbus_data_sheet_service.go rename component/rulex_api_server/service/{modbus_data_sheet_service.go => device_s1200_data_import_service.go} (100%) delete mode 100644 component/rulex_api_server/service/siemons_data_sheet_service.go create mode 100644 test/data/test-siemens-sheet.xlsx diff --git a/component/rulex_api_server/apis/device_data_sheet_api.go b/component/rulex_api_server/apis/device_modbus_data_sheet_api.go similarity index 86% rename from component/rulex_api_server/apis/device_data_sheet_api.go rename to component/rulex_api_server/apis/device_modbus_data_sheet_api.go index 217ab60ec..b8f0d1bc6 100644 --- a/component/rulex_api_server/apis/device_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_modbus_data_sheet_api.go @@ -35,15 +35,18 @@ import ( ) type ModbusPointVo struct { - UUID string `json:"uuid,omitempty"` - DeviceUUID string `json:"device_uuid"` - Tag string `json:"tag"` - Alias string `json:"alias"` - Function *int `json:"function"` - SlaverId *byte `json:"slaverId"` - Address *uint16 `json:"address"` - Frequency *int64 `json:"frequency"` - Quantity *uint16 `json:"quantity"` + UUID string `json:"uuid,omitempty"` + DeviceUUID string `json:"device_uuid"` + Tag string `json:"tag"` + Alias string `json:"alias"` + Function *int `json:"function"` + SlaverId *byte `json:"slaverId"` + Address *uint16 `json:"address"` + Frequency *int64 `json:"frequency"` + Quantity *uint16 `json:"quantity"` + Status int `json:"status"` // 运行时数据 + LastFetchTime uint64 `json:"lastFetchTime"` // 运行时数据 + Value string `json:"value"` // 运行时数据 } /* @@ -93,7 +96,25 @@ func ModbusSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(result.Error)) return } - Result := service.WrapPageResult(*pager, records, count) + recordsVo := []ModbusPointVo{} + + for _, record := range records { + recordsVo = append(recordsVo, ModbusPointVo{ + UUID: record.UUID, + DeviceUUID: record.DeviceUuid, + Tag: record.Tag, + Alias: record.Alias, + Function: record.Function, + SlaverId: record.SlaverId, + Address: record.Address, + Frequency: record.Frequency, + Quantity: record.Quantity, + Status: 1, // 运行时 + LastFetchTime: uint64(time.Now().UnixMilli()), // 运行时 + Value: "00000000", // 运行时 + }) + } + Result := service.WrapPageResult(*pager, recordsVo, count) c.JSON(common.HTTP_OK, common.OkWithData(Result)) } diff --git a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go new file mode 100644 index 000000000..b6e677bc3 --- /dev/null +++ b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go @@ -0,0 +1,321 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package apis + +import ( + "encoding/csv" + "errors" + "fmt" + "io" + "strconv" + "time" + + "github.com/gin-gonic/gin" + "github.com/hootrhino/rulex/component/interdb" + common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/component/rulex_api_server/service" + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" + "github.com/jinzhu/copier" + "github.com/xuri/excelize/v2" +) + +type SiemensPointVo struct { + UUID string `json:"uuid,omitempty"` + DeviceUUID string `json:"device_uuid"` + Tag string `json:"tag"` + Alias string `json:"alias"` + Type string `json:"type"` + Frequency *int64 `json:"frequency"` + Address *int `json:"address"` + Start *int `json:"start"` + Size *int `json:"size"` + Status *int `json:"status"` // 运行时数据 + LastFetchTime uint64 `json:"lastFetchTime"` // 运行时数据 + Value string `json:"value"` // 运行时数据 +} + +/* +* +* 特殊设备需要和外界交互,这里主要就是一些设备的点位表导入导出等支持 +* http://127.0.0.1:2580/api/v1/Siemens_data_sheet/export + */ + +// SiemensPoints 获取Siemens_excel类型的点位数据 +func SiemensPointsExport(c *gin.Context, ruleEngine typex.RuleX) { + c.Header("Content-Type", "text/csv") + c.Header("Content-Disposition", fmt.Sprintf("attachment;filename=%v.csv", time.Now().UnixMilli())) + csvWriter := csv.NewWriter(c.Writer) + csvWriter.WriteAll([][]string{ + {"h1", "h2", "h3"}, + {"11", "12", "13"}, + {"21", "22", "23"}, + {"31", "32", "33"}, + }) + csvWriter.Flush() +} + +// 分页获取 +// SELECT * FROM `m_Siemens_data_points` WHERE +// `m_Siemens_data_points`.`device_uuid` = "DEVICEDQNLO8" +// ORDER BY +// created_at DESC LIMIT 2 OFFSET 10 +func SiemensSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { + pager, err := service.ReadPageRequest(c) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + deviceUuid, _ := c.GetQuery("device_uuid") + db := interdb.DB() + tx := db.Scopes(service.Paginate(*pager)) + var count int64 + err1 := interdb.DB().Model(&model.MSiemensDataPoint{}).Count(&count).Error + if err1 != nil { + c.JSON(common.HTTP_OK, common.Error400(err1)) + return + } + var records []model.MSiemensDataPoint + result := tx.Order("created_at DESC").Find(&records, + &model.MSiemensDataPoint{DeviceUuid: deviceUuid}) + if result.Error != nil { + c.JSON(common.HTTP_OK, common.Error400(result.Error)) + return + } + recordsVo := []SiemensPointVo{} + + for _, record := range records { + Status := 1 + recordsVo = append(recordsVo, SiemensPointVo{ + UUID: record.UUID, + DeviceUUID: record.DeviceUuid, + Tag: record.Tag, + Alias: record.Alias, + Address: record.Address, + Frequency: record.Frequency, + Start: record.Start, + Size: record.Size, + Status: &Status, // 运行时 + LastFetchTime: uint64(time.Now().UnixMilli()), // 运行时 + Value: "00000000", // 运行时 + }) + } + Result := service.WrapPageResult(*pager, recordsVo, count) + c.JSON(common.HTTP_OK, common.OkWithData(Result)) +} + +/* +* +* 删除单行 +* + */ +func SiemensSheetDeleteAll(c *gin.Context, ruleEngine typex.RuleX) { + type Form struct { + UUIDs []string `json:"uuids"` + DeviceUUID string `json:"device_uuid"` + } + form := Form{} + if Error := c.ShouldBindJSON(&form); Error != nil { + c.JSON(common.HTTP_OK, common.Error400(Error)) + return + } + err := service.DeleteAllSiemensPointByDevice(form.DeviceUUID) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) + +} +func SiemensSheetDelete(c *gin.Context, ruleEngine typex.RuleX) { + type Form struct { + UUIDs []string `json:"uuids"` + DeviceUUID string `json:"device_uuid"` + } + form := Form{} + if Error := c.ShouldBindJSON(&form); Error != nil { + c.JSON(common.HTTP_OK, common.Error400(Error)) + return + } + err := service.DeleteSiemensPointByDevice(form.UUIDs, form.DeviceUUID) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) + +} + +/* +* +* 更新点位表 +* + */ +func SiemensSheetUpdate(c *gin.Context, ruleEngine typex.RuleX) { + SiemensDataPoints := []SiemensPointVo{} + err := c.ShouldBindJSON(&SiemensDataPoints) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + for _, SiemensDataPoint := range SiemensDataPoints { + if SiemensDataPoint.UUID == "" { + NewRow := model.MSiemensDataPoint{} + copier.Copy(&NewRow, &SiemensDataPoint) + NewRow.DeviceUuid = SiemensDataPoint.DeviceUUID + NewRow.UUID = utils.SiemensPointUUID() + err0 := service.InsertSiemensPointPosition(NewRow) + if err0 != nil { + c.JSON(common.HTTP_OK, common.Error400(err0)) + return + } + } else { + OldRow := model.MSiemensDataPoint{} + copier.Copy(&OldRow, &SiemensDataPoint) + OldRow.DeviceUuid = SiemensDataPoint.DeviceUUID + OldRow.UUID = SiemensDataPoint.UUID + err0 := service.UpdateSiemensPoint(OldRow) + if err0 != nil { + c.JSON(common.HTTP_OK, common.Error400(err0)) + return + } + } + } + c.JSON(common.HTTP_OK, common.Ok()) + +} + +// SiemensSheetImport 上传Excel文件 +func SiemensSheetImport(c *gin.Context, ruleEngine typex.RuleX) { + // 解析 multipart/form-data 类型的请求体 + err := c.Request.ParseMultipartForm(1024 * 1024 * 10) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + + // 获取上传的文件 + file, header, err := c.Request.FormFile("file") + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + defer file.Close() + deviceUuid := c.Request.Form.Get("device_uuid") + type DeviceDto struct { + UUID string + Name string + Type string + } + Device := DeviceDto{} + errDb := interdb.DB().Table("m_devices"). + Where("uuid=?", deviceUuid).Find(&Device).Error + if errDb != nil { + c.JSON(common.HTTP_OK, common.Error400(errDb)) + return + } + if Device.Type != typex.S1200PLC.String() { + c.JSON(common.HTTP_OK, + common.Error("Invalid Device Type, Only Support Import Siemens Device")) + return + } + contentType := header.Header.Get("Content-Type") + if contentType != "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" && + contentType != "application/vnd.ms-excel" { + c.JSON(common.HTTP_OK, common.Error("File Must be Excel Sheet")) + return + } + // 判断文件大小是否符合要求(10MB) + if header.Size > 1024*1024*10 { + c.JSON(common.HTTP_OK, common.Error("Excel file size cannot be greater than 10MB")) + return + } + list, err := parseSiemensPointExcel(file, "Sheet1", deviceUuid) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + if err = service.InsertSiemensPointPositions(list); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) +} + +func parseSiemensPointExcel( + r io.Reader, + sheetName string, + deviceUuid string) (list []model.MSiemensDataPoint, err error) { + excelFile, err := excelize.OpenReader(r) + if err != nil { + return nil, err + } + defer func() { + excelFile.Close() + }() + // 读取表格 + rows, err := excelFile.GetRows(sheetName) + if err != nil { + return nil, err + } + // 判断首行标头 + // + err1 := errors.New("invalid Sheet Header") + if len(rows[0]) < 7 { + return nil, err1 + } + //tag alias type frequency address size + if rows[0][0] != "tag" || + rows[0][1] != "alias" || + rows[0][2] != "type" || + rows[0][3] != "frequency" || + rows[0][4] != "address" || + rows[0][5] != "start" || + rows[0][6] != "size" { + return nil, err1 + } + + list = make([]model.MSiemensDataPoint, 0) + //tag alias type frequency address start size + for i := 1; i < len(rows); i++ { + row := rows[i] + tag := row[0] + alias := row[1] + DbType := row[2] + frequency, _ := strconv.ParseInt(row[3], 10, 8) + address, _ := strconv.ParseUint(row[4], 10, 16) + start, _ := strconv.ParseUint(row[5], 10, 16) + size, _ := strconv.ParseUint(row[6], 10, 16) + Address := int(address) + Frequency := int64(frequency) + Start := int(start) + Size := int(size) + model := model.MSiemensDataPoint{ + UUID: utils.SiemensPointUUID(), + DeviceUuid: deviceUuid, + Tag: tag, + Alias: alias, + Type: DbType, + Frequency: &Frequency, + Address: &Address, + Start: &Start, + Size: &Size, + } + list = append(list, model) + } + return list, nil +} diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index ebcc051b6..4e9797c7b 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -339,13 +339,23 @@ func (hs *ApiServerPlugin) LoadRoute() { // Modbus 点位表 modbusApi := server.RouteGroup(server.ContextUrl("/modbus_data_sheet")) { - modbusApi.POST(("/import"), server.AddRoute(apis.ModbusSheetImport)) - modbusApi.GET(("/export"), server.AddRoute(apis.ModbusPointsExport)) + modbusApi.POST(("/sheetImport"), server.AddRoute(apis.ModbusSheetImport)) + modbusApi.GET(("/sheetExport"), server.AddRoute(apis.ModbusPointsExport)) modbusApi.GET(("/list"), server.AddRoute(apis.ModbusSheetPageList)) modbusApi.POST(("/update"), server.AddRoute(apis.ModbusSheetUpdate)) modbusApi.DELETE(("/delIds"), server.AddRoute(apis.ModbusSheetDelete)) modbusApi.DELETE(("/delAll"), server.AddRoute(apis.ModbusSheetDeleteAll)) } + // S1200 点位表 + S1200Plc := server.RouteGroup(server.ContextUrl("/s1200_data_sheet")) + { + S1200Plc.POST(("/sheetImport"), server.AddRoute(apis.SiemensSheetImport)) + S1200Plc.GET(("/sheetExport"), server.AddRoute(apis.SiemensPointsExport)) + S1200Plc.GET(("/list"), server.AddRoute(apis.SiemensSheetPageList)) + S1200Plc.POST(("/update"), server.AddRoute(apis.SiemensSheetUpdate)) + S1200Plc.DELETE(("/delIds"), server.AddRoute(apis.SiemensSheetDelete)) + S1200Plc.DELETE(("/delAll"), server.AddRoute(apis.SiemensSheetDeleteAll)) + } // ---------------------------------------------------------------------------------------------- // APP diff --git a/component/rulex_api_server/model/siemons_data_point.go b/component/rulex_api_server/model/siemons_data_point.go index a9e83a2b0..f41a07d4f 100644 --- a/component/rulex_api_server/model/siemons_data_point.go +++ b/component/rulex_api_server/model/siemons_data_point.go @@ -21,9 +21,10 @@ type MSiemensDataPoint struct { UUID string `gorm:"not null"` DeviceUuid string `gorm:"not null"` Tag string `gorm:"not null"` + Alias string `gorm:"not null"` Type string `gorm:"not null"` - Frequency int64 `gorm:"not null"` - Address int `gorm:"not null"` - Start int `gorm:"not null"` - Size int `gorm:"not null"` + Frequency *int64 `gorm:"not null"` + Address *int `gorm:"not null"` + Start *int `gorm:"not null"` + Size *int `gorm:"not null"` } diff --git a/component/rulex_api_server/service/device_modbus_data_sheet_service.go b/component/rulex_api_server/service/device_modbus_data_sheet_service.go new file mode 100644 index 000000000..5d76a72ed --- /dev/null +++ b/component/rulex_api_server/service/device_modbus_data_sheet_service.go @@ -0,0 +1,69 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package service + +import ( + "fmt" + + "github.com/hootrhino/rulex/component/interdb" + "github.com/hootrhino/rulex/component/rulex_api_server/model" +) + +/* +* +* Siemens点位表管理 +* + */ +// InsertSiemensPointPosition 插入Siemens点位表 +func InsertSiemensPointPositions(list []model.MSiemensDataPoint) error { + m := model.MSiemensDataPoint{} + return interdb.DB().Model(m).Create(list).Error +} + +// InsertSiemensPointPosition 插入Siemens点位表 +func InsertSiemensPointPosition(P model.MSiemensDataPoint) error { + IgnoreUUID := P.UUID + Count := int64(0) + P.UUID = "" + interdb.DB().Model(P).Where(P).Count(&Count) + if Count > 0 { + return fmt.Errorf("already exists same record:%s", IgnoreUUID) + } + P.UUID = IgnoreUUID + return interdb.DB().Model(P).Create(&P).Error +} + +// DeleteSiemensPointByDevice 删除Siemens点位与设备 +func DeleteSiemensPointByDevice(uuids []string, deviceUuid string) error { + return interdb.DB(). + Where("uuid IN ? AND device_uuid=?", uuids, deviceUuid). + Delete(&model.MSiemensDataPoint{}).Error +} + +// DeleteAllSiemensPointByDevice 删除Siemens点位与设备 +func DeleteAllSiemensPointByDevice(deviceUuid string) error { + return interdb.DB(). + Where("device_uuid=?", deviceUuid). + Delete(&model.MSiemensDataPoint{}).Error +} + +// 更新DataSchema +func UpdateSiemensPoint(MSiemensDataPoint model.MSiemensDataPoint) error { + return interdb.DB().Model(model.MSiemensDataPoint{}). + Where("device_uuid=? AND uuid=?", + MSiemensDataPoint.DeviceUuid, MSiemensDataPoint.UUID). + Updates(MSiemensDataPoint).Error +} diff --git a/component/rulex_api_server/service/modbus_data_sheet_service.go b/component/rulex_api_server/service/device_s1200_data_import_service.go similarity index 100% rename from component/rulex_api_server/service/modbus_data_sheet_service.go rename to component/rulex_api_server/service/device_s1200_data_import_service.go diff --git a/component/rulex_api_server/service/siemons_data_sheet_service.go b/component/rulex_api_server/service/siemons_data_sheet_service.go deleted file mode 100644 index 4cd5edd35..000000000 --- a/component/rulex_api_server/service/siemons_data_sheet_service.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (C) 2023 wwhai -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero 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 Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -package service - -import ( - "github.com/hootrhino/rulex/component/interdb" - "github.com/hootrhino/rulex/component/rulex_api_server/model" -) - -/* -* -* 西门子点位表管理 -* - */ -// InsertSiemensPoint 插入modbus点位表 -func InsertSiemensPoint(list []model.MModbusDataPoint) error { - m := model.MModbusDataPoint{} - return interdb.DB().Model(m).Create(list).Error -} - -// DeleteSiemensPointAndDevice 删除modbus点位与设备 -func DeleteSiemensPointByDevice(deviceUuid string) error { - return interdb.DB(). - Where("device_uuid=?", deviceUuid). - Delete(&model.MModbusDataPoint{}).Error -} - -// AllSiemensPointByDeviceUuid 根据设备UUID查询设备点位 -func AllSiemensPointByDeviceUuid(deviceUuid string, - page, pageSize int) (list []model.MModbusDataPoint, err error) { - switch { - case pageSize > 100: - pageSize = 100 - case pageSize <= 0: - pageSize = 10 - } - err = interdb.DB().Where("device_uuid=?", deviceUuid). - Find(&list).Offset(int(page)).Limit(pageSize).Error - return -} - -// 更新DataSchema -func UpdateSiemensPoint(MModbusDataPoint model.MModbusDataPoint) error { - return interdb.DB().Model(MModbusDataPoint).Updates(&MModbusDataPoint).Error -} diff --git a/test/data/test-siemens-sheet.xlsx b/test/data/test-siemens-sheet.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..d360c10549b04c2f8674eff7c249056e5918374f GIT binary patch literal 11892 zcmbt)Wk8fm`}fi<9n#$`T>^rDba!{d(j_S+jdVzNN=gezx0E!3NO$MEE9dAr{-5Xh z^3I3Zy?3ve`CTz{&s+-9P|%0~a0`+9CJg@kyCHzSnAjUD0PP)|SQJ2HSfC%^f08wG zf30MN001~30RXgrk{LQUFuU8@WW;`Y1;vIXei871_QC!c6S)#QT|g*5oR$mGGyAy? z8H~6eW7kZ~&SaNxcBl3#x5&>h$BG+)Zu{u)7Ous`A=6K3r zR{Dy8r+T{pBG4w)Gz6Ioz90y=-iBmpm0owbJTXxc#iGO9zzm7>dRM1Bq1!#bksfFL zWOZxp{!Ps)|8uCXi@K6~fh$ZSS_&3|2-jSCLiy`ju$%Z!bFV7%Kg}+Do*3JigE{?n zcXhOP#>~9Rc)eAg)U~Ow1I4xlrML^*9MFv(soR;~gWu_)DjDqykPq$c(T%ORURDO7YXU+S{h#O>+XGF(@J7aszv^PedvgG@oW0&A zI}tWA;hOb<0WJXZb92n?PJk_boJ9l8q3GcRH~O-qepl_{cCem%%0s$0?+=2kjp>iNWFHC0cIS|btDvX;?aD9&CIju zbO}xz*@8A6Oj2MY@CZ5nmcxbZbZ>!J_SDw^W+gesSjXQufHzp%pa_n9jueI@=6d`c zk+1_Yl}c9nXO5i9-klDW^HHRX4{K$4+SbdKm~Kf-?krFC6A}WeEmMo0y0Ce_4nHtU zn$ew7C~;LMRLDfkbbuO~qP9<_$5)W1R&IG_r>?=iWA=I;3E`VfhHq<|cblMZn{VD_ z!)B~*U?vjzVM<)vC$*168Tvzow9!%mh?azLN9pO*r?h12Z9ZNHuhXhYRMMayNR{R= z`lT?U-9oj6m%cAO;9hb6+X9hxsL$v@7C;AC0P|lKaB*_Bw*}iEKUP<|ixn&Q0OsLE zzfWp(Ma@%Ni7%*VELiEy2@?g{*;23K^AsSs)BRVUr?r62(PFrr*l8&xX|n(z(8&gnJ%>*P~f>UpF!-XL~_S#ACbH1=V= zzPU@g@`Zvg@nz)%g+vp&Gu%02!;Eh}gc`Mo4cn9@I^1^pKeKnK@)fUd;{BSkx52}= z$Z;P;(keICCflKnz9EkO4Q(RsdyGLR8PY6DH+s*zFD*uzS5I1wunIbq>zt?TPs)vn zcCGOABQhr9RFIQ`UUFzK@jJx`bjO{wAcQfZmK6{1S`NI9cv);-0 zY5{dmP3HM6?Grl6NjLd3sXn~>Vc3icmwVG|2r#t&Im1AKpmn$TnOpud!IMV1JyS3sejkr7C( ztcjyP7iArYli3Ly!z*R zTZVdz3nS*kmNP>8^7_OZ57&iPt9Rb6TlIy#d)b1Vs3*@;2XA}jeeb{AS$o~z9WQV! z4yp3!5^s#^UK~4CH|}Ppt(^nEv~kcB3e^2rt9K$9)yGLna;ot`j*kiv_wn*-;IX?X z^w3{j^LQ0`zGc~N&9%3`Q_bt*6YJzO>uPtG^y6;uO^J_hy2`;(i;qj|gl8O;ohQ|F zsoK};sGG%)t+n!t!xe(e*ZJRdUu$?9_z=5kl0i&6f=075h+1*@)_VWszUtr}es3Zm z)voB|`r7m48u;;R#*$hrpk#?DRnE87dC#$Cul_{-Vioz;Q_s7}cY#0resXkV_)FJq z;dX9oa|S<|#(k^39!vj4jor;v!^YTd)5iE-!qu*?t=Fw>gJ7eNBFjwwkM^6I*X{&o z{NJ7C@An7qres^rq~T3({TrI?9?HjuKYiU>9N4RW2(G(4SQN!^q}sZurN?xgsr>QP z_@wsEbJN-Da`e91>vghk@|W4?b2IH6H!PzW+Q-K|& z&sR#Cmd$%x+c7q3*3P{yujkageU(++x+>jHzA_8@@Ee?|<-ONymvz&(yjFcU9zMAC zJyGA+l8JJ=bEqh-(z-|}XjWVP7=4A0>r?1ox{UUIe{^qWNSCqV`{3ZT{=ihP+dkpm z?TY+s4vVPe&ylZhoW0sFH{^QuhqHkapNaU~CKsyviKO>0dELqyyVj#P-DVdYafy&5 z$Z{MCWrbHIc*ETsJ^k`uf=F9_aB{657L{uI-8q#6m{nMCO~GE4SvJ7EDY&DxzlPGU z!gtwR@RyB$VV7EbySWi=rd&Q&+rGMiBkqX_kw3y)O+wpm>4RiiHckGV#Gm40{B^d)B>yoCRRbw`u>Eh_itGL4++5USRE2HDbIym z7$bCwG0g)jKc=f19t1$1IC}IUBWw_V_(15Oe%b=d4XhHaJe)>>Cq-P=CwZ{>$ zs%$>UIq?2%CV-L$!r$l>cO73n0TBX(AMFJE4e>F?htRMyC;&*I^k4RV1pw&R5&rVa z;)q8vl-Q3$2SsE%I3k(;VM-RVw;=Zi0H)aM00vYvpIC=T0vR6XF9H}RhcYhZ{&rg3U4(tPVyaL%Nc^P`;w3R%50iqT zXvlx3s1#6&(sN1#1Q|9WK>i#rDr6|mQ$YL->sKAsJN|{cXg6<5=&^Ri#rCV44|fx{ zwqExip6i;0Z1lHMIC`xu;|pCJNMDdNol~J*Ex7Iz9Ut!1cty86+QThhUlhNetItK< z7vI)HFdLFT{v`;zQ>pEpqceO3*Hm@3AzdbIM9zihbZo=O@j8Z2-Nhv0x z6VvD@ES#_QP3b=M4LPmS15D;#f43ZA4o*;(mE5z;Wv|yH?H9MP4C*A596Xi zCqC06JMfuM#L3~W?!CU~w8MiBn?TQD{2b{JCGPI>aCcFWCHQm=8jkdRxZotbFiBgsUXdJ7KA5#HgO9M*Aq z7iw9m@;}iFGvV|$V?$e%Uw~Jm;u)5hbra#X zS}LkYDTUwX5!`D5Uu#SD3N{^D!URK_6K<}n@7gXn*vM8=7B`fPCdDR*#0(zMu=s51 zNxLo&1 z2hZ=X3P*2+X>;<$S=!u>cWP)@+HThy>`A;<;0RG{+}~4bKyx2zI=rP?NqZ7u%}abZ z6TjIT%7Z}*yGT4m^pwAYz)8%fk=ixTE#$?+Aw=cyK7akWkx+d1vy(F(N59^Paq6`t zfR4J8Ci?#9M3^s7sK&7YjqhxDQM5RIZiF$gLdu(7o6U7dAe%P9B0!lD>MT;0?cCih z8jYr+*Q77S!1(C`g$O3Pz2vpY3YsOIvm{2};DR}6-dx!5QASpO(dZ7BkV~urTBv8l zf$?_G5q_%FyGxaGMbSM!60)Z^5xc`zV?8cGK{E2JrXuD+Zw~tx)>kSMPItzHZY`e| zoOFu=r3!>HBtqE;zM6eei-;Qv*^A|pTU#K6Vb~LM z-*+}=-Xby6peX!|YFjtt^-OkGL)#1clJCB4EG*h=&X#pgIp%F!ujFpM4%o75X?|dl zAhh1$R9#0ju@(iLieTcxRWk-lsP<$nev;*(H=!n<;XoJZfhI)liY%FgfLbH zEK$$3VDlG>>kRU23KJ@3R!JNRbIR2-&WVGNMhY~bKb?G#Lib>#_ss7~9k3pv8}luy;~Y}wwhApBVBN6jMGaZSG${zX{E>;{k-t$+n!$`C z=olkYaeMe+wwdVkabZ;VHxuU7QON+HW~sxHy5-OG*hK$lv)X5!JA z+-+CjrjlQ5QMB_oOBg(-YuBf_3h(C(E*;qo2YGkr3-R zYR8Ajm_*W1S7q=xV+kX4pgzEOdSUeLQ$kl_)Ef&NiWj=cMlVcpskb;ZrUOd#)N3oP zGaUsA(BK<+gBUuYzK5ow?W0N@0_l7O6m8YK>JA&q(sj<%hX_{Rw76`j3ivtAmK+p( zTbljWd1T65a;8)#DZT|X(bJ>BKA*}62k;b%nwmofD8BRa-|55Muo(laZmAX)76f zaMg%yvD0<1L_E~+tf8De9eS?AJ>n(Lg$Sp^8WiJ^Gzs}sd5ch^b<2230<$Zm>pOMG z`t%_-S&q^d5c>VzW@1w8XRf5(~WB@=`9{@mkTqvBJ zJ#0*!z~?B7I(yOcl20F^x*rVk15iUb>epJ_?Q2ZAn-k?q}@}Q{`%`83tlGptH64%|V=X|JpEy?cWTWiH6&xpWD z%U!0&hR?~sct@GklUZuIYUg}+RiyN^b?4riN8TA9`gV)ry#x5iX5(XN*EKr7yOx;XSR+HLxP-IBjJmC_K`f7%j z@X%4x!|4al20Cg(sFb>TveF9U{I~8**y-ICKlPpNMeWVrvsIK*qBIdyk|67j?(&ds z#}2yyzX`Nugdh<%c^n9LsIlb}T+Vt38+WSYaN=Z=J ztmo8~C&Ktco3|vf23Pfajf!fL{Wy{sHm4862Cx7++;+e8(XC6`+}ZLJ|ctpLg}hZNOCxA%;aWbBDvkA3h)2RT&% zO}pp)sSvY^g{Lt*hN#BW7(XGoNWVXdpEwIc5Zsk-z$=7C54a4qepZu9bG%Uc`1}^M zU|ECNZdImm!*Exzc5$m2!{M)DoK7R98{hKRT{4G(##tCVm4;dEI*d+y(aM$eHfKC` zv(AGY)V+~xW@v6muDXcyr7x!}CSx6Ou_2{OV0c83O9#6Uj0gR)s~2YzaPill;^SW~ zlgp-lYoD^bP@*F<4=n^OEwrZ9cG89g4P=;%9EeIOQ`Unsj1DuR{wzvX)m0sfZ`e*{ zYkbg{7BB`l+|_|?q|0%-!@F$yr8(dynSZJ^`vu$ z5A`1foP;+4hTN@~{^nJ8envdqDcrQ?DX0M#A5cdGBYP9?rkxfwbzw-l^%X8;^NX8= zg~rykP#K}E?YYfK2T|%10X5O^Lrld^Nc^&dx>xsPWiD@&M>o3N0!;%E>9Hm=HE{<0 z#QPW#je?cT5~&8#m6Hs*TXS=szZ+)f3|BVU#HQ(+V3vzjmrxL1-x>>sDm9mfjitzC zgK&J_DOUeKjuun{`n zgvVJ6A3N5Svk5$KyHBB|EK1M~a%T~p7)qWU8!i3iGd{(7K_tEJThD_?0F?^($E=;{&CFs`R?r4cDEp9$3zW<5};O89EVw(f{ z5gW2|yHgg2cz>PaAi6Q&sS2)wwDo9P6yKTAy|juI|B-vIQ-`m&I$EO6Ex@TO?W!RIeJ!J5$%?lWpgu;^KBRsS5#%Q!i2vR@8#!tb><*N&K8Od z(a-^Ch7XlI8etF1$;f<(<}0?!9BN~HPwwgiR*WcLnzdJd0KL0e7&VsJc}Hqw97LCLXVV{0#<_)`Y`g9m?QmrlA~c9noX}#w++srcji4 z%AgIhhM>}6K+z3Gw@`9yeIc459R>?-7^?^-0t`?gn>2Kq1}lD%H+$NOj@m!au_&K3 zdB(gr4;g+umi%3HXZ@4J8j2u@*`h^K!f60}Dw5PLS?85mO6*&Z^#l6QblGnhieq5IEO&(_s)B8U&D7S`DHg;#~dZ-(vu%4Dens=C-UxXrb;^cp#Vc4)Nh_HG7&X*AQ!UyG5828SoGR6@e z{<|wWl%*@8+^f-ynwwFx_SbmFA|A;TF<*9^%#vT9Z*BD_nWM_-c^@uq2?!3vydyr4 z&-lT6GowGc-$ueN)*p`1ArRl8Ul{$sem8tmv%H+)bJ-B{Bp)?6ijXxk-uZldu_pQf zO=*RfF<8vv{)@zWKZhFaXm>kzv#^Qjpi9!-JX(A#Vsh4JbYo1U0XdXGSi}_JW3~|J zSSX?H?zE!qFk%WEq~DH2Mlgr@cTT_FZDqg{SpXBN`67m(@yX(v-%IGYi*>L{i2;v) z;L@OyV-RD~FFEqC%z*Z*QHE&jc|O`) zqy2#Lbybn%1$p=6>FSpv0aOH4_^>T=8buFcloB))^M=>wxBY9OLA?R=-JPdzN97+J z30Q@EZdZ2KQ00BE=-x09c6?7~L^e{r4^~N3DqXFH6r}TCtJ}45zZC|hAX&j?d}3u) zvI6LBF~{QLjsUv=;V7|Ev8k0OR4~XNzZ(CE5RTIJFHCj2guI81KOS5~Gd+1h%wLY%P>%P1(?|Vx?nN z9gAfgqU&G{Q0IoF=;Z1K*nS!Y*hS&x!jA;*L(@UYvbBii!4h_|p$lLh_w{L3;8r7S z(|IdJ(<0tA&!zar9ok6}i`aZdZZ0BSZ#)niM-M>}!jL7xuL}9e4~GDP4u`xNZes&q z*d*U-E2gyYp;HH%u#Nh0iGBZ`;sCcMiQcqhq;N%&C0kgEsds5o7}e0XUB+YSGC6~y zMsY6j5k&Z;N1-^q(hi{k{K8$>QSUP)nHhLQV{~`~gdH|L&*%NnzDPaKMHA0niP3qZ z)=8*iyyqt8CN7hNah*LMN~b4sH4*(KQK$lmaeg~QqNGmo+^+`D=%}bW9w1` z({0ZOpF8~w)ktww#Q=w$S`!IJuj4ihd$=rr-jg7hIvX>|YJ73LN!Ea$4odiMG%6+8J|U93py0+QlN^DMRlIk1MIY zg_8{3%_N!B7CWSEgpX~S#8ytJ(IR)_R$Wn*|c1@JgH&c zHoxq^mZ7I&!e)AI-ZCnZKU}6>+0lcvTOdD=kE=h<wK1r4e-gNq%ou|=#Iye3ZgjaV7D3E(&gk&d=@pkS{yHv zbC5OyUGWB$0#<%rg%%rM;AJ^pt=n|0uM0AT(d9epOq9sJCAk;Ni_a#3%1f4sbtS3{ zJ9Qbl7Rqz{&CS8grNA2^08Nwm>ov*o5x1n~GIeL*vH+onT5V)C6nC4KNEZP|*3GGI zX}9;saJzd_3Kuj24#b3_h+MD3hI`b1zp})<+_8`Z-PY%T&bP4sdS$UN1e%&CI|D84 z%zwVQm`*Or1+wD#tvX>I_@6F_Jk(qIQCYP>w)(*~MM5J^jPO+I4ap%N7%nG97t%1H zF28v1bH(dwTokl`MSha~be=h#{^;obyb4!ShPk$aB(So3O2V<|;9vkxx!#+=h-!pR zR^Ed+t%gKrAtD}iaKtekE-CT5_rMy5*Gx~%h2^G`D%QNWgD#rpGd)qQ`(|$P=AiwP zZ~Ato&6qAvo10`@fQ9VxE-4R8_WfrWZ+DU_;`JNWc9T-FKUQ$-%#R2e^#G@M%SU_m z;Q}*s-h2A!;T9@zgo{+uYQG~IApVXnjw90;5^o~iM70_RlxoV;#b7B`pJdp^J`490 zZ_UwDtSkaQa-OAn%C;8hDOVQHOj`eZe9@Y{q+nmfJxQ>Qau)0fepIqAZkW{GW;#ps zly1!jJw9xme2*;m{dt)W#`v)g=u}Qzc@TvBGUz5B^$~gSUA>XLz4gy)cV%7sG*&F1 z_q7iOR~dMc7Ep*P+0f-m%Bq%$cJlFX)EY3LLzcYM^JViFn<0F%0=mmgt6} zknN!{?`qKao)JKHvS%v0BCpQ)STT{sAl4A7r^liRVIoxKjJ{VR!j*r{>kFyn*N>L? ziW5SVok1${djxmTR$9PYe1^SninvHpo+K)=l8PAXdEBC&cb`Pa(3Cmc6~`hd1+1+* zCrQaA-z3QCC)UQYYGK!shh&rcrENT!;X6=<5qXn8x2_T^5ahIX9Mu9z44q^9Em7@y z`u#k!*tm4;g(!c)928ZC_vc6?z5(Ep;Dk;BnKR4Xn?(F7mLOv3{Q2#sO!Lz*g2*;> ztsa+YG{yt(J+H4%i~60b+e-N90VMoZM4a{VWWR_W+C5|HSzIFmU$SX#*EY4 zYikuzWSne*i%z-PNL%(cX(m`C)nhA&Y6);r3=p>Ob8S;R^mf-+43I2qor3aEap;6@ z-aa~F-0I(tDS<~!12qT_rwaa z0-u-YL%o_|9eLigT-n=~?2N1krsTdDeZ~N?e1?ln40c4IckXOE+L<^kEbl1LMQHHA z?Nvxwxfv6RxXzno&Ph7R?}OS8Xa?sOKORh?Qd=3b zDwy!nA~RoeO~ST4IY4E}3bj3~e+z*UAz8(6a8OS&tC=W0Sqnwyh+vXsNUT>!J!4=` z_ZA9vONH$$QM^D4b(+XF(lh?YDBsr!vp?iwNJgp2beX-Y*K{2#Ux# z7yJFNZ+8M{Za^On_FffUoQza;)zX~}AnuK<{9qED^C{U{I%|uqZ)a>d`E+8;bqlK? z4FQSub2WZkDgLw!$T$E904b<%r~Qw1dK3Vv?EGXF~%I3^z(SQ)teqbT;@`u;471rtB&qxmP>Uq!NiLiA_Z=Wp&eAea87 z^zS0jKiU7RS^Uio2U?wfv;V4K{9ls>SLQu7@T85P|EkjiPxn8Y0{{bNF+j#&0 literal 0 HcmV?d00001 diff --git a/typex/version.go b/typex/version.go index 14c1f3fa7..317509fe1 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-10 22:25:13", + ReleaseTime: "2023-12-11 12:56:31", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-d739c102281e20c +** Version: v0.6.4-a4c602b67fb543d ** Document: https://hootrhino.github.io ` diff --git a/utils/uuid_util.go b/utils/uuid_util.go index 1009c9344..529e8a732 100644 --- a/utils/uuid_util.go +++ b/utils/uuid_util.go @@ -59,6 +59,10 @@ func UserLuaUuid() string { func ModbusPointUUID() string { return MakeUUID("MDTB") } +// MakeUUID +func SiemensPointUUID() string { + return MakeUUID("SIMTB") +} // MakeUUID func MakeUUID(prefix string) string { From fd939cd06baef2762f835127b32c30143a842980 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 11 Dec 2023 20:36:49 +0800 Subject: [PATCH 109/138] dev: fix s1200 status --- device/s1200plc_device.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index c9316dc40..e4383b994 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -144,6 +144,7 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { s1200.lock.Unlock() if err != nil { glogger.GLogger.Error(err) + s1200.status = typex.DEV_DOWN return } ok, err := s1200.RuleEngine.WorkDevice( @@ -179,10 +180,10 @@ func (s1200 *s1200plc) OnWrite(cmd []byte, data []byte) (int, error) { // 设备当前状态 func (s1200 *s1200plc) Status() typex.DeviceState { - if s1200.client != nil { - return typex.DEV_UP + if s1200.client == nil { + return typex.DEV_DOWN } - return typex.DEV_DOWN + return s1200.status } From 14fd2373f0a90fcd450ec9d50774688f08090737 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 11 Dec 2023 21:00:54 +0800 Subject: [PATCH 110/138] fix: fix missing 'type' param --- .../rulex_api_server/apis/device_s1200_data_sheet_api.go | 6 +++--- typex/version.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go index b6e677bc3..7bd864e41 100644 --- a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go @@ -44,7 +44,7 @@ type SiemensPointVo struct { Address *int `json:"address"` Start *int `json:"start"` Size *int `json:"size"` - Status *int `json:"status"` // 运行时数据 + Status int `json:"status"` // 运行时数据 LastFetchTime uint64 `json:"lastFetchTime"` // 运行时数据 Value string `json:"value"` // 运行时数据 } @@ -99,17 +99,17 @@ func SiemensSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { recordsVo := []SiemensPointVo{} for _, record := range records { - Status := 1 recordsVo = append(recordsVo, SiemensPointVo{ UUID: record.UUID, DeviceUUID: record.DeviceUuid, Tag: record.Tag, + Type: record.Type, Alias: record.Alias, Address: record.Address, Frequency: record.Frequency, Start: record.Start, Size: record.Size, - Status: &Status, // 运行时 + Status: 1, // 运行时 LastFetchTime: uint64(time.Now().UnixMilli()), // 运行时 Value: "00000000", // 运行时 }) diff --git a/typex/version.go b/typex/version.go index 317509fe1..ee197640d 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-11 12:56:31", + ReleaseTime: "2023-12-11 20:57:21", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-a4c602b67fb543d +** Version: v0.6.4-fd939cd06baef27 ** Document: https://hootrhino.github.io ` From 19b0e24ce3a0e75369048ca774f6fc8d74e3aa08 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 12 Dec 2023 00:53:28 +0800 Subject: [PATCH 111/138] dev: add realtime data value for s1200/modbus --- common/modbus_config.go | 18 +- component/rulex_api_server/apis/device_api.go | 8 +- device/generic_modbus_device.go | 283 +++++++++++++++--- device/s1200plc_device.go | 69 +++-- driver/modbus_rtu_driver.go | 13 +- driver/modbus_tcp_driver.go | 4 +- test/apps/s1200_parse_float.lua | 23 ++ typex/version.go | 4 +- 8 files changed, 324 insertions(+), 98 deletions(-) create mode 100644 test/apps/s1200_parse_float.lua diff --git a/common/modbus_config.go b/common/modbus_config.go index a2de155f9..68b3a98af 100644 --- a/common/modbus_config.go +++ b/common/modbus_config.go @@ -39,14 +39,16 @@ type Registers struct { * */ type RegisterRW struct { - Tag string `json:"tag" validate:"required" title:"数据Tag"` // 数据Tag - Alias string `json:"alias" validate:"required" title:"别名"` // 别名 - Function int `json:"function" validate:"required" title:"Modbus功能"` // Function - SlaverId byte `json:"slaverId" validate:"required" title:"从机ID"` // 从机ID - Address uint16 `json:"address" validate:"required" title:"地址"` // Address - Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` // 间隔 - Quantity uint16 `json:"quantity" validate:"required" title:"数量"` // Quantity - Value string `json:"value" title:"值" info:"本地系统的串口路径"` // Value + Tag string `json:"tag" validate:"required" title:"数据Tag"` // 数据Tag + Alias string `json:"alias" validate:"required" title:"别名"` // 别名 + Function int `json:"function" validate:"required" title:"Modbus功能"` // Function + SlaverId byte `json:"slaverId" validate:"required" title:"从机ID"` // 从机ID + Address uint16 `json:"address" validate:"required" title:"地址"` // Address + Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` // 间隔 + Quantity uint16 `json:"quantity" validate:"required" title:"数量"` // Quantity + Status int `json:"status"` // 运行时数据 + LastFetchTime uint64 `json:"lastFetchTime"` // 运行时数据 + Value string `json:"value"` // 运行时数据 } /* diff --git a/component/rulex_api_server/apis/device_api.go b/component/rulex_api_server/apis/device_api.go index 8096845f7..1d29cc77f 100644 --- a/component/rulex_api_server/apis/device_api.go +++ b/component/rulex_api_server/apis/device_api.go @@ -117,8 +117,9 @@ func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { return } } + // 西门子的 if Mdev.Type == "S1200PLC" { - if err := service.DeleteAllModbusPointByDevice(uuid); err != nil { + if err := service.DeleteAllSiemensPointByDevice(uuid); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } @@ -129,6 +130,11 @@ func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { old.Device.Stop() } } + err1 := service.DeleteDevice(uuid) + if err1 != nil { + c.JSON(common.HTTP_OK, common.Error400(err1)) + return + } ruleEngine.RemoveDevice(uuid) c.JSON(common.HTTP_OK, common.Ok()) diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index eb715056d..1389518f3 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -17,6 +17,9 @@ package device import ( "context" + "encoding/binary" + "encoding/hex" + "encoding/json" "errors" "fmt" golog "log" @@ -27,7 +30,6 @@ import ( "github.com/hootrhino/rulex/component/hwportmanager" "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/core" - "github.com/hootrhino/rulex/driver" "github.com/hootrhino/rulex/glogger" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" @@ -57,8 +59,8 @@ import ( // } // } type _GMODCommonConfig struct { - Mode string `json:"mode" title:"工作模式" info:"UART/TCP"` - AutoRequest *bool `json:"autoRequest" title:"启动轮询"` + Mode string `json:"mode"` + AutoRequest *bool `json:"autoRequest"` } type _GMODConfig struct { CommonConfig _GMODCommonConfig `json:"commonConfig" validate:"required"` @@ -84,15 +86,17 @@ type ModbusPoint struct { } type generic_modbus_device struct { typex.XStatus - status typex.DeviceState - RuleEngine typex.RuleX - driver typex.XExternalDriver - rtuHandler *modbus.RTUClientHandler - tcpHandler *modbus.TCPClientHandler + status typex.DeviceState + RuleEngine typex.RuleX + // + rtuHandler *modbus.RTUClientHandler + tcpHandler *modbus.TCPClientHandler + Client modbus.Client + // mainConfig _GMODConfig retryTimes int hwPortConfig hwportmanager.UartConfig - Registers []common.RegisterRW + Registers map[string]*common.RegisterRW } /* @@ -113,6 +117,7 @@ func NewGenericModbusDevice(e typex.RuleX) typex.XDevice { PortUuid: "/dev/ttyS0", HostConfig: common.HostConfig{Host: "127.0.0.1", Port: 502, Timeout: 3000}, } + mdev.Registers = map[string]*common.RegisterRW{} mdev.Busy = false mdev.status = typex.DEV_DOWN return mdev @@ -139,16 +144,15 @@ func (mdev *generic_modbus_device) Init(devId string, configMap map[string]inter if v.Frequency < 50 { return errors.New("'frequency' must grate than 50 millisecond") } - mdev.Registers = append(mdev.Registers, - common.RegisterRW{ - Tag: v.Tag, - Alias: v.Alias, - Function: v.Function, - SlaverId: v.SlaverId, - Address: v.Address, - Quantity: v.Quantity, - Frequency: v.Frequency, - }) + mdev.Registers[v.UUID] = &common.RegisterRW{ + Tag: v.Tag, + Alias: v.Alias, + Function: v.Function, + SlaverId: v.SlaverId, + Address: v.Address, + Quantity: v.Quantity, + Frequency: v.Frequency, + } } if mdev.mainConfig.CommonConfig.Mode == "UART" { @@ -207,11 +211,7 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { Type: "DEVICE", Name: mdev.Details().Name, }) - client := modbus.NewClient(mdev.rtuHandler) - mdev.driver = driver.NewModBusRtuDriver(mdev.Details(), - mdev.RuleEngine, - mdev.Registers, mdev.rtuHandler, - client) + mdev.Client = modbus.NewClient(mdev.rtuHandler) } if mdev.mainConfig.CommonConfig.Mode == "TCP" { mdev.tcpHandler = modbus.NewTCPClientHandler( @@ -224,16 +224,14 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { if err := mdev.tcpHandler.Connect(); err != nil { return err } - client := modbus.NewClient(mdev.tcpHandler) - mdev.driver = driver.NewModBusTCPDriver(mdev.Details(), - mdev.RuleEngine, mdev.Registers, mdev.tcpHandler, client) + mdev.Client = modbus.NewClient(mdev.tcpHandler) } //--------------------------------------------------------------------------------- // Start //--------------------------------------------------------------------------------- if *mdev.mainConfig.CommonConfig.AutoRequest { mdev.retryTimes = 0 - go func(ctx context.Context, Driver typex.XExternalDriver) { + go func(ctx context.Context) { buffer := make([]byte, common.T_64KB) for { select { @@ -245,7 +243,14 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { { } } - n, err := Driver.Read([]byte{}, buffer) + n := 0 + var err error + if mdev.mainConfig.CommonConfig.Mode == "TCP" { + n, err = mdev.RTURead(buffer) + } + if mdev.mainConfig.CommonConfig.Mode == "RTU" { + n, err = mdev.TCPRead(buffer) + } if err != nil { glogger.GLogger.Error(err) mdev.retryTimes++ @@ -256,7 +261,7 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { } } - }(mdev.Ctx, mdev.driver) + }(mdev.Ctx) } mdev.status = typex.DEV_UP @@ -265,21 +270,75 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { // 从设备里面读数据出来 func (mdev *generic_modbus_device) OnRead(cmd []byte, data []byte) (int, error) { - - n, err := mdev.driver.Read(cmd, data) - if err != nil { - glogger.GLogger.Error(err) - mdev.retryTimes++ - } - return n, err + return 0, nil } // 把数据写入设备 func (mdev *generic_modbus_device) OnWrite(cmd []byte, data []byte) (int, error) { - if mdev.Busy { - return 0, fmt.Errorf("device busing now") + RegisterW := common.RegisterW{} + if err := json.Unmarshal(data, &RegisterW); err != nil { + return 0, err } - return mdev.driver.Write(cmd, data) + dataMap := [1]common.RegisterW{RegisterW} + for _, r := range dataMap { + if mdev.mainConfig.CommonConfig.Mode == "TCP" { + mdev.tcpHandler.SlaveId = r.SlaverId + } + if mdev.mainConfig.CommonConfig.Mode == "RTU" { + mdev.rtuHandler.SlaveId = r.SlaverId + } + // 5 + if r.Function == common.WRITE_SINGLE_COIL { + if len(r.Values) > 0 { + if r.Values[0] == 0 { + _, err := mdev.Client.WriteSingleCoil(r.Address, + binary.BigEndian.Uint16([]byte{0x00, 0x00})) + if err != nil { + return 0, err + } + } + if r.Values[0] == 1 { + _, err := mdev.Client.WriteSingleCoil(r.Address, + binary.BigEndian.Uint16([]byte{0xFF, 0x00})) + if err != nil { + return 0, err + } + } + + } + + } + // 15 + if r.Function == common.WRITE_MULTIPLE_COILS { + _, err := mdev.Client.WriteMultipleCoils(r.Address, r.Quantity, r.Values) + if err != nil { + return 0, err + } + } + // 6 + if r.Function == common.WRITE_SINGLE_HOLDING_REGISTER { + _, err := mdev.Client.WriteSingleRegister(r.Address, binary.BigEndian.Uint16(r.Values)) + if err != nil { + return 0, err + } + } + // 16 + if r.Function == common.WRITE_MULTIPLE_HOLDING_REGISTERS { + + _, err := mdev.Client.WriteMultipleRegisters(r.Address, + uint16(len(r.Values))/2, maybePrependZero(r.Values)) + if err != nil { + return 0, err + } + } + } + return 0, nil +} +func maybePrependZero(slice []byte) []byte { + if len(slice)%2 != 0 { + slice = append([]byte{0}, slice...) + } + return slice } // 设备当前状态 @@ -293,13 +352,17 @@ func (mdev *generic_modbus_device) Status() typex.DeviceState { // 停止设备 func (mdev *generic_modbus_device) Stop() { - mdev.CancelCTX() mdev.status = typex.DEV_DOWN - if mdev.driver != nil { - mdev.driver.Stop() - } + mdev.CancelCTX() if mdev.mainConfig.CommonConfig.Mode == "UART" { hwportmanager.FreeInterfaceBusy(mdev.mainConfig.PortUuid) + mdev.rtuHandler.Close() + } + if mdev.mainConfig.CommonConfig.Mode == "UART" { + mdev.rtuHandler.Close() + } + if mdev.mainConfig.CommonConfig.Mode == "TCP" { + mdev.tcpHandler.Close() } } @@ -320,11 +383,139 @@ func (mdev *generic_modbus_device) SetState(status typex.DeviceState) { // 驱动 func (mdev *generic_modbus_device) Driver() typex.XExternalDriver { - return mdev.driver + return nil } func (mdev *generic_modbus_device) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { return typex.DCAResult{} } -func (mdev *generic_modbus_device) OnCtrl(cmd []byte, args []byte) ([]byte, error) { +func (mdev *generic_modbus_device) OnCtrl([]byte, []byte) ([]byte, error) { return []byte{}, nil } + +/* +* +* 串口模式 +* + */ +func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { + var err error + var results []byte + dataMap := map[string]common.RegisterRW{} + count := len(mdev.Registers) + if count == 0 { + return 0, nil + } + if mdev.Client == nil { + return 0, fmt.Errorf("modbus client id not valid") + } + for uuid, r := range mdev.Registers { + if mdev.mainConfig.CommonConfig.Mode == "TCP" { + mdev.tcpHandler.SlaveId = r.SlaverId + } + if mdev.mainConfig.CommonConfig.Mode == "RTU" { + mdev.rtuHandler.SlaveId = r.SlaverId + } + if r.Function == common.READ_COIL { + results, err = mdev.Client.ReadCoils(r.Address, r.Quantity) + if err != nil { + count-- + mdev.Registers[uuid].Status = 0 + glogger.GLogger.Error(err) + } + Value := covertEmptyHex(results) + value := common.RegisterRW{ + Tag: r.Tag, + Function: r.Function, + SlaverId: r.SlaverId, + Address: r.Address, + Quantity: r.Quantity, + Alias: r.Alias, + Value: Value, + } + mdev.Registers[uuid].Value = Value + mdev.Registers[uuid].Status = 1 + mdev.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) + dataMap[r.Tag] = value + } + if r.Function == common.READ_DISCRETE_INPUT { + results, err = mdev.Client.ReadDiscreteInputs(r.Address, r.Quantity) + if err != nil { + count-- + glogger.GLogger.Error(err) + } + Value := covertEmptyHex(results) + value := common.RegisterRW{ + Tag: r.Tag, + Function: r.Function, + SlaverId: r.SlaverId, + Address: r.Address, + Quantity: r.Quantity, + Alias: r.Alias, + Value: Value, + } + mdev.Registers[uuid].Value = Value + mdev.Registers[uuid].Status = 1 + mdev.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) + dataMap[r.Tag] = value + + } + if r.Function == common.READ_HOLDING_REGISTERS { + results, err = mdev.Client.ReadHoldingRegisters(r.Address, r.Quantity) + if err != nil { + count-- + glogger.GLogger.Error(err) + } + Value := covertEmptyHex(results) + value := common.RegisterRW{ + Tag: r.Tag, + Function: r.Function, + SlaverId: r.SlaverId, + Address: r.Address, + Quantity: r.Quantity, + Alias: r.Alias, + Value: Value, + } + mdev.Registers[uuid].Value = Value + mdev.Registers[uuid].Status = 1 + mdev.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) + dataMap[r.Tag] = value + } + if r.Function == common.READ_INPUT_REGISTERS { + results, err = mdev.Client.ReadInputRegisters(r.Address, r.Quantity) + if err != nil { + count-- + glogger.GLogger.Error(err) + } + Value := covertEmptyHex(results) + value := common.RegisterRW{ + Tag: r.Tag, + Function: r.Function, + SlaverId: r.SlaverId, + Address: r.Address, + Quantity: r.Quantity, + Alias: r.Alias, + Value: Value, + } + mdev.Registers[uuid].Value = Value + mdev.Registers[uuid].Status = 1 + mdev.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) + dataMap[r.Tag] = value + } + time.Sleep(time.Duration(r.Frequency) * time.Millisecond) + } + bytes, _ := json.Marshal(dataMap) + copy(buffer, bytes) + return len(bytes), nil +} +func (mdev *generic_modbus_device) RTURead(buffer []byte) (int, error) { + return mdev.modbusRead(buffer) +} +func (mdev *generic_modbus_device) TCPRead(buffer []byte) (int, error) { + return mdev.modbusRead(buffer) +} +func covertEmptyHex(v []byte) string { + if len(v) < 1 { + return "" + } + return hex.EncodeToString(v) +} diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index e4383b994..ad1bd3a3c 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -18,15 +18,17 @@ import ( // 点位表 type SiemensDataPoint struct { - UUID string `json:"uuid"` // 当UUID为空时新建 - DeviceUuid string `json:"device_uuid"` - Tag string `json:"tag,omitempty"` - Type string `json:"type,omitempty"` - Frequency *int64 `json:"frequency,omitempty"` - Address *int `json:"address,omitempty"` - Start *int `json:"start,omitempty"` - Size *int `json:"size,omitempty"` - Value string `json:"value"` // 采集到的值 + UUID string `json:"uuid"` // 当UUID为空时新建 + DeviceUuid string `json:"device_uuid"` + Tag string `json:"tag,omitempty"` + Type string `json:"type,omitempty"` + Frequency *int64 `json:"frequency,omitempty"` + Address *int `json:"address,omitempty"` + Start *int `json:"start"` + Size *int `json:"size"` + Status int `json:"status"` // 运行时数据 + LastFetchTime uint64 `json:"lastFetchTime"` // 运行时数据 + Value string `json:"value"` // 运行时数据 } type S1200CommonConfig struct { @@ -50,7 +52,7 @@ type s1200plc struct { mainConfig S1200Config client gos7.Client lock sync.Mutex - SiemensDataPoints []SiemensDataPoint + SiemensDataPoints map[string]*SiemensDataPoint } /* @@ -76,6 +78,7 @@ func NewS1200plc(e typex.RuleX) typex.XDevice { AutoRequest: &AutoRequest, }, } + s1200.SiemensDataPoints = map[string]*SiemensDataPoint{} return s1200 } @@ -98,7 +101,7 @@ func (s1200 *s1200plc) Init(devId string, configMap map[string]interface{}) erro if *v.Frequency < 50 { return errors.New("'frequency' must grate than 50 millisecond") } - s1200.SiemensDataPoints = append(s1200.SiemensDataPoints, v) + s1200.SiemensDataPoints[v.UUID] = &v } return nil } @@ -118,6 +121,8 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { *s1200.mainConfig.CommonConfig.IdleTimeout) * time.Millisecond if err := handler.Connect(); err != nil { return err + } else { + s1200.status = typex.DEV_UP } s1200.client = gos7.NewClient(handler) @@ -222,22 +227,6 @@ func (s1200 *s1200plc) OnCtrl(cmd []byte, args []byte) ([]byte, error) { return []byte{}, nil } func (s1200 *s1200plc) Write(cmd []byte, data []byte) (int, error) { - blocks := []SiemensDataPoint{} - if err := json.Unmarshal(data, &blocks); err != nil { - return 0, err - } - // - for _, block := range blocks { - hexV, _ := hex.DecodeString(block.Value) - if err := s1200.client.AGWriteDB( - *block.Address, - *block.Start, - *block.Size, - hexV, - ); err != nil { - return 0, err - } - } return 0, nil } @@ -247,25 +236,31 @@ var rData = [common.T_2KB]byte{} // 一次最大接受2KB数据 func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { values := []SiemensDataPoint{} - for _, db := range s1200.SiemensDataPoints { + for uuid, db := range s1200.SiemensDataPoints { //DB 4字节 if db.Type == "DB" { // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 if err := s1200.client.AGReadDB(*db.Address, *db.Start, *db.Size, rData[:]); err != nil { + s1200.SiemensDataPoints[uuid].Status = 0 return 0, err } count := db.Size if *db.Size*2 > 2000 { *count = 2000 } + Value := hex.EncodeToString(rData[:*count]) values = append(values, SiemensDataPoint{ - Tag: db.Tag, - Address: db.Address, - Type: db.Type, - Start: db.Start, - Size: db.Size, - Value: hex.EncodeToString(rData[:*count]), + DeviceUuid: db.DeviceUuid, + Tag: db.Tag, + Address: db.Address, + Type: db.Type, + Start: db.Start, + Size: db.Size, + Value: Value, }) + s1200.SiemensDataPoints[uuid].Value = Value + s1200.SiemensDataPoints[uuid].Status = 1 + s1200.SiemensDataPoints[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) } // if db.Type == "MB" { @@ -277,14 +272,18 @@ func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { if *db.Size*2 > 2000 { *count = 2000 } + Value := hex.EncodeToString(rData[:*count]) values = append(values, SiemensDataPoint{ Tag: db.Tag, Type: db.Type, Address: db.Address, Start: db.Start, Size: db.Size, - Value: hex.EncodeToString(rData[:*count]), + Value: Value, }) + s1200.SiemensDataPoints[uuid].Value = Value + s1200.SiemensDataPoints[uuid].Status = 1 + s1200.SiemensDataPoints[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) } if *db.Frequency < 100 { *db.Frequency = 100 // 不能太快 diff --git a/driver/modbus_rtu_driver.go b/driver/modbus_rtu_driver.go index c73f0c4aa..9060e59d4 100644 --- a/driver/modbus_rtu_driver.go +++ b/driver/modbus_rtu_driver.go @@ -21,7 +21,7 @@ type modBusRtuDriver struct { handler *modbus.RTUClientHandler client modbus.Client RuleEngine typex.RuleX - Registers []common.RegisterRW + Registers map[string]*common.RegisterRW device *typex.Device frequency int64 } @@ -29,7 +29,7 @@ type modBusRtuDriver struct { func NewModBusRtuDriver( d *typex.Device, e typex.RuleX, - Registers []common.RegisterRW, + Registers map[string]*common.RegisterRW, handler *modbus.RTUClientHandler, client modbus.Client) typex.XExternalDriver { return &modBusRtuDriver{ @@ -66,14 +66,16 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { if count == 0 { return 0, nil } - for _, r := range d.Registers { + for uuid, r := range d.Registers { d.handler.SlaveId = r.SlaverId if r.Function == common.READ_COIL { results, err = d.client.ReadCoils(r.Address, r.Quantity) if err != nil { count-- + d.Registers[uuid].Status = 0 glogger.GLogger.Error(err) } + Value := covertEmptyHex(results) value := common.RegisterRW{ Tag: r.Tag, Function: r.Function, @@ -81,8 +83,11 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { Address: r.Address, Quantity: r.Quantity, Alias: r.Alias, - Value: covertEmptyHex(results), + Value: Value, } + d.Registers[uuid].Value = Value + d.Registers[uuid].Status = 1 + d.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) dataMap[r.Tag] = value } if r.Function == common.READ_DISCRETE_INPUT { diff --git a/driver/modbus_tcp_driver.go b/driver/modbus_tcp_driver.go index 562caa037..a30b52b52 100644 --- a/driver/modbus_tcp_driver.go +++ b/driver/modbus_tcp_driver.go @@ -21,7 +21,7 @@ type modBusTCPDriver struct { handler *modbus.TCPClientHandler client modbus.Client RuleEngine typex.RuleX - Registers []common.RegisterRW + Registers map[string]*common.RegisterRW device *typex.Device frequency int64 } @@ -29,7 +29,7 @@ type modBusTCPDriver struct { func NewModBusTCPDriver( d *typex.Device, e typex.RuleX, - Registers []common.RegisterRW, + Registers map[string]*common.RegisterRW, handler *modbus.TCPClientHandler, client modbus.Client) typex.XExternalDriver { return &modBusTCPDriver{ diff --git a/test/apps/s1200_parse_float.lua b/test/apps/s1200_parse_float.lua new file mode 100644 index 000000000..32a478c8f --- /dev/null +++ b/test/apps/s1200_parse_float.lua @@ -0,0 +1,23 @@ +-- Copyright (C) 2023 wwhai +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU Affero 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 Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + +-- 003e 004c 00cc 00cd +function Main(arg) + local HexS = "3e4ccccd" + stdlib:Debug("Bin2F32Big:" .. HexS .. "->" .. binary:Bin2F32Big(HexS)) + -- 8.9 + stdlib:Debug("Bin2F32Little:" .. HexS .. "->" .. binary:Bin2F32Little(HexS)) + return 0 +end diff --git a/typex/version.go b/typex/version.go index ee197640d..1d9ed48c1 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-11 20:57:21", + ReleaseTime: "2023-12-11 21:42:05", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-fd939cd06baef27 +** Version: v0.6.4-14fd2373f0a90fc ** Document: https://hootrhino.github.io ` From 47162a31b8c6617105af09db733f794a47b5be5e Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 12 Dec 2023 22:14:08 +0800 Subject: [PATCH 112/138] dev: enhancement modbus, plc1200 --- component/rulex_api_server/apis/device_api.go | 12 +++++++++ .../apis/device_modbus_data_sheet_api.go | 21 ++++++++++----- .../apis/device_s1200_data_sheet_api.go | 15 ++++++++--- component/rulex_api_server/apis/inend_api.go | 10 +++++++ component/rulex_api_server/apis/outend_api.go | 10 +++++++ component/rulex_api_server/http_api_server.go | 8 +++--- device/generic_modbus_device.go | 6 ++--- device/s1200plc_device.go | 3 +++ engine/engine.go | 25 +++++++++++++----- test/data/test-modbus-sheet.xlsx | Bin 11914 -> 11908 bytes typex/version.go | 4 +-- 11 files changed, 90 insertions(+), 24 deletions(-) diff --git a/component/rulex_api_server/apis/device_api.go b/component/rulex_api_server/apis/device_api.go index 1d29cc77f..023da91ca 100644 --- a/component/rulex_api_server/apis/device_api.go +++ b/component/rulex_api_server/apis/device_api.go @@ -85,6 +85,18 @@ func ListDeviceByGroup(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.OkWithData(devices)) } +// 重启 +func RestartDevice(c *gin.Context, ruleEngine typex.RuleX) { + uuid, _ := c.GetQuery("uuid") + err := ruleEngine.RestartDevice(uuid) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) + +} + // 删除设备 func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { uuid, _ := c.GetQuery("uuid") diff --git a/component/rulex_api_server/apis/device_modbus_data_sheet_api.go b/component/rulex_api_server/apis/device_modbus_data_sheet_api.go index b8f0d1bc6..1816432c5 100644 --- a/component/rulex_api_server/apis/device_modbus_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_modbus_data_sheet_api.go @@ -138,6 +138,7 @@ func ModbusSheetDeleteAll(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } + ruleEngine.RestartDevice(form.DeviceUUID) c.JSON(common.HTTP_OK, common.Ok()) } @@ -156,6 +157,7 @@ func ModbusSheetDelete(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } + ruleEngine.RestartDevice(form.DeviceUUID) c.JSON(common.HTTP_OK, common.Ok()) } @@ -166,13 +168,18 @@ func ModbusSheetDelete(c *gin.Context, ruleEngine typex.RuleX) { * */ func ModbusSheetUpdate(c *gin.Context, ruleEngine typex.RuleX) { - ModbusDataPoints := []ModbusPointVo{} - err := c.ShouldBindJSON(&ModbusDataPoints) + type Form struct { + DeviceUUID string `json:"device_uuid"` + ModbusDataPoints []ModbusPointVo `json:"modbus_data_points"` + } + // ModbusDataPoints := []ModbusPointVo{} + form := Form{} + err := c.ShouldBindJSON(&form) if err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } - for _, ModbusDataPoint := range ModbusDataPoints { + for _, ModbusDataPoint := range form.ModbusDataPoints { if ModbusDataPoint.UUID == "" { NewRow := model.MModbusDataPoint{} copier.Copy(&NewRow, &ModbusDataPoint) @@ -195,6 +202,7 @@ func ModbusSheetUpdate(c *gin.Context, ruleEngine typex.RuleX) { } } } + ruleEngine.RestartDevice(form.DeviceUUID) c.JSON(common.HTTP_OK, common.Ok()) } @@ -253,6 +261,7 @@ func ModbusSheetImport(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } + ruleEngine.RestartDevice(deviceUuid) c.JSON(common.HTTP_OK, common.Ok()) } @@ -273,7 +282,7 @@ func parseModbusPointExcel( return nil, err } // 判断首行标头 - // tag, alias, function, frequency, slaverId, startAddress, quality + // tag, alias, function, frequency, slaverId, address, quality err1 := errors.New("invalid Sheet Header") if len(rows[0]) < 7 { return nil, err1 @@ -283,13 +292,13 @@ func parseModbusPointExcel( rows[0][2] != "function" || rows[0][3] != "frequency" || rows[0][4] != "slaverId" || - rows[0][5] != "startAddress" || + rows[0][5] != "address" || rows[0][6] != "quality" { return nil, err1 } list = make([]model.MModbusDataPoint, 0) - // tag, alias, function, frequency, slaverId, startAddress, quality + // tag, alias, function, frequency, slaverId, address, quality for i := 1; i < len(rows); i++ { row := rows[i] tag := row[0] diff --git a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go index 7bd864e41..9939d1657 100644 --- a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go @@ -138,6 +138,7 @@ func SiemensSheetDeleteAll(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } + ruleEngine.RestartDevice(form.DeviceUUID) c.JSON(common.HTTP_OK, common.Ok()) } @@ -156,6 +157,7 @@ func SiemensSheetDelete(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } + ruleEngine.RestartDevice(form.DeviceUUID) c.JSON(common.HTTP_OK, common.Ok()) } @@ -166,13 +168,18 @@ func SiemensSheetDelete(c *gin.Context, ruleEngine typex.RuleX) { * */ func SiemensSheetUpdate(c *gin.Context, ruleEngine typex.RuleX) { - SiemensDataPoints := []SiemensPointVo{} - err := c.ShouldBindJSON(&SiemensDataPoints) + type Form struct { + DeviceUUID string `json:"device_uuid"` + SiemensDataPoints []SiemensPointVo `json:"siemens_data_points"` + } + form := Form{} + // SiemensDataPoints := []SiemensPointVo{} + err := c.ShouldBindJSON(&form) if err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } - for _, SiemensDataPoint := range SiemensDataPoints { + for _, SiemensDataPoint := range form.SiemensDataPoints { if SiemensDataPoint.UUID == "" { NewRow := model.MSiemensDataPoint{} copier.Copy(&NewRow, &SiemensDataPoint) @@ -195,6 +202,7 @@ func SiemensSheetUpdate(c *gin.Context, ruleEngine typex.RuleX) { } } } + ruleEngine.RestartDevice(form.DeviceUUID) c.JSON(common.HTTP_OK, common.Ok()) } @@ -253,6 +261,7 @@ func SiemensSheetImport(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } + ruleEngine.RestartDevice(deviceUuid) c.JSON(common.HTTP_OK, common.Ok()) } diff --git a/component/rulex_api_server/apis/inend_api.go b/component/rulex_api_server/apis/inend_api.go index 20139b800..f7e842bca 100644 --- a/component/rulex_api_server/apis/inend_api.go +++ b/component/rulex_api_server/apis/inend_api.go @@ -122,6 +122,16 @@ func CreateInend(c *gin.Context, ruleEngine typex.RuleX) { } c.JSON(common.HTTP_OK, common.Ok()) +} +func RestartInEnd(c *gin.Context, ruleEngine typex.RuleX) { + uuid, _ := c.GetQuery("uuid") + err := ruleEngine.RestartInEnd(uuid) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) + } /* diff --git a/component/rulex_api_server/apis/outend_api.go b/component/rulex_api_server/apis/outend_api.go index 38eb8a1cb..6c2d0e33e 100644 --- a/component/rulex_api_server/apis/outend_api.go +++ b/component/rulex_api_server/apis/outend_api.go @@ -144,6 +144,16 @@ func CreateOutEnd(c *gin.Context, ruleEngine typex.RuleX) { } c.JSON(common.HTTP_OK, common.Ok()) +} +func RestartOutEnd(c *gin.Context, ruleEngine typex.RuleX) { + uuid, _ := c.GetQuery("uuid") + err := ruleEngine.RestartOutEnd(uuid) + if err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + c.JSON(common.HTTP_OK, common.Ok()) + } // 更新 diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 4e9797c7b..8ff9ae34d 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -269,13 +269,13 @@ func (hs *ApiServerPlugin) LoadRoute() { server.DefaultApiServer.Route().GET(server.ContextUrl("info"), server.AddRoute(apis.Info)) // InEndApi := server.RouteGroup(server.ContextUrl("/inends")) - { InEndApi.GET(("/detail"), server.AddRoute(apis.InEndDetail)) InEndApi.GET(("/list"), server.AddRoute(apis.InEnds)) InEndApi.POST(("/create"), server.AddRoute(apis.CreateInend)) InEndApi.DELETE(("/del"), server.AddRoute(apis.DeleteInEnd)) InEndApi.PUT(("/update"), server.AddRoute(apis.UpdateInend)) + InEndApi.PUT("/restart", server.AddRoute(apis.RestartInEnd)) } rulesApi := server.RouteGroup(server.ContextUrl("/rules")) @@ -299,6 +299,7 @@ func (hs *ApiServerPlugin) LoadRoute() { OutEndApi.POST(("/create"), server.AddRoute(apis.CreateOutEnd)) OutEndApi.DELETE(("/del"), server.AddRoute(apis.DeleteOutEnd)) OutEndApi.PUT(("/update"), server.AddRoute(apis.UpdateOutEnd)) + OutEndApi.PUT("/restart", server.AddRoute(apis.RestartOutEnd)) } // @@ -313,10 +314,9 @@ func (hs *ApiServerPlugin) LoadRoute() { { osApi.GET(("/netInterfaces"), server.AddRoute(apis.GetNetInterfaces)) osApi.GET(("/osRelease"), server.AddRoute(apis.CatOsRelease)) - osApi.GET(("/uarts"), server.AddRoute(apis.GetUartList)) + // osApi.GET(("/uarts"), server.AddRoute(apis.GetUartList)) osApi.GET(("/system"), server.AddRoute(apis.System)) osApi.GET(("/startedAt"), server.AddRoute(apis.StartedAt)) - } backupApi := server.RouteGroup(server.ContextUrl("/backup")) { @@ -334,7 +334,7 @@ func (hs *ApiServerPlugin) LoadRoute() { deviceApi.GET(("/detail"), server.AddRoute(apis.DeviceDetail)) deviceApi.GET("/group", server.AddRoute(apis.ListDeviceGroup)) deviceApi.GET("/listByGroup", server.AddRoute(apis.ListDeviceByGroup)) - + deviceApi.PUT("/restart", server.AddRoute(apis.RestartDevice)) } // Modbus 点位表 modbusApi := server.RouteGroup(server.ContextUrl("/modbus_data_sheet")) diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index 1389518f3..c362044fe 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -248,7 +248,7 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { if mdev.mainConfig.CommonConfig.Mode == "TCP" { n, err = mdev.RTURead(buffer) } - if mdev.mainConfig.CommonConfig.Mode == "RTU" { + if mdev.mainConfig.CommonConfig.Mode == "UART" { n, err = mdev.TCPRead(buffer) } if err != nil { @@ -284,7 +284,7 @@ func (mdev *generic_modbus_device) OnWrite(cmd []byte, data []byte) (int, error) if mdev.mainConfig.CommonConfig.Mode == "TCP" { mdev.tcpHandler.SlaveId = r.SlaverId } - if mdev.mainConfig.CommonConfig.Mode == "RTU" { + if mdev.mainConfig.CommonConfig.Mode == "UART" { mdev.rtuHandler.SlaveId = r.SlaverId } // 5 @@ -412,7 +412,7 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { if mdev.mainConfig.CommonConfig.Mode == "TCP" { mdev.tcpHandler.SlaveId = r.SlaverId } - if mdev.mainConfig.CommonConfig.Mode == "RTU" { + if mdev.mainConfig.CommonConfig.Mode == "UART" { mdev.rtuHandler.SlaveId = r.SlaverId } if r.Function == common.READ_COIL { diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index ad1bd3a3c..687d57bb5 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -90,6 +90,9 @@ func (s1200 *s1200plc) Init(devId string, configMap map[string]interface{}) erro return err } // 合并数据库里面的点位表 + // TODO 这里需要优化一下,而不是直接查表这种形式,应该从物模型组件来加载 + // DataSchema = schema.load(uuid) + // DataSchema.update(k, v) var list []SiemensDataPoint errDb := interdb.DB().Table("m_siemens_data_points"). Where("device_uuid=?", devId).Find(&list).Error diff --git a/engine/engine.go b/engine/engine.go index ddd2fd30c..1c321e5af 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -416,26 +416,39 @@ func (e *RuleEngine) SnapshotDump() string { // 重启源 func (e *RuleEngine) RestartInEnd(uuid string) error { - if _, ok := e.InEnds.Load(uuid); ok { + if Value, ok := e.InEnds.Load(uuid); ok { + InEnd := Value.(*typex.InEnd) + if InEnd.Source != nil { + InEnd.Source.Stop() // Down 以后会被自动拉起来 + } return nil } - return errors.New("InEnd:" + uuid + "not exists") + return fmt.Errorf("InendEnd not exists:%s", uuid) } // 重启目标 func (e *RuleEngine) RestartOutEnd(uuid string) error { - if _, ok := e.OutEnds.Load(uuid); ok { + if Value, ok := e.OutEnds.Load(uuid); ok { + OutEnd := Value.(*typex.OutEnd) + if OutEnd.Target != nil { + OutEnd.Target.Stop() // Down 以后会被自动拉起来 + } return nil } - return errors.New("OutEnd:" + uuid + "not exists") + return fmt.Errorf("OutEnd not exists:%s", uuid) + } // 重启设备 func (e *RuleEngine) RestartDevice(uuid string) error { - if _, ok := e.Devices.Load(uuid); ok { + if Value, ok := e.Devices.Load(uuid); ok { + Device := Value.(*typex.Device) + if Device.Device != nil { + Device.Device.Stop() // Down 以后会被自动拉起来 + } return nil } - return errors.New("Device:" + uuid + "not exists") + return fmt.Errorf("Device not exists:%s", uuid) } /* diff --git a/test/data/test-modbus-sheet.xlsx b/test/data/test-modbus-sheet.xlsx index 0f6bcf0808eefcd55f199d981a171193381c57c4..e3c298aa30a06a24036b7305b927f7752c891f9f 100644 GIT binary patch delta 3546 zcmai%c{o&k8^=v$Dj7*+DWoT59s5|aON)J{43Z^V_Atb$gtDYMG9i1`YHZm@qsG41 z5RV~dWY3yO2=5G~-uHRm>pg#*>pC;{@4kQc=li{X*Ex|^cdZIR2)$fW{~c5CDTD`T z*Qyg|4O_l5XHe`xNL6d-@>6v%W7=oN>d#k65JWg%$Vf)*V!xw3boS<7!7zefc1PL) zbmjQxR(bUElG5Co(_Psv_Td@F&+=UOIIk7YStU5O!HQ}yYIYvH(9{KGOdM@IFKB#M zh704HsY+ys9>4H`Ia~5|vDu+$nC0y>;FKrRWSv7Med%nj_Dg}FH2z^ZM*TuMZTV7G ze^r~9v#&M15hr>wF+p_KI9!;Izj|xPOyVt|7i~*r4|M1h6sk7F5D>G23?I~ z8p^JRA|~xBejIvZiL_oeUDxufzItmhPU@Ys0dWGGRqUpQae6|o@hX3p$W`r0G_^LX z?L@5fPPdK|zmBh+j|8Ha{+8vas8vGWXN38+T=xz!Y%}DE@FJft;?;|qk2`yqC4701 zxOcfa8n5bh_(v#5y(TNz99P%OX)zzGvMt66mC^|eLY(yA{h(<9%!d$8R(X^JxABV{mL zib?@oY&>wSZ_roqWy|z*Qjb@)is%{xZ-`(sW2(mzB0IXAaYRHR&6wE7L z{N+pVjb7=-AwQyq1$+H<3;D@qTw_j1KsA?nOHTHRQv8~0#e#xfy71w>pJw~ld;32| zT=6%xaNC^8W(i>=SY)B*Q=RoNmX^2__E-wxTWfl0J4t1&@!LuWs`|O>rjzxi(VU7( zxvgYRk7K3No7WNRK;A~y#%11ju;tbyxh{IBnHwTmO(cEFaeMOmZ4`S`k^K+}ja=T7?+BKe2 z_|fMD9(&Oh)*V@B6lYfVqL^*&!;Do)+jIQmzYr|UD&DUu!V#MyCi0jOu7UAN#A~bJ zhG6B8#fAJjAXqFy24vD^f}vgQkQgSyZ2v$Fn%s8P)WX#or#~F7lt0|?f@S%L=V|Wv zV_fjwh6-fZ4N?X4)qK?{PrRk-+Zc0xcZhJKj-|*Y=_{C++m(@L5?s3&J4@3!cgbPt z*@gqyZrRQ}b&leXg0_`Ph?|q@KUYB8=aH>+5ha=c?rm%LJVJMety5%SZ^O`hlE_|)~W%s#__#PjH0KZy=F z{mZ|$0_bzpGIDQeUrKqPXA)i(z&F-pXJptUSSw<*OZ19b!qt9i68@ZBoZfu+BGOq0 zMa>!mp9zUlfeBVe4uzM3#yUZ6i@6gf$3x+tZ8z3~kS6dn3F}<^E3&C|-JZ-e<3ihs z!dxAHVJu@UHIpWgqb50_9-diuzolNaSEk{>4QBqpHc18r&1aCBIw!N=>Fni9p5-D{ z?Xa|ZJ=A)B910>rf7G*=L;emJq6P$UtQw@py4JsLJQW+MM^CFWQh&dNUYc6vX$5j# zVp3oNV7>K^G&aw2qsKAqE=)>}JoL#K%o-7z4w25Wx;$*j4E9}NjN?&yvj8!RPTH8Shq@w1`48n0vUpU(HjhrFp z(UGh~wb(}&QB!fxp-T(|?=LZXiR3@y=C zzyc_G;5dZz`wo!4cxFf<8njK%7c5ElTE*`*4|8^>wHXet^GZDIy?;Ck6q0VxmI=k= zR7T!85;RpvY-8NQ2z{Sgg=OzxKW*X`jdp=r>HDz#1A#CV!AnLeCGJn1C)!N|6Q|+$ zJ5(hc184?Q!~lW^Qd)b&H*Jx=CjDX>}g6{#mD4@dn(Sir^9|ZF=+ zy`4Q5jwGyQw0o87$df-vZG~}e$wnommUFVc%hoW#h30ons^5L#BP(Qk2d8M7FV3B! zPX->dYVZmz0kY=0zbxM|%0TT&82@%UOhE?;|NdLHylf=|%EVXbAyqSaDwike)S-}H z`ac1jOQk7eRjrGjmiP=wDMbWI+L!OaL0LZ9R`US$tx*U}v^4Izs!z4XuU=M-*_X*H zl^?Cn-LcWkv7_!LMTJL}*U z%|7M%A^=}Nq3Ro6vtv;d()gRgZgj6Fs14&Xm%cET=YxXLrlRO)R}B%wL@J($LC0;i zq%S~|TLZS8NF9q`d?Ofw6D{?B)7#k=(_wTFI0)ka{!F?(0)9!C{@V)2E?JsGT4jGg z2?I2f!L06$$YLM%(op>(MKqw1@=N-kq%>%x+@)x!w@3jUqp*KNmHrP@j{lCzgEk8P zi3%BV1Ce)ANNMYF9U+bv{++p1Nfz3|17xL^J&UOG0r8ulr zZVH3^(*ii0l$W5jpmjb-GdBMnXRBB>& zmd!i%sG#;6>?7=ngx)dUje`c-yZ2CEDCy`P?Pn|beDEvF{!`B^Q_n%@=n}!<6WlGCu1R#o!8D>`J8I;VfeuFGB!!# z^%tL+3vkt^S;UF9NVPDH(rcROm}nRC4?gz1Sb5Uw1N=U^TX>3%5*esjlVNSBRgi1G z^_&=}Ta#^VT#(n>?K&kxp*^O5GVsWi?LImMql5=)Y(3_ccUw-0QsM)(YqCBWdE}LE zE;(#i5^ZRd!D>;i61$Vq&|RGZ;DP`fh!GNk$bx?hNkJ?@m@xSB3o1+41hOAo6;_4V zgJ(pMs6kjkQBeg*9q1&A zfJ}p_qN)%Ta9C6k5(aX^`Ht;;L8#EtanP1hukF=Ed%(6mT%a$U8G22K_Vd308e!s@ delta 3631 zcma)nIuIIYX`#gWwJ;xpG5a&<~LRm+oeRYuFL#PPw z$+%XYKW2)x4>w$8`jxX&uj^)GA$+$j_mtjjk@TA@MmarMZ`o^1`c8#C{w0_@VXOJ$ zUDNXDaFe>uZEE_db)VTy`XwZ0IBq6`WJj{@{l8idM z$x+Aqjya)=$`?|48ZJiz@w}ZXG~yw6`fWM~XQM-~Z>pTdfy6@rzuz8hzu%14!9{Dm zLW}mGmFQ7^kNS1qpC8+${IK<^>R}OxQOeR!rz3q9CM-L_7HPo}ah8YBJwPu_xqmMN z0)QWOiUB=-T_5(xOj#!fU7QIwfF5#fI(o(Pa)px7=VPyvNi8a-y1br7dSa-i^t={W zwn%{J5B}-8ws-38{hrO)*h*>-w(o9i9c3}BQ!Q`F)ixOuIZ15He*8&_J96!#}Uub>{K9@|PsQqW?8gPNmb0TAu?4FfHFJE*iS@L^k?(H;e zFZ#xtu-Y`YGNSjnO8aBMLU3;tn{AoswRq9%M?Xtu}jX}vyMP9=4mzPpfMD+$zAPZN3FQq^LAwWM+lN@s6MrG&?qWy#!ItV<#rUHb2 z^3nNiD>~+2r-OO@(tf$<%H8UTH?hTXab3lJZ7l%S{P*-V<-+^srgPV27ARK-11n+* z&s0obqfAzJyg9M6T(Z`A2^}PzyL@rc?)=m1Aq1gt^M#SJ`T6mXnR7bc)$j{l@Rbt4 z>(Nw7sfh+1OPxo|ugv)i`QXdG%J2cC6ne4F=W4Rkxc>2h@Q{P4K_oFG$EpK-!51OJ z*Dz5!IrqBg=SqQu55{TgLA(Q{qm-Q&ZLrwRVjL9u^GSR4cv0{2z#Iv<9_WBc|NT*= z13enuQtBU99M!2EzRIgVGs#;ko*90_rm6_z)K|Gk>iRYSnsN2q$m^XgKm$Gt5<^m9 z1WmP~_+owi6a=E{=ZeIM3U+oEKCTsR?6nKQmr}0&7_Xi08S@NYDOZaX(A@j2*yXgO zuxP_wV~ubT&5pK#`nz`me!dtwrf!R4&*$--!P@P|HriI0 z$U|wRK8lel8Yi%gh7@vm^AP|PPMR=-j}Ac~JdX)KfD6h|>IwG3KINVzLxRs#T3!!m z-4vqZBZaWW-F9y?1J3!m6YPbC{CGNIhQ3CSU%wkqd&_}_vZ{$B6Ih?YmAqeE`V>J_ zWur<>UMkd8(xPD8cK1*7A|r+@A(+=Lxv~#r1m!99Z|!6Fz#&29TEJhH1@0EV1CHG> zeKmZwD(%g=m+o)vg;@LpgInmD4?SC93=NpNgLjRBm&5O#hVt8DQ#WgPjzuw>Fnb)h z&+H-pOk|scX0`?ucg*MoHo|TJTd_$_7R6_xO0_QF=_ua8hZjD`|CO;1z==EFQlI9x zs`o7Cznrq8<6i2(i+>(Rwj1Q&BTUYlofenUx2xFaKdg{1G0c6DSMnxrarPO72}Vtl z^-UNt5#@ESQTk{m|ugZT;Uatc!3{QSic_BFS;DcGF3n%T}!ZRU&C#~ zMtRK)Bu>E*uO6V?oXq{?i*;;|n_IBgES?sy|95`8zi-uX9B(T>fFQ#|6V42=I$0$- z(~7&AVQbFGCFzd(?U`c;{lbs<%zd-YvoPVFk#63Rx>m+AlgKaJ{fq>1+6@$G_HwbO zDS7Ia0zyMi({w5A_C`i=OtDH@sv*dLvcK6fn~pZ~iA%Y-R3MdT3W}2EnMvdbM^sw; zDjK>19Ktd*OKI?Y$o3~jGdJaxkmA9nZFr0|Gl^TDA-ZuhOJc$wK`@5oy&6X)F`VV3 z`|baK1N(PjzB!7j^(HD&B7cFAW=3(KI{Q8Vb&bIgLw>>Iv!Q9@oJ}=0sI+t@hB$WL z3~Ds}!L}ItH_t=~T zxw8yNxA$QJgg>LgoK5B|Y!l+vN?9{@;LV0ocbXoYOHGW~0f__FF(o~hbbpb@8Q<8v zF_Mece4~S5zIt_QTbWlb&0WWjN%@AgDjQ^3_|rnu?5x)mY(sc9l(2e&v<5MG06Bwk zV)&{FyS^FU93l66pd3(ys#*geCQYBx-kp|2o+hh3r2cWV*?M$VkQ#q5`2|xa)Ad?! zQzqj+O4}G`c#2Qh@^sD86Qt*P+RQ1CO4QxfqxMcyP&w$Qge-!U2)QoYkc+N8i(RMF=4 zMJV?xKaOy0Pom2rNib`XBbWFmsyXuiT4!sD7|Yae%FqT3b7$=PEH*qOZJy9_=!+Xc zX>=31#~Eh{ZGAf>satRhF@^+L|1bK#c)KZWQK`0ewlbs2j-BfEpfN42u2EKF{xRwE z4gTanI1V#+W8;2i+17s*>o6F&zjD>qcl9+nWny#@-8DD*``gRoWb*;1RVSyqqE}f< zQ(Ox=uSh18cym*sDx03)boH>3N=_$-%Da7taF4VH;k%t=CRHfHFrC7-v!f+7T-*ou zRJ&nz8bcwFM_}(^VZhvkaZiYtDen)GAbO?){>EKmk^K%jC*4b)x8~Y`aZ7Z=YxlGp zv~W{PO;6`1FAK(_tKXwI?<8WACBkUb@ZGV7VK=IDybSh(?3F^J{X)JomfycFm21=^ zhtc|8?-ic5o1Cwoq>1y1j)Gjj+;kA2$u9!DG5A8o_|T^%K>5zof&x=@qS&pRbV}l^ zqpQIS%s|Crsb{CxDZ2*TbL;eOoSd~?3ee!`H`G7q-Ccw;`6WP$Z}Ha;B39md+=N)A zeFE*;Jo^wQoc{?Sl^--z57B%t$$iJ!LZ*>zWRGk7Y{FsbV+BV$lYEQ_PwbQAuB5y- z8RMCc3pJ?B`Plusdhj;YM2g)$y{Ezo#1vd|dEJSJ4X632Wj zCEJb3&OZn>seIaNh0ZS}cL9rvs~1bOk09BgpTQ)llTdB2T}lax0(VJ+8#l5?(n#oT z@Q3utT`oHzkYFza_+1tbo|WN*-Ui)dRH4OSri`r6W-_c02sdQ?1BD!7eEA0)kjf$;z9?c$vvX{R9QBe##uTZ;M1 Fe*wpo4!HmT diff --git a/typex/version.go b/typex/version.go index 1d9ed48c1..ca8aaf5e6 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-11 21:42:05", + ReleaseTime: "2023-12-12 22:03:44", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-14fd2373f0a90fc +** Version: v0.6.4-19b0e24ce3a0e75 ** Document: https://hootrhino.github.io ` From af5877c5c1fc2e51b84a034837c72189d6fbc19e Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 13 Dec 2023 16:09:58 +0800 Subject: [PATCH 113/138] fix: fix some warning --- component/rulex_api_server/model/model.go | 2 +- device/decoder/h264decoder.go | 276 ++++++++++---------- device/s1200plc_device.go | 17 +- test/device_generic_ais_rxtx_device_test.go | 4 +- test/device_modbus_wite_with_app_test.go | 6 +- test/device_s1200plc_test.go | 28 +- 6 files changed, 155 insertions(+), 178 deletions(-) diff --git a/component/rulex_api_server/model/model.go b/component/rulex_api_server/model/model.go index 4d224fa13..f1d991bc1 100644 --- a/component/rulex_api_server/model/model.go +++ b/component/rulex_api_server/model/model.go @@ -8,7 +8,7 @@ import ( ) type RulexModel struct { - ID uint `gorm:"primarykey" json:"id"` + ID uint `gorm:"primaryKey" json:"id"` CreatedAt time.Time `json:"created_at"` } type StringList []string diff --git a/device/decoder/h264decoder.go b/device/decoder/h264decoder.go index 22dfa6374..35b6b6eba 100644 --- a/device/decoder/h264decoder.go +++ b/device/decoder/h264decoder.go @@ -1,140 +1,140 @@ package decoder -import ( - "fmt" - "image" - "unsafe" -) - -// #cgo pkg-config: libavcodec libavutil libswscale -// #include -// #include -// #include -import "C" - -func FrameData(frame *C.AVFrame) **C.uint8_t { - return (**C.uint8_t)(unsafe.Pointer(&frame.data[0])) -} - -func FrameLineSize(frame *C.AVFrame) *C.int { - return (*C.int)(unsafe.Pointer(&frame.linesize[0])) -} - -// h264Decoder is a wrapper around ffmpeg's H264 decoder. -type h264Decoder struct { - codecCtx *C.AVCodecContext - srcFrame *C.AVFrame - swsCtx *C.struct_SwsContext - dstFrame *C.AVFrame - dstFramePtr []uint8 -} - -// newH264Decoder allocates a new h264Decoder. -func NewH264Decoder() (*h264Decoder, error) { - codec := C.avcodec_find_decoder(C.AV_CODEC_ID_H264) - if codec == nil { - return nil, fmt.Errorf("avcodec_find_decoder() failed") - } - - codecCtx := C.avcodec_alloc_context3(codec) - if codecCtx == nil { - return nil, fmt.Errorf("avcodec_alloc_context3() failed") - } - - res := C.avcodec_open2(codecCtx, codec, nil) - if res < 0 { - C.avcodec_close(codecCtx) - return nil, fmt.Errorf("avcodec_open2() failed") - } - - srcFrame := C.av_frame_alloc() - if srcFrame == nil { - C.avcodec_close(codecCtx) - return nil, fmt.Errorf("av_frame_alloc() failed") - } - - return &h264Decoder{ - codecCtx: codecCtx, - srcFrame: srcFrame, - }, nil -} - -// close closes the decoder. -func (d *h264Decoder) Close() { - if d.dstFrame != nil { - C.av_frame_free(&d.dstFrame) - } - - if d.swsCtx != nil { - C.sws_freeContext(d.swsCtx) - } - - C.av_frame_free(&d.srcFrame) - C.avcodec_close(d.codecCtx) -} - -func (d *h264Decoder) Decode(nalu []byte) (image.Image, error) { - nalu = append([]uint8{0x00, 0x00, 0x00, 0x01}, []uint8(nalu)...) - - // send frame to decoder - var avPacket C.AVPacket - avPacket.data = (*C.uint8_t)(C.CBytes(nalu)) - defer C.free(unsafe.Pointer(avPacket.data)) - avPacket.size = C.int(len(nalu)) - res := C.avcodec_send_packet(d.codecCtx, &avPacket) - if res < 0 { - return nil, nil - } - - // receive frame if available - res = C.avcodec_receive_frame(d.codecCtx, d.srcFrame) - if res < 0 { - return nil, nil - } - - // if frame size has changed, allocate needed objects - if d.dstFrame == nil || d.dstFrame.width != d.srcFrame.width || d.dstFrame.height != d.srcFrame.height { - if d.dstFrame != nil { - C.av_frame_free(&d.dstFrame) - } - - if d.swsCtx != nil { - C.sws_freeContext(d.swsCtx) - } - - d.dstFrame = C.av_frame_alloc() - d.dstFrame.format = C.AV_PIX_FMT_RGBA - d.dstFrame.width = d.srcFrame.width - d.dstFrame.height = d.srcFrame.height - d.dstFrame.color_range = C.AVCOL_RANGE_JPEG - res = C.av_frame_get_buffer(d.dstFrame, 1) - if res < 0 { - return nil, fmt.Errorf("av_frame_get_buffer() err") - } - - d.swsCtx = C.sws_getContext(d.srcFrame.width, d.srcFrame.height, C.AV_PIX_FMT_YUV420P, - d.dstFrame.width, d.dstFrame.height, (int32)(d.dstFrame.format), C.SWS_BILINEAR, nil, nil, nil) - if d.swsCtx == nil { - return nil, fmt.Errorf("sws_getContext() err") - } - - dstFrameSize := C.av_image_get_buffer_size((int32)(d.dstFrame.format), d.dstFrame.width, d.dstFrame.height, 1) - d.dstFramePtr = (*[1 << 30]uint8)(unsafe.Pointer(d.dstFrame.data[0]))[:dstFrameSize:dstFrameSize] - } - - // convert frame from YUV420 to RGB - res = C.sws_scale(d.swsCtx, frameData(d.srcFrame), frameLineSize(d.srcFrame), - 0, d.srcFrame.height, frameData(d.dstFrame), frameLineSize(d.dstFrame)) - if res < 0 { - return nil, fmt.Errorf("sws_scale() err") - } - - // embed frame into an image.Image - return &image.RGBA{ - Pix: d.dstFramePtr, - Stride: 4 * (int)(d.dstFrame.width), - Rect: image.Rectangle{ - Max: image.Point{(int)(d.dstFrame.width), (int)(d.dstFrame.height)}, - }, - }, nil -} +// import ( +// "fmt" +// "image" +// "unsafe" +// ) + +// // #cgo pkg-config: libavcodec libavutil libswscale +// // #include +// // #include +// // #include +// import "C" + +// func FrameData(frame *C.AVFrame) **C.uint8_t { +// return (**C.uint8_t)(unsafe.Pointer(&frame.data[0])) +// } + +// func FrameLineSize(frame *C.AVFrame) *C.int { +// return (*C.int)(unsafe.Pointer(&frame.linesize[0])) +// } + +// // h264Decoder is a wrapper around ffmpeg's H264 decoder. +// type h264Decoder struct { +// codecCtx *C.AVCodecContext +// srcFrame *C.AVFrame +// swsCtx *C.struct_SwsContext +// dstFrame *C.AVFrame +// dstFramePtr []uint8 +// } + +// // newH264Decoder allocates a new h264Decoder. +// func NewH264Decoder() (*h264Decoder, error) { +// codec := C.avcodec_find_decoder(C.AV_CODEC_ID_H264) +// if codec == nil { +// return nil, fmt.Errorf("avcodec_find_decoder() failed") +// } + +// codecCtx := C.avcodec_alloc_context3(codec) +// if codecCtx == nil { +// return nil, fmt.Errorf("avcodec_alloc_context3() failed") +// } + +// res := C.avcodec_open2(codecCtx, codec, nil) +// if res < 0 { +// C.avcodec_close(codecCtx) +// return nil, fmt.Errorf("avcodec_open2() failed") +// } + +// srcFrame := C.av_frame_alloc() +// if srcFrame == nil { +// C.avcodec_close(codecCtx) +// return nil, fmt.Errorf("av_frame_alloc() failed") +// } + +// return &h264Decoder{ +// codecCtx: codecCtx, +// srcFrame: srcFrame, +// }, nil +// } + +// // close closes the decoder. +// func (d *h264Decoder) Close() { +// if d.dstFrame != nil { +// C.av_frame_free(&d.dstFrame) +// } + +// if d.swsCtx != nil { +// C.sws_freeContext(d.swsCtx) +// } + +// C.av_frame_free(&d.srcFrame) +// C.avcodec_close(d.codecCtx) +// } + +// func (d *h264Decoder) Decode(nalu []byte) (image.Image, error) { +// nalu = append([]uint8{0x00, 0x00, 0x00, 0x01}, []uint8(nalu)...) + +// // send frame to decoder +// var avPacket C.AVPacket +// avPacket.data = (*C.uint8_t)(C.CBytes(nalu)) +// defer C.free(unsafe.Pointer(avPacket.data)) +// avPacket.size = C.int(len(nalu)) +// res := C.avcodec_send_packet(d.codecCtx, &avPacket) +// if res < 0 { +// return nil, nil +// } + +// // receive frame if available +// res = C.avcodec_receive_frame(d.codecCtx, d.srcFrame) +// if res < 0 { +// return nil, nil +// } + +// // if frame size has changed, allocate needed objects +// if d.dstFrame == nil || d.dstFrame.width != d.srcFrame.width || d.dstFrame.height != d.srcFrame.height { +// if d.dstFrame != nil { +// C.av_frame_free(&d.dstFrame) +// } + +// if d.swsCtx != nil { +// C.sws_freeContext(d.swsCtx) +// } + +// d.dstFrame = C.av_frame_alloc() +// d.dstFrame.format = C.AV_PIX_FMT_RGBA +// d.dstFrame.width = d.srcFrame.width +// d.dstFrame.height = d.srcFrame.height +// d.dstFrame.color_range = C.AVCOL_RANGE_JPEG +// res = C.av_frame_get_buffer(d.dstFrame, 1) +// if res < 0 { +// return nil, fmt.Errorf("av_frame_get_buffer() err") +// } + +// d.swsCtx = C.sws_getContext(d.srcFrame.width, d.srcFrame.height, C.AV_PIX_FMT_YUV420P, +// d.dstFrame.width, d.dstFrame.height, (int32)(d.dstFrame.format), C.SWS_BILINEAR, nil, nil, nil) +// if d.swsCtx == nil { +// return nil, fmt.Errorf("sws_getContext() err") +// } + +// dstFrameSize := C.av_image_get_buffer_size((int32)(d.dstFrame.format), d.dstFrame.width, d.dstFrame.height, 1) +// d.dstFramePtr = (*[1 << 30]uint8)(unsafe.Pointer(d.dstFrame.data[0]))[:dstFrameSize:dstFrameSize] +// } + +// // convert frame from YUV420 to RGB +// res = C.sws_scale(d.swsCtx, frameData(d.srcFrame), frameLineSize(d.srcFrame), +// 0, d.srcFrame.height, frameData(d.dstFrame), frameLineSize(d.dstFrame)) +// if res < 0 { +// return nil, fmt.Errorf("sws_scale() err") +// } + +// // embed frame into an image.Image +// return &image.RGBA{ +// Pix: d.dstFramePtr, +// Stride: 4 * (int)(d.dstFrame.width), +// Rect: image.Rectangle{ +// Max: image.Point{(int)(d.dstFrame.width), (int)(d.dstFrame.height)}, +// }, +// }, nil +// } diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index 687d57bb5..f36dd4efe 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -32,13 +32,14 @@ type SiemensDataPoint struct { } type S1200CommonConfig struct { - Host string `json:"host" validate:"required"` // 127.0.0.1:502 - Model string `json:"model" validate:"required"` // s7-200 s7-1500 - Rack *int `json:"rack" validate:"required"` // 0 - Slot *int `json:"slot" validate:"required"` // 1 - Timeout *int `json:"timeout" validate:"required"` // 5s - IdleTimeout *int `json:"idleTimeout" validate:"required"` // 5s - AutoRequest *bool `json:"autoRequest" validate:"required"` // false + Host string `json:"host" validate:"required"` // 127.0.0.1:502 + Model string `json:"model" validate:"required"` // s7-200 s7-1500 + // https://cloudvpn.beijerelectronics.com/hc/en-us/articles/4406049761169-Siemens-S7 + Rack *int `json:"rack" validate:"required"` // 0 + Slot *int `json:"slot" validate:"required"` // 1 + Timeout *int `json:"timeout" validate:"required"` // 5s + IdleTimeout *int `json:"idleTimeout" validate:"required"` // 5s + AutoRequest *bool `json:"autoRequest" validate:"required"` // false } type S1200Config struct { CommonConfig S1200CommonConfig `json:"commonConfig" validate:"required"` // 通用配置 @@ -245,6 +246,7 @@ func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 if err := s1200.client.AGReadDB(*db.Address, *db.Start, *db.Size, rData[:]); err != nil { s1200.SiemensDataPoints[uuid].Status = 0 + glogger.GLogger.Error(err) return 0, err } count := db.Size @@ -269,6 +271,7 @@ func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { if db.Type == "MB" { // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 if err := s1200.client.AGReadMB(*db.Start, *db.Size, rData[:]); err != nil { + glogger.GLogger.Error(err) return 0, err } count := db.Size diff --git a/test/device_generic_ais_rxtx_device_test.go b/test/device_generic_ais_rxtx_device_test.go index beaf44172..44aaf2652 100644 --- a/test/device_generic_ais_rxtx_device_test.go +++ b/test/device_generic_ais_rxtx_device_test.go @@ -35,7 +35,7 @@ func Test_AIS_SEND_PACKET(t *testing.T) { * AIS 数据发送模拟器 * */ -func ais_sender_emulator_udp() { +func Ais_sender_emulator_udp() { // Server address serverAddr := "localhost:6005" @@ -74,7 +74,7 @@ func ais_sender_emulator_udp() { fmt.Println("Response from server:", response) } -func ais_sender_emulator_tcp() { +func Ais_sender_emulator_tcp() { // Connect to the server s1 := `!ABVDM,1,1,5,B,H69EvShlTpID@TpMUG3COOL0000,2*14` conn, err := net.Dial("tcp", "localhost:6005") diff --git a/test/device_modbus_wite_with_app_test.go b/test/device_modbus_wite_with_app_test.go index 5d3e75fdc..77525148f 100644 --- a/test/device_modbus_wite_with_app_test.go +++ b/test/device_modbus_wite_with_app_test.go @@ -13,12 +13,12 @@ import ( ) // 读出来的字节缓冲默认大小 -const __DEFAULT_BUFFER_SIZE = 100 +// const __DEFAULT_BUFFER_SIZE = 100 // 传输形式: // `rawtcp`, `rawudp`, `rawserial` -const rawtcp string = "TCP" -const rawudp string = "rawudp" +// const rawtcp string = "TCP" +// const rawudp string = "rawudp" const rawserial string = "UART" type _CPDCommonConfig struct { diff --git a/test/device_s1200plc_test.go b/test/device_s1200plc_test.go index 69d0d0d1f..cff18dd85 100644 --- a/test/device_s1200plc_test.go +++ b/test/device_s1200plc_test.go @@ -31,32 +31,6 @@ import ( // ] // } func Test_gen_config(t *testing.T) { - port := 1800 - Rack := 0 - Slot := 1 - Timeout := 5 - IdleTimeout := 5 - ReadFrequency := 5 - c := common.S1200Config{ - Host: "127.0.0.1", - Port: &port, - Rack: &Rack, - Slot: &Slot, - Model: "S1200", - Timeout: &Timeout, - IdleTimeout: &IdleTimeout, - Frequency: int64(ReadFrequency), - Blocks: []common.S1200Block{ - { - Tag: "V1", - Address: 1, - Start: 1, - Size: 10, - }, - }, - } - b, _ := json.MarshalIndent(c, "", " ") - t.Log(string(b)) } func Test_parse_config(t *testing.T) { @@ -136,7 +110,7 @@ func Test_RULEX_WITH_S1200PLC(t *testing.T) { EMQX_BROKER := typex.NewOutEnd(typex.MQTT_TARGET, "内网MQTT桥接", "内网MQTT桥接", map[string]interface{}{ - "Host": "emqx.dev.inrobot.cloud", + "Host": "emqx.dev.com", "Port": 1883, "DataTopic": "iothub/upstream/YK0801", "ClientId": "YK0801", From 1eadfee0a322c9208c7179afe54259f91dbf2a53 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 14 Dec 2023 21:05:07 +0800 Subject: [PATCH 114/138] dev: support data sheet status --- common/modbus_config.go | 18 +- component/intercache/intercache.go | 28 ++ component/intercache/modbus/modbus_cache.go | 110 ++++++ component/intercache/readme.md | 19 + component/intercache/siemens/siemens_cache.go | 108 ++++++ .../thingsschema/things_schema_cache.go | 19 + component/rulex_api_server/apis/device_api.go | 43 ++- .../apis/device_modbus_data_sheet_api.go | 25 +- .../apis/device_s1200_data_sheet_api.go | 2 +- component/rulex_api_server/apis/rule_api.go | 345 +++++++++--------- component/rulex_api_server/http_api_server.go | 14 +- component/rulex_api_server/model/model.go | 50 +-- device/generic_modbus_device.go | 73 ++-- device/s1200plc_device.go | 102 ++++-- device/s1200plc_device.md | 8 +- device/type_loader.go | 2 +- driver/modbus_rtu_driver.go | 6 +- engine/engine.go | 18 +- test/device_s1200plc_test.go | 12 +- typex/xdevice.go | 2 +- 20 files changed, 699 insertions(+), 305 deletions(-) create mode 100644 component/intercache/intercache.go create mode 100644 component/intercache/modbus/modbus_cache.go create mode 100644 component/intercache/readme.md create mode 100644 component/intercache/siemens/siemens_cache.go create mode 100644 component/intercache/thingsschema/things_schema_cache.go diff --git a/common/modbus_config.go b/common/modbus_config.go index 68b3a98af..e36e357ab 100644 --- a/common/modbus_config.go +++ b/common/modbus_config.go @@ -39,16 +39,14 @@ type Registers struct { * */ type RegisterRW struct { - Tag string `json:"tag" validate:"required" title:"数据Tag"` // 数据Tag - Alias string `json:"alias" validate:"required" title:"别名"` // 别名 - Function int `json:"function" validate:"required" title:"Modbus功能"` // Function - SlaverId byte `json:"slaverId" validate:"required" title:"从机ID"` // 从机ID - Address uint16 `json:"address" validate:"required" title:"地址"` // Address - Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` // 间隔 - Quantity uint16 `json:"quantity" validate:"required" title:"数量"` // Quantity - Status int `json:"status"` // 运行时数据 - LastFetchTime uint64 `json:"lastFetchTime"` // 运行时数据 - Value string `json:"value"` // 运行时数据 + Tag string `json:"tag" validate:"required" title:"数据Tag"` // 数据Tag + Alias string `json:"alias" validate:"required" title:"别名"` // 别名 + Function int `json:"function" validate:"required" title:"Modbus功能"` // Function + SlaverId byte `json:"slaverId" validate:"required" title:"从机ID"` // 从机ID + Address uint16 `json:"address" validate:"required" title:"地址"` // Address + Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` // 间隔 + Quantity uint16 `json:"quantity" validate:"required" title:"数量"` // Quantity + Value string `json:"value"` // 运行时数据 } /* diff --git a/component/intercache/intercache.go b/component/intercache/intercache.go new file mode 100644 index 000000000..98e1bded7 --- /dev/null +++ b/component/intercache/intercache.go @@ -0,0 +1,28 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package intercache + +/* +* +* 内部缓存器 +* + */ +type InterCache interface { + RegisterSlot(Slot string) // 存储槽位, 释放资源的时候调用 + UnRegisterSlot(Slot string) // 注销存储槽位, 释放资源的时候调用 + Size() uint64 // 存储器当前长度 + Flush() // 释放存储器空间 +} diff --git a/component/intercache/modbus/modbus_cache.go b/component/intercache/modbus/modbus_cache.go new file mode 100644 index 000000000..52881d03d --- /dev/null +++ b/component/intercache/modbus/modbus_cache.go @@ -0,0 +1,110 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) RegisterPoint later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT RegisterPoint WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +package modbus + +import ( + "github.com/hootrhino/rulex/component/intercache" + "github.com/hootrhino/rulex/typex" +) + +// 点位表 +type RegisterPoint struct { + UUID string + Status int + LastFetchTime uint64 + Value string +} + +var __DefaultModbusPointCache *ModbusPointCache + +func RegisterSlot(Slot string) { + __DefaultModbusPointCache.RegisterSlot(Slot) +} +func GetSlot(Slot string) map[string]RegisterPoint { + return __DefaultModbusPointCache.GetSlot(Slot) +} +func SetValue(Slot, K string, V RegisterPoint) { + __DefaultModbusPointCache.SetValue(Slot, K, V) +} +func GetValue(Slot, K string) RegisterPoint { + return __DefaultModbusPointCache.GetValue(Slot, K) +} +func DeleteValue(Slot, K string) { + __DefaultModbusPointCache.DeleteValue(Slot, K) +} +func UnRegisterSlot(Slot string) { + __DefaultModbusPointCache.UnRegisterSlot(Slot) +} +func Size() uint64 { + return __DefaultModbusPointCache.Size() +} +func Flush() { + __DefaultModbusPointCache.Flush() +} + +//Modbus 点位运行时存储器 + +type ModbusPointCache struct { + Slots map[string]map[string]RegisterPoint + ruleEngine typex.RuleX +} + +func InitModbusPointCache(ruleEngine typex.RuleX) intercache.InterCache { + __DefaultModbusPointCache = &ModbusPointCache{ + ruleEngine: ruleEngine, + Slots: map[string]map[string]RegisterPoint{}, + } + return __DefaultModbusPointCache +} +func (M ModbusPointCache) RegisterSlot(Slot string) { + M.Slots[Slot] = map[string]RegisterPoint{} +} +func (M ModbusPointCache) GetSlot(Slot string) map[string]RegisterPoint { + if S, ok := M.Slots[Slot]; ok { + return S + } + return nil +} +func (M ModbusPointCache) SetValue(Slot, K string, V RegisterPoint) { + if S, ok := M.Slots[Slot]; ok { + S[K] = V + M.Slots[Slot] = S + } +} +func (M ModbusPointCache) GetValue(Slot, K string) RegisterPoint { + if S, ok := M.Slots[Slot]; ok { + return S[K] + } + return RegisterPoint{} +} +func (M ModbusPointCache) DeleteValue(Slot, K string) { + if S, ok := M.Slots[Slot]; ok { + delete(S, Slot) + } +} +func (M ModbusPointCache) UnRegisterSlot(Slot string) { + delete(M.Slots, Slot) +} +func (M ModbusPointCache) Size() uint64 { + return uint64(len(M.Slots)) +} +func (M ModbusPointCache) Flush() { + for slotName, slot := range M.Slots { + for k, _ := range slot { + delete(slot, k) + } + delete(M.Slots, slotName) + } +} diff --git a/component/intercache/readme.md b/component/intercache/readme.md new file mode 100644 index 000000000..415804998 --- /dev/null +++ b/component/intercache/readme.md @@ -0,0 +1,19 @@ + + +# 内部缓存器 +主要用来做内存缓存加速使用,比如留给物模型来展示实时值等。是一个K-V存储器,其本质是Map。 \ No newline at end of file diff --git a/component/intercache/siemens/siemens_cache.go b/component/intercache/siemens/siemens_cache.go new file mode 100644 index 000000000..367773d4f --- /dev/null +++ b/component/intercache/siemens/siemens_cache.go @@ -0,0 +1,108 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) SiemensPoint later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT SiemensPoint WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +package siemens + +import ( + "github.com/hootrhino/rulex/component/intercache" + "github.com/hootrhino/rulex/typex" +) + +var __DefaultSiemensPointCache *SiemensPointCache + +// 点位表 +type SiemensPoint struct { + UUID string + Status int + LastFetchTime uint64 + Value string +} + +func RegisterSlot(Slot string) { + __DefaultSiemensPointCache.RegisterSlot(Slot) +} +func GetSlot(Slot string) map[string]SiemensPoint { + return __DefaultSiemensPointCache.GetSlot(Slot) +} +func SetValue(Slot, K string, V SiemensPoint) { + __DefaultSiemensPointCache.SetValue(Slot, K, V) +} +func GetValue(Slot, K string) SiemensPoint { + return __DefaultSiemensPointCache.GetValue(Slot, K) +} +func DeleteValue(Slot, K string) { + __DefaultSiemensPointCache.DeleteValue(Slot, K) +} +func UnRegisterSlot(Slot string) { + __DefaultSiemensPointCache.UnRegisterSlot(Slot) +} +func Size() uint64 { + return __DefaultSiemensPointCache.Size() +} +func Flush() { + __DefaultSiemensPointCache.Flush() +} + +type SiemensPointCache struct { + Slots map[string]map[string]SiemensPoint + ruleEngine typex.RuleX +} + +func InitSiemensPointCache(ruleEngine typex.RuleX) intercache.InterCache { + __DefaultSiemensPointCache = &SiemensPointCache{ + ruleEngine: ruleEngine, + Slots: map[string]map[string]SiemensPoint{}, + } + return __DefaultSiemensPointCache +} +func (M SiemensPointCache) RegisterSlot(Slot string) { + M.Slots[Slot] = map[string]SiemensPoint{} +} +func (M SiemensPointCache) GetSlot(Slot string) map[string]SiemensPoint { + if S, ok := M.Slots[Slot]; ok { + return S + } + return nil +} +func (M SiemensPointCache) SetValue(Slot, K string, V SiemensPoint) { + if S, ok := M.Slots[Slot]; ok { + S[K] = V + M.Slots[Slot] = S + } +} +func (M SiemensPointCache) GetValue(Slot, K string) SiemensPoint { + if S, ok := M.Slots[Slot]; ok { + return S[K] + } + return SiemensPoint{} +} +func (M SiemensPointCache) DeleteValue(Slot, K string) { + if S, ok := M.Slots[Slot]; ok { + delete(S, Slot) + } +} +func (M SiemensPointCache) UnRegisterSlot(Slot string) { + delete(M.Slots, Slot) +} +func (M SiemensPointCache) Size() uint64 { + return uint64(len(M.Slots)) +} +func (M SiemensPointCache) Flush() { + for slotName, slot := range M.Slots { + for k, _ := range slot { + delete(slot, k) + } + delete(M.Slots, slotName) + } +} diff --git a/component/intercache/thingsschema/things_schema_cache.go b/component/intercache/thingsschema/things_schema_cache.go new file mode 100644 index 000000000..d14efc00c --- /dev/null +++ b/component/intercache/thingsschema/things_schema_cache.go @@ -0,0 +1,19 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package intercache + +type ThingsSchemaCache struct { +} diff --git a/component/rulex_api_server/apis/device_api.go b/component/rulex_api_server/apis/device_api.go index 023da91ca..3cc1ee617 100644 --- a/component/rulex_api_server/apis/device_api.go +++ b/component/rulex_api_server/apis/device_api.go @@ -3,10 +3,12 @@ package apis import ( "fmt" + "github.com/hootrhino/rulex/component/interdb" common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/component/rulex_api_server/server" "github.com/hootrhino/rulex/component/rulex_api_server/service" + "gorm.io/gorm" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" @@ -130,7 +132,7 @@ func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { } } // 西门子的 - if Mdev.Type == "S1200PLC" { + if Mdev.Type == "SIEMENS_PLC" { if err := service.DeleteAllSiemensPointByDevice(uuid); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return @@ -241,16 +243,37 @@ func UpdateDevice(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } - // 取消绑定分组,删除原来旧的分组 + + // 只有检查到分组变了才更改 Group := service.GetVisualGroup(Device.UUID) - if err := service.UnBindResource(Group.UUID, Device.UUID); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // 重新绑定分组 - if err := service.BindResource(form.Gid, Device.UUID); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return + if Group.UUID != form.Gid { + // 取消绑定分组,删除原来旧的分组 + txErr := interdb.DB().Transaction(func(tx *gorm.DB) error { + err1 := tx.Where("gid=? and rid =?", Group.UUID, Device.UUID). + Delete(&model.MGenericGroupRelation{}).Error + if err1 != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return err1 + } + // 重新绑定分组,首先确定分组是否存在 + MGroup := model.MGenericGroup{} + if err2 := interdb.DB().Where("uuid=?", Group.UUID).First(&MGroup).Error; err2 != nil { + return err2 + } + Relation := model.MGenericGroupRelation{ + Gid: MGroup.UUID, + Rid: Device.UUID, + } + err3 := tx.Save(&Relation).Error + if err3 != nil { + return err3 + } + return nil + }) + if txErr != nil { + c.JSON(common.HTTP_OK, common.Error400(txErr)) + return + } } if err := server.LoadNewestDevice(form.UUID, ruleEngine); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) diff --git a/component/rulex_api_server/apis/device_modbus_data_sheet_api.go b/component/rulex_api_server/apis/device_modbus_data_sheet_api.go index 1816432c5..904b76fd5 100644 --- a/component/rulex_api_server/apis/device_modbus_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_modbus_data_sheet_api.go @@ -24,6 +24,7 @@ import ( "time" "github.com/gin-gonic/gin" + modbuscache "github.com/hootrhino/rulex/component/intercache/modbus" "github.com/hootrhino/rulex/component/interdb" common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/component/rulex_api_server/model" @@ -99,7 +100,9 @@ func ModbusSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { recordsVo := []ModbusPointVo{} for _, record := range records { - recordsVo = append(recordsVo, ModbusPointVo{ + Slot := modbuscache.GetSlot(deviceUuid) + Value, ok := Slot[record.UUID] + Vo := ModbusPointVo{ UUID: record.UUID, DeviceUUID: record.DeviceUuid, Tag: record.Tag, @@ -109,10 +112,22 @@ func ModbusSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { Address: record.Address, Frequency: record.Frequency, Quantity: record.Quantity, - Status: 1, // 运行时 - LastFetchTime: uint64(time.Now().UnixMilli()), // 运行时 - Value: "00000000", // 运行时 - }) + LastFetchTime: Value.LastFetchTime, // 运行时 + Value: Value.Value, // 运行时 + } + if ok { + Vo.Status = func() int { + if Value.Value == "" { + return 0 + } + return 1 + }() // 运行时 + Vo.LastFetchTime = Value.LastFetchTime // 运行时 + Vo.Value = Value.Value // 运行时 + recordsVo = append(recordsVo, Vo) + } else { + recordsVo = append(recordsVo, Vo) + } } Result := service.WrapPageResult(*pager, recordsVo, count) c.JSON(common.HTTP_OK, common.OkWithData(Result)) diff --git a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go index 9939d1657..5eb2a1bff 100644 --- a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go @@ -236,7 +236,7 @@ func SiemensSheetImport(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(errDb)) return } - if Device.Type != typex.S1200PLC.String() { + if Device.Type != typex.SIEMENS_PLC.String() { c.JSON(common.HTTP_OK, common.Error("Invalid Device Type, Only Support Import Siemens Device")) return diff --git a/component/rulex_api_server/apis/rule_api.go b/component/rulex_api_server/apis/rule_api.go index 8c06a3a7e..e44dfaebe 100644 --- a/component/rulex_api_server/apis/rule_api.go +++ b/component/rulex_api_server/apis/rule_api.go @@ -133,106 +133,109 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } - // 更新FromSource RULE到Device表中 - for _, inId := range form.FromSource { - InEnd, _ := service.GetMInEndWithUUID(inId) - if InEnd == nil { - c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) - return - } - // SaveDB - // - mRule := &model.MRule{ - Name: form.Name, - UUID: rule.UUID, - Description: form.Description, - FromSource: form.FromSource, - FromDevice: form.FromDevice, - Success: form.Success, - Failed: form.Failed, - Actions: form.Actions, - } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range InEnd.BindRules { - ruleMap[rule] = rule - } - // 追加新的ID - ruleMap[inId] = mRule.UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } - InEnd.BindRules = BindRules - if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ - BindRules: BindRules, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } + go func() { + // 更新FromSource RULE到Device表中 + for _, inId := range form.FromSource { + InEnd, _ := service.GetMInEndWithUUID(inId) + if InEnd == nil { + // c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) + return + } + // SaveDB + // + mRule := &model.MRule{ + Name: form.Name, + UUID: rule.UUID, + Description: form.Description, + FromSource: form.FromSource, + FromDevice: form.FromDevice, + Success: form.Success, + Failed: form.Failed, + Actions: form.Actions, + } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range InEnd.BindRules { + ruleMap[rule] = rule + } + // 追加新的ID + ruleMap[inId] = mRule.UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + InEnd.BindRules = BindRules + if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ + BindRules: BindRules, + }); err != nil { + // c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + + if err := service.InsertMRule(mRule); err != nil { + // c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // LoadNewest!!! + if err := server.LoadNewestInEnd(inId, ruleEngine); err != nil { + // c.JSON(common.HTTP_OK, common.Error400(err)) + return + } - if err := service.InsertMRule(mRule); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // LoadNewest!!! - if err := server.LoadNewestInEnd(inId, ruleEngine); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return } - } + // FromDevice + for _, devId := range form.FromDevice { + Device, _ := service.GetMDeviceWithUUID(devId) + if Device == nil { + // c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) + return + } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range Device.BindRules { + ruleMap[rule] = rule // for ["", "", "" ....] + } + // SaveDB + mRule := &model.MRule{ + Name: form.Name, + UUID: rule.UUID, + Description: form.Description, + FromSource: form.FromSource, + FromDevice: form.FromDevice, + Success: form.Success, + Failed: form.Failed, + Actions: form.Actions, + } + // 追加新的ID + ruleMap[devId] = mRule.UUID // append New Rule UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + Device.BindRules = BindRules + if err := service.UpdateDevice(Device.UUID, &model.MDevice{ + BindRules: BindRules, + }); err != nil { + // c.JSON(common.HTTP_OK, common.Error400(err)) + return + } - // FromDevice - for _, devId := range form.FromDevice { - Device, _ := service.GetMDeviceWithUUID(devId) - if Device == nil { - c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) - return - } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range Device.BindRules { - ruleMap[rule] = rule // for ["", "", "" ....] - } - // SaveDB - mRule := &model.MRule{ - Name: form.Name, - UUID: rule.UUID, - Description: form.Description, - FromSource: form.FromSource, - FromDevice: form.FromDevice, - Success: form.Success, - Failed: form.Failed, - Actions: form.Actions, - } - // 追加新的ID - ruleMap[devId] = mRule.UUID // append New Rule UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } - Device.BindRules = BindRules - if err := service.UpdateDevice(Device.UUID, &model.MDevice{ - BindRules: BindRules, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } + if err := service.InsertMRule(mRule); err != nil { + // c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // LoadNewest!!! + if err := server.LoadNewestDevice(devId, ruleEngine); err != nil { + // c.JSON(common.HTTP_OK, common.Error400(err)) + return + } - if err := service.InsertMRule(mRule); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // LoadNewest!!! - if err := server.LoadNewestDevice(devId, ruleEngine); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return } + }() - } c.JSON(common.HTTP_OK, common.Ok()) } @@ -248,7 +251,6 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { FromDevice []string `json:"fromDevice" binding:"required"` Name string `json:"name" binding:"required"` Type string `json:"type"` - Expression string `json:"expression"` Description string `json:"description"` Actions string `json:"actions"` Success string `json:"success"` @@ -259,6 +261,13 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } + // tmpRule 是一个一次性的临时rule,用来验证规则,这么做主要是为了防止真实Lua Vm 被污染 + tmpRule := typex.NewRule(nil, "_", "_", "_", []string{}, []string{}, + form.Success, form.Actions, form.Failed) + if err := core.VerifyLuaSyntax(tmpRule); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } for _, id := range form.FromSource { in := ruleEngine.GetInEnd(id) if in == nil { @@ -273,15 +282,6 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { return } } - // tmpRule 是一个一次性的临时rule,用来验证规则,这么做主要是为了防止真实Lua Vm 被污染 - tmpRule := typex.NewRule(nil, "_", "_", "_", []string{}, []string{}, - form.Success, form.Actions, form.Failed) - - if err := core.VerifyLuaSyntax(tmpRule); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - mRule, err := service.GetMRuleWithUUID(form.UUID) if err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) @@ -316,75 +316,84 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } - // 更新FromSource RULE到Device表中 - for _, inId := range form.FromSource { - if inId != "" { - InEnd, _ := service.GetMInEndWithUUID(inId) - if InEnd == nil { - c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) - return - } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range InEnd.BindRules { - ruleMap[rule] = rule - } - // 追加新的ID - ruleMap[inId] = mRule.UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } - InEnd.BindRules = BindRules - if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ - BindRules: BindRules, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // LoadNewest!!! - if err := server.LoadNewestInEnd(inId, ruleEngine); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - } - } - // FromDevice - for _, devId := range form.FromDevice { - if devId != "" { - Device, _ := service.GetMDeviceWithUUID(devId) - if Device == nil { - c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) - return - } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range Device.BindRules { - ruleMap[rule] = rule // for ["", "", "" ....] - } - // 追加新的ID - ruleMap[devId] = mRule.UUID // append New Rule UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } - Device.BindRules = BindRules - if err := service.UpdateDevice(Device.UUID, &model.MDevice{ - BindRules: BindRules, - }); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return + // 耗时操作直接后台执行 + go func() { + select { + case <-typex.GCTX.Done(): + return + default: + } + // 更新FromSource RULE到Device表中 + for _, inId := range form.FromSource { + if inId != "" { + InEnd, _ := service.GetMInEndWithUUID(inId) + if InEnd == nil { + //c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) + return + } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range InEnd.BindRules { + ruleMap[rule] = rule + } + // 追加新的ID + ruleMap[inId] = mRule.UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + InEnd.BindRules = BindRules + if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ + BindRules: BindRules, + }); err != nil { + //c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // LoadNewest!!! + if err := server.LoadNewestInEnd(inId, ruleEngine); err != nil { + //c.JSON(common.HTTP_OK, common.Error400(err)) + return + } } - // LoadNewest!!! - if err := server.LoadNewestDevice(devId, ruleEngine); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return + + } + // FromDevice + for _, devId := range form.FromDevice { + if devId != "" { + Device, _ := service.GetMDeviceWithUUID(devId) + if Device == nil { + //c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) + return + } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range Device.BindRules { + ruleMap[rule] = rule // for ["", "", "" ....] + } + // 追加新的ID + ruleMap[devId] = mRule.UUID // append New Rule UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + Device.BindRules = BindRules + if err := service.UpdateDevice(Device.UUID, &model.MDevice{ + BindRules: BindRules, + }); err != nil { + //c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // LoadNewest!!! + if err := server.LoadNewestDevice(devId, ruleEngine); err != nil { + //c.JSON(common.HTTP_OK, common.Error400(err)) + return + } } } - } + }() c.JSON(common.HTTP_OK, common.Ok()) } diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 8ff9ae34d..79a0b1bbe 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -347,14 +347,14 @@ func (hs *ApiServerPlugin) LoadRoute() { modbusApi.DELETE(("/delAll"), server.AddRoute(apis.ModbusSheetDeleteAll)) } // S1200 点位表 - S1200Plc := server.RouteGroup(server.ContextUrl("/s1200_data_sheet")) + SIEMENS_PLC := server.RouteGroup(server.ContextUrl("/s1200_data_sheet")) { - S1200Plc.POST(("/sheetImport"), server.AddRoute(apis.SiemensSheetImport)) - S1200Plc.GET(("/sheetExport"), server.AddRoute(apis.SiemensPointsExport)) - S1200Plc.GET(("/list"), server.AddRoute(apis.SiemensSheetPageList)) - S1200Plc.POST(("/update"), server.AddRoute(apis.SiemensSheetUpdate)) - S1200Plc.DELETE(("/delIds"), server.AddRoute(apis.SiemensSheetDelete)) - S1200Plc.DELETE(("/delAll"), server.AddRoute(apis.SiemensSheetDeleteAll)) + SIEMENS_PLC.POST(("/sheetImport"), server.AddRoute(apis.SiemensSheetImport)) + SIEMENS_PLC.GET(("/sheetExport"), server.AddRoute(apis.SiemensPointsExport)) + SIEMENS_PLC.GET(("/list"), server.AddRoute(apis.SiemensSheetPageList)) + SIEMENS_PLC.POST(("/update"), server.AddRoute(apis.SiemensSheetUpdate)) + SIEMENS_PLC.DELETE(("/delIds"), server.AddRoute(apis.SiemensSheetDelete)) + SIEMENS_PLC.DELETE(("/delAll"), server.AddRoute(apis.SiemensSheetDeleteAll)) } // ---------------------------------------------------------------------------------------------- diff --git a/component/rulex_api_server/model/model.go b/component/rulex_api_server/model/model.go index f1d991bc1..05cb40d5f 100644 --- a/component/rulex_api_server/model/model.go +++ b/component/rulex_api_server/model/model.go @@ -55,7 +55,7 @@ type MRule struct { type MInEnd struct { RulexModel // UUID for origin source ID - UUID string `gorm:"not null"` + UUID string `gorm:"uniqueIndex"` Type string `gorm:"not null"` Name string `gorm:"not null"` BindRules StringList `json:"bindRules"` // 与之关联的规则表["A","B","C"] @@ -77,7 +77,7 @@ func (md MInEnd) GetConfig() map[string]interface{} { type MOutEnd struct { RulexModel // UUID for origin source ID - UUID string `gorm:"not null"` + UUID string `gorm:"uniqueIndex"` Type string `gorm:"not null"` Name string `gorm:"not null"` Description string @@ -104,7 +104,7 @@ type MUser struct { // 设备元数据 type MDevice struct { RulexModel - UUID string `gorm:"not null"` + UUID string `gorm:"uniqueIndex"` Name string `gorm:"not null"` Type string `gorm:"not null"` Config string @@ -127,7 +127,7 @@ func (md MDevice) GetConfig() map[string]interface{} { type MGoods struct { RulexModel - UUID string `gorm:"not null"` + UUID string `gorm:"uniqueIndex"` LocalPath string `gorm:"not null"` GoodsType string `gorm:"not null"` // LOCAL, EXTERNAL ExecuteType string `gorm:"not null"` // exe,elf,js,py.... @@ -144,12 +144,12 @@ type MGoods struct { */ type MApp struct { RulexModel - UUID string `gorm:"not null"` // 名称 - Name string `gorm:"not null"` // 名称 - Version string `gorm:"not null"` // 版本号 - AutoStart *bool `gorm:"not null"` // 允许启动 - LuaSource string `gorm:"not null"` // LuaSource - Description string `gorm:"not null"` // 文件路径, 是相对于main的apps目录 + UUID string `gorm:"uniqueIndex"` // 名称 + Name string `gorm:"not null"` // 名称 + Version string `gorm:"not null"` // 版本号 + AutoStart *bool `gorm:"not null"` // 允许启动 + LuaSource string `gorm:"not null"` // LuaSource + Description string `gorm:"not null"` // 文件路径, 是相对于main的apps目录 } /* @@ -159,12 +159,12 @@ type MApp struct { */ type MAiBase struct { RulexModel - UUID string `gorm:"not null"` // 名称 - Name string `gorm:"not null"` // 名称 - Type string `gorm:"not null"` // 类型 - IsBuildIn bool `gorm:"not null"` // 是否内建 - Version string `gorm:"not null"` // 版本号 - Filepath string `gorm:"not null"` // 文件路径, 是相对于main的apps目录 + UUID string `gorm:"uniqueIndex"` // 名称 + Name string `gorm:"not null"` // 名称 + Type string `gorm:"not null"` // 类型 + IsBuildIn bool `gorm:"not null"` // 是否内建 + Version string `gorm:"not null"` // 版本号 + Filepath string `gorm:"not null"` // 文件路径, 是相对于main的apps目录 Description string `gorm:"not null"` } @@ -178,12 +178,12 @@ type MAiBase struct { */ type MVisual struct { RulexModel - UUID string `gorm:"not null"` // 名称 - Name string `gorm:"not null"` // 名称 - Type string `gorm:"not null"` // 类型 - Status bool `gorm:"not null"` // 状态, EDITING, PUBLISH - Content string `gorm:"not null"` // 大屏的内容 - Thumbnail string `gorm:"not null"` // 缩略图 + UUID string `gorm:"uniqueIndex"` // 名称 + Name string `gorm:"not null"` // 名称 + Type string `gorm:"not null"` // 类型 + Status bool `gorm:"not null"` // 状态, EDITING, PUBLISH + Content string `gorm:"not null"` // 大屏的内容 + Thumbnail string `gorm:"not null"` // 缩略图 } /* @@ -193,7 +193,7 @@ type MVisual struct { */ type MGenericGroup struct { RulexModel - UUID string `gorm:"not null"` + UUID string `gorm:"uniqueIndex"` Name string `gorm:"not null"` // 名称 Type string `gorm:"not null"` // 组的类型, DEVICE: 设备分组 Parent string `gorm:"not null"` // 上级, 如果是0表示根节点 @@ -206,7 +206,7 @@ type MGenericGroup struct { */ type MGenericGroupRelation struct { RulexModel - UUID string `gorm:"not null"` + UUID string `gorm:"uniqueIndex"` Gid string `gorm:"not null"` // 分组ID Rid string `gorm:"not null"` // 被绑定方 } @@ -245,7 +245,7 @@ type MWifiConfig struct { */ type MCronTask struct { RulexModel - UUID string `gorm:"not null; default:''" json:"uuid"` + UUID string `gorm:"uniqueIndex,not null; default:''" json:"uuid"` Name string `gorm:"not null;" json:"name"` CronExpr string `gorm:"not null" json:"cronExpr"` // quartz cron expr Enable *bool `json:"enable"` // 是否启用定时任务 diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index c362044fe..18b032b66 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -28,6 +28,7 @@ import ( "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/component/hwportmanager" + modbuscache "github.com/hootrhino/rulex/component/intercache/modbus" "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/core" "github.com/hootrhino/rulex/glogger" @@ -126,6 +127,7 @@ func NewGenericModbusDevice(e typex.RuleX) typex.XDevice { //  初始化 func (mdev *generic_modbus_device) Init(devId string, configMap map[string]interface{}) error { mdev.PointId = devId + modbuscache.RegisterSlot(mdev.PointId) if err := utils.BindSourceConfig(configMap, &mdev.mainConfig); err != nil { return err } @@ -153,6 +155,13 @@ func (mdev *generic_modbus_device) Init(devId string, configMap map[string]inter Quantity: v.Quantity, Frequency: v.Frequency, } + Status := 0 + LastFetchTime := uint64(time.Now().UnixMilli()) + modbuscache.SetValue(mdev.PointId, v.UUID, modbuscache.RegisterPoint{ + UUID: v.UUID, + Status: Status, + LastFetchTime: LastFetchTime, + }) } if mdev.mainConfig.CommonConfig.Mode == "UART" { @@ -356,7 +365,6 @@ func (mdev *generic_modbus_device) Stop() { mdev.CancelCTX() if mdev.mainConfig.CommonConfig.Mode == "UART" { hwportmanager.FreeInterfaceBusy(mdev.mainConfig.PortUuid) - mdev.rtuHandler.Close() } if mdev.mainConfig.CommonConfig.Mode == "UART" { mdev.rtuHandler.Close() @@ -364,6 +372,8 @@ func (mdev *generic_modbus_device) Stop() { if mdev.mainConfig.CommonConfig.Mode == "TCP" { mdev.tcpHandler.Close() } + modbuscache.UnRegisterSlot(mdev.PointId) + } // 设备属性,是一系列属性描述 @@ -419,11 +429,10 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { results, err = mdev.Client.ReadCoils(r.Address, r.Quantity) if err != nil { count-- - mdev.Registers[uuid].Status = 0 glogger.GLogger.Error(err) } Value := covertEmptyHex(results) - value := common.RegisterRW{ + Reg := common.RegisterRW{ Tag: r.Tag, Function: r.Function, SlaverId: r.SlaverId, @@ -432,19 +441,23 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { Alias: r.Alias, Value: Value, } - mdev.Registers[uuid].Value = Value - mdev.Registers[uuid].Status = 1 - mdev.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) - dataMap[r.Tag] = value + dataMap[r.Tag] = Reg + modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ + UUID: uuid, + Status: 0, + Value: Value, + LastFetchTime: uint64(time.Now().UnixMilli()), + }) } if r.Function == common.READ_DISCRETE_INPUT { results, err = mdev.Client.ReadDiscreteInputs(r.Address, r.Quantity) if err != nil { count-- glogger.GLogger.Error(err) + continue } Value := covertEmptyHex(results) - value := common.RegisterRW{ + Reg := common.RegisterRW{ Tag: r.Tag, Function: r.Function, SlaverId: r.SlaverId, @@ -453,11 +466,13 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { Alias: r.Alias, Value: Value, } - mdev.Registers[uuid].Value = Value - mdev.Registers[uuid].Status = 1 - mdev.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) - dataMap[r.Tag] = value - + dataMap[r.Tag] = Reg + modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ + UUID: uuid, + Status: 0, + Value: Value, + LastFetchTime: uint64(time.Now().UnixMilli()), + }) } if r.Function == common.READ_HOLDING_REGISTERS { results, err = mdev.Client.ReadHoldingRegisters(r.Address, r.Quantity) @@ -466,7 +481,7 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { glogger.GLogger.Error(err) } Value := covertEmptyHex(results) - value := common.RegisterRW{ + Reg := common.RegisterRW{ Tag: r.Tag, Function: r.Function, SlaverId: r.SlaverId, @@ -475,10 +490,14 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { Alias: r.Alias, Value: Value, } - mdev.Registers[uuid].Value = Value - mdev.Registers[uuid].Status = 1 - mdev.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) - dataMap[r.Tag] = value + dataMap[r.Tag] = Reg + modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ + UUID: uuid, + Status: 0, + Value: Value, + LastFetchTime: uint64(time.Now().UnixMilli()), + }) + } if r.Function == common.READ_INPUT_REGISTERS { results, err = mdev.Client.ReadInputRegisters(r.Address, r.Quantity) @@ -487,7 +506,7 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { glogger.GLogger.Error(err) } Value := covertEmptyHex(results) - value := common.RegisterRW{ + Reg := common.RegisterRW{ Tag: r.Tag, Function: r.Function, SlaverId: r.SlaverId, @@ -496,10 +515,18 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { Alias: r.Alias, Value: Value, } - mdev.Registers[uuid].Value = Value - mdev.Registers[uuid].Status = 1 - mdev.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) - dataMap[r.Tag] = value + dataMap[r.Tag] = Reg + modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ + UUID: uuid, + Status: func() int { + if Value == "" { + return 0 + } + return 1 + }(), + Value: Value, + LastFetchTime: uint64(time.Now().UnixMilli()), + }) } time.Sleep(time.Duration(r.Frequency) * time.Millisecond) } diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index f36dd4efe..14c8a1f18 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -8,6 +8,8 @@ import ( "sync" "time" + siemenscache "github.com/hootrhino/rulex/component/intercache/siemens" + "github.com/hootrhino/rulex/common" "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/glogger" @@ -18,17 +20,15 @@ import ( // 点位表 type SiemensDataPoint struct { - UUID string `json:"uuid"` // 当UUID为空时新建 - DeviceUuid string `json:"device_uuid"` - Tag string `json:"tag,omitempty"` - Type string `json:"type,omitempty"` - Frequency *int64 `json:"frequency,omitempty"` - Address *int `json:"address,omitempty"` - Start *int `json:"start"` - Size *int `json:"size"` - Status int `json:"status"` // 运行时数据 - LastFetchTime uint64 `json:"lastFetchTime"` // 运行时数据 - Value string `json:"value"` // 运行时数据 + UUID string `json:"uuid"` // 当UUID为空时新建 + DeviceUuid string `json:"device_uuid"` + Tag string `json:"tag,omitempty"` + Type string `json:"type,omitempty"` + Frequency *int64 `json:"frequency,omitempty"` + Address *int `json:"address,omitempty"` + Start *int `json:"start"` + Size *int `json:"size"` + Value string `json:"value"` } type S1200CommonConfig struct { @@ -46,7 +46,7 @@ type S1200Config struct { } // https://www.ad.siemens.com.cn/productportal/prods/s7-1200_plc_easy_plus/07-Program/02-basic/01-Data_Type/01-basic.html -type s1200plc struct { +type SIEMENS_PLC struct { typex.XStatus status typex.DeviceState RuleEngine typex.RuleX @@ -61,8 +61,8 @@ type s1200plc struct { * 西门子 S1200 系列 PLC * */ -func NewS1200plc(e typex.RuleX) typex.XDevice { - s1200 := new(s1200plc) +func NewSIEMENS_PLC(e typex.RuleX) typex.XDevice { + s1200 := new(SIEMENS_PLC) s1200.RuleEngine = e s1200.lock = sync.Mutex{} Rack := 0 @@ -84,8 +84,9 @@ func NewS1200plc(e typex.RuleX) typex.XDevice { } // 初始化 -func (s1200 *s1200plc) Init(devId string, configMap map[string]interface{}) error { +func (s1200 *SIEMENS_PLC) Init(devId string, configMap map[string]interface{}) error { s1200.PointId = devId + siemenscache.RegisterSlot(s1200.PointId) if err := utils.BindSourceConfig(configMap, &s1200.mainConfig); err != nil { glogger.GLogger.Error(err) return err @@ -106,12 +107,19 @@ func (s1200 *s1200plc) Init(devId string, configMap map[string]interface{}) erro return errors.New("'frequency' must grate than 50 millisecond") } s1200.SiemensDataPoints[v.UUID] = &v + + siemenscache.SetValue(s1200.PointId, v.UUID, siemenscache.SiemensPoint{ + UUID: v.UUID, + Status: 0, + LastFetchTime: 0, + Value: "0", + }) } return nil } // 启动 -func (s1200 *s1200plc) Start(cctx typex.CCTX) error { +func (s1200 *SIEMENS_PLC) Start(cctx typex.CCTX) error { s1200.Ctx = cctx.Ctx s1200.CancelCTX = cctx.CancelCTX // @@ -171,7 +179,7 @@ func (s1200 *s1200plc) Start(cctx typex.CCTX) error { } // 从设备里面读数据出来 -func (s1200 *s1200plc) OnRead(cmd []byte, data []byte) (int, error) { +func (s1200 *SIEMENS_PLC) OnRead(cmd []byte, data []byte) (int, error) { return s1200.Read(cmd, data) } @@ -179,7 +187,7 @@ func (s1200 *s1200plc) OnRead(cmd []byte, data []byte) (int, error) { // // db.Address:int, db.Start:int, db.Size:int, rData[] -func (s1200 *s1200plc) OnWrite(cmd []byte, data []byte) (int, error) { +func (s1200 *SIEMENS_PLC) OnWrite(cmd []byte, data []byte) (int, error) { blocks := []SiemensDataPoint{} if err := json.Unmarshal(data, &blocks); err != nil { return 0, err @@ -188,7 +196,7 @@ func (s1200 *s1200plc) OnWrite(cmd []byte, data []byte) (int, error) { } // 设备当前状态 -func (s1200 *s1200plc) Status() typex.DeviceState { +func (s1200 *SIEMENS_PLC) Status() typex.DeviceState { if s1200.client == nil { return typex.DEV_DOWN } @@ -197,40 +205,41 @@ func (s1200 *s1200plc) Status() typex.DeviceState { } // 停止设备 -func (s1200 *s1200plc) Stop() { +func (s1200 *SIEMENS_PLC) Stop() { s1200.status = typex.DEV_DOWN if s1200.CancelCTX != nil { s1200.CancelCTX() } + siemenscache.UnRegisterSlot(s1200.PointId) } // 设备属性,是一系列属性描述 -func (s1200 *s1200plc) Property() []typex.DeviceProperty { +func (s1200 *SIEMENS_PLC) Property() []typex.DeviceProperty { return []typex.DeviceProperty{} } // 真实设备 -func (s1200 *s1200plc) Details() *typex.Device { +func (s1200 *SIEMENS_PLC) Details() *typex.Device { return s1200.RuleEngine.GetDevice(s1200.PointId) } // 状态 -func (s1200 *s1200plc) SetState(status typex.DeviceState) { +func (s1200 *SIEMENS_PLC) SetState(status typex.DeviceState) { s1200.status = status } // 驱动 -func (s1200 *s1200plc) Driver() typex.XExternalDriver { +func (s1200 *SIEMENS_PLC) Driver() typex.XExternalDriver { return nil } -func (s1200 *s1200plc) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { +func (s1200 *SIEMENS_PLC) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { return typex.DCAResult{} } -func (s1200 *s1200plc) OnCtrl(cmd []byte, args []byte) ([]byte, error) { +func (s1200 *SIEMENS_PLC) OnCtrl(cmd []byte, args []byte) ([]byte, error) { return []byte{}, nil } -func (s1200 *s1200plc) Write(cmd []byte, data []byte) (int, error) { +func (s1200 *SIEMENS_PLC) Write(cmd []byte, data []byte) (int, error) { return 0, nil } @@ -238,14 +247,20 @@ func (s1200 *s1200plc) Write(cmd []byte, data []byte) (int, error) { // 读: db --> dbNumber, start, size, buffer[] var rData = [common.T_2KB]byte{} // 一次最大接受2KB数据 -func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { +func (s1200 *SIEMENS_PLC) Read(cmd []byte, data []byte) (int, error) { values := []SiemensDataPoint{} for uuid, db := range s1200.SiemensDataPoints { //DB 4字节 if db.Type == "DB" { // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 if err := s1200.client.AGReadDB(*db.Address, *db.Start, *db.Size, rData[:]); err != nil { - s1200.SiemensDataPoints[uuid].Status = 0 + Status := 0 + LastFetchTime := uint64(time.Now().UnixMilli()) + siemenscache.SetValue(s1200.PointId, uuid, siemenscache.SiemensPoint{ + UUID: uuid, + Status: Status, + LastFetchTime: LastFetchTime, + }) glogger.GLogger.Error(err) return 0, err } @@ -263,14 +278,26 @@ func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { Size: db.Size, Value: Value, }) - s1200.SiemensDataPoints[uuid].Value = Value - s1200.SiemensDataPoints[uuid].Status = 1 - s1200.SiemensDataPoints[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) + Status := 1 + LastFetchTime := uint64(time.Now().UnixMilli()) + siemenscache.SetValue(s1200.PointId, uuid, siemenscache.SiemensPoint{ + UUID: uuid, + Status: Status, + LastFetchTime: LastFetchTime, + Value: Value, + }) } // if db.Type == "MB" { // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 if err := s1200.client.AGReadMB(*db.Start, *db.Size, rData[:]); err != nil { + Status := 0 + LastFetchTime := uint64(time.Now().UnixMilli()) + siemenscache.SetValue(s1200.PointId, uuid, siemenscache.SiemensPoint{ + UUID: uuid, + Status: Status, + LastFetchTime: LastFetchTime, + }) glogger.GLogger.Error(err) return 0, err } @@ -287,9 +314,14 @@ func (s1200 *s1200plc) Read(cmd []byte, data []byte) (int, error) { Size: db.Size, Value: Value, }) - s1200.SiemensDataPoints[uuid].Value = Value - s1200.SiemensDataPoints[uuid].Status = 1 - s1200.SiemensDataPoints[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) + Status := 1 + LastFetchTime := uint64(time.Now().UnixMilli()) + siemenscache.SetValue(s1200.PointId, uuid, siemenscache.SiemensPoint{ + UUID: uuid, + Status: Status, + LastFetchTime: LastFetchTime, + Value: Value, + }) } if *db.Frequency < 100 { *db.Frequency = 100 // 不能太快 diff --git a/device/s1200plc_device.md b/device/s1200plc_device.md index ac7760c18..4e19e1467 100644 --- a/device/s1200plc_device.md +++ b/device/s1200plc_device.md @@ -12,14 +12,14 @@ PLC S1200系列设备提供了丰富的输入输出接口、通信接口和编 ## 参数 ```json { - "name": "S1200PLC", - "type": "S1200PLC", + "name": "SIEMENS_PLC", + "type": "SIEMENS_PLC", "gid": "DROOT", "config": { "host": "127.0.0.1:1500", "rack": 0, "slot": 1, - "model": "S1200PLC", + "model": "SIEMENS_PLC", "timeout": 1000, "autoRequest": true, "idleTimeout": 1000, @@ -35,7 +35,7 @@ PLC S1200系列设备提供了丰富的输入输出接口、通信接口和编 } ] }, - "description": "S1200PLC" + "description": "SIEMENS_PLC" } ``` ## 脚本示例 diff --git a/device/type_loader.go b/device/type_loader.go index cdc5ed563..fb8edcf61 100644 --- a/device/type_loader.go +++ b/device/type_loader.go @@ -17,7 +17,7 @@ func LoadDt() { DM.Register(typex.TSS200V02, &typex.XConfig{}) DM.Register(typex.RTU485_THER, &typex.XConfig{}) DM.Register(typex.YK08_RELAY, &typex.XConfig{}) - DM.Register(typex.S1200PLC, &typex.XConfig{}) + DM.Register(typex.SIEMENS_PLC, &typex.XConfig{}) DM.Register(typex.GENERIC_MODBUS, &typex.XConfig{}) DM.Register(typex.GENERIC_MODBUS_POINT_EXCEL, &typex.XConfig{}) DM.Register(typex.GENERIC_UART, &typex.XConfig{}) diff --git a/driver/modbus_rtu_driver.go b/driver/modbus_rtu_driver.go index 9060e59d4..43f148378 100644 --- a/driver/modbus_rtu_driver.go +++ b/driver/modbus_rtu_driver.go @@ -66,13 +66,12 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { if count == 0 { return 0, nil } - for uuid, r := range d.Registers { + for _, r := range d.Registers { d.handler.SlaveId = r.SlaverId if r.Function == common.READ_COIL { results, err = d.client.ReadCoils(r.Address, r.Quantity) if err != nil { count-- - d.Registers[uuid].Status = 0 glogger.GLogger.Error(err) } Value := covertEmptyHex(results) @@ -85,9 +84,6 @@ func (d *modBusRtuDriver) Read(cmd []byte, data []byte) (int, error) { Alias: r.Alias, Value: Value, } - d.Registers[uuid].Value = Value - d.Registers[uuid].Status = 1 - d.Registers[uuid].LastFetchTime = uint64(time.Now().UnixMilli()) dataMap[r.Tag] = value } if r.Function == common.READ_DISCRETE_INPUT { diff --git a/engine/engine.go b/engine/engine.go index 1c321e5af..1825f0f73 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -27,6 +27,8 @@ import ( "github.com/hootrhino/rulex/component/appstack" "github.com/hootrhino/rulex/component/datacenter" "github.com/hootrhino/rulex/component/hwportmanager" + modbuscache "github.com/hootrhino/rulex/component/intercache/modbus" + siemenscache "github.com/hootrhino/rulex/component/intercache/siemens" "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/component/intermetric" "github.com/hootrhino/rulex/component/internotify" @@ -83,6 +85,10 @@ func InitRuleEngine(config typex.RulexConfig) typex.RuleX { } // Internal DB interdb.Init(__DefaultRuleEngine, __DEFAULT_DB_PATH) + // Init Modbus Point Cache + modbuscache.InitModbusPointCache(__DefaultRuleEngine) + // Init Siemens Point Cache + siemenscache.InitSiemensPointCache(__DefaultRuleEngine) // Internal Bus internotify.InitInternalEventBus(__DefaultRuleEngine, core.GlobalConfig.MaxQueueSize) // 前后交互组件 @@ -193,7 +199,10 @@ func (e *RuleEngine) Stop() { glogger.GLogger.Info("Stop Device:", Device.Name, " Successfully") return true }) - + glogger.GLogger.Info("Flush Modbus Point sheet Cache") + modbuscache.Flush() + glogger.GLogger.Info("Flush Siemens Point sheet Cache") + siemenscache.Flush() glogger.GLogger.Info("[√] Stop Rulex successfully") if err := glogger.Close(); err != nil { fmt.Println("Close logger error: ", err) @@ -444,7 +453,8 @@ func (e *RuleEngine) RestartDevice(uuid string) error { if Value, ok := e.Devices.Load(uuid); ok { Device := Value.(*typex.Device) if Device.Device != nil { - Device.Device.Stop() // Down 以后会被自动拉起来 + // Device.Device.Stop() // Down 以后会被自动拉起来 + Device.Device.SetState(typex.DEV_DOWN) // Down 以后会被自动拉起来 } return nil } @@ -487,10 +497,10 @@ func (e *RuleEngine) InitDeviceTypeManager() error { NewDevice: device.NewRtu485Ther, }, ) - e.DeviceTypeManager.Register(typex.S1200PLC, + e.DeviceTypeManager.Register(typex.SIEMENS_PLC, &typex.XConfig{ Engine: e, - NewDevice: device.NewS1200plc, + NewDevice: device.NewSIEMENS_PLC, }, ) e.DeviceTypeManager.Register(typex.GENERIC_MODBUS, diff --git a/test/device_s1200plc_test.go b/test/device_s1200plc_test.go index cff18dd85..788434b62 100644 --- a/test/device_s1200plc_test.go +++ b/test/device_s1200plc_test.go @@ -66,14 +66,14 @@ func Test_parse_config(t *testing.T) { /* * -* 测试RULEX加载 S1200PLC +* 测试RULEX加载 SIEMENS_PLC * */ -func Test_RULEX_WITH_S1200PLC(t *testing.T) { +func Test_RULEX_WITH_SIEMENS_PLC(t *testing.T) { engine := RunTestEngine() engine.Start() - S1200PLC := typex.NewDevice(typex.S1200PLC, + SIEMENS_PLC := typex.NewDevice(typex.SIEMENS_PLC, "PLC工站系统", "PLC工站系统", map[string]interface{}{ "host": "127.0.0.1", "port": 1800, @@ -99,10 +99,10 @@ func Test_RULEX_WITH_S1200PLC(t *testing.T) { }, }, ) - S1200PLC.UUID = "S1200PLC" + SIEMENS_PLC.UUID = "SIEMENS_PLC" ctx, cancelF := typex.NewCCTX() - if err := engine.LoadDeviceWithCtx(S1200PLC, ctx, cancelF); err != nil { - t.Error("S1200PLC load failed:", err) + if err := engine.LoadDeviceWithCtx(SIEMENS_PLC, ctx, cancelF); err != nil { + t.Error("SIEMENS_PLC load failed:", err) } // // 透传到内部EMQX diff --git a/typex/xdevice.go b/typex/xdevice.go index 781dbad19..d04a3008b 100644 --- a/typex/xdevice.go +++ b/typex/xdevice.go @@ -51,7 +51,7 @@ const ( TSS200V02 DeviceType = "TSS200V02" // Multi params Sensor RTU485_THER DeviceType = "RTU485_THER" // RS485 Sensor YK08_RELAY DeviceType = "YK08_RELAY" // YK8 RS485 Relay - S1200PLC DeviceType = "S1200PLC" // SIEMENS-S71200 + SIEMENS_PLC DeviceType = "SIEMENS_PLC" // SIEMENS-S71200 GENERIC_MODBUS DeviceType = "GENERIC_MODBUS" // 通用Modbus GENERIC_MODBUS_POINT_EXCEL DeviceType = "GENERIC_MODBUS_POINT_EXCEL" // 通用Modbus通过Excel表配置点位 GENERIC_UART DeviceType = "GENERIC_UART" // 通用串口 From 32d9bb57a63b295a7890fb1bd11bde864a028d5c Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 15 Dec 2023 13:58:04 +0800 Subject: [PATCH 115/138] fix: fix group unrelease --- component/rulex_api_server/apis/device_api.go | 25 +++++++++++++----- .../apis/user_lua_template_api.go | 20 ++++++++++++-- component/rulex_api_server/apis/visual_api.go | 22 ++++++++++++--- .../rulex_api_server/service/group_service.go | 6 +++-- test/data/test-modbus-tcp-sheet.xlsx | Bin 0 -> 11920 bytes ...sheet.xlsx => test-modbus-uart-sheet.xlsx} | Bin typex/version.go | 4 +-- 7 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 test/data/test-modbus-tcp-sheet.xlsx rename test/data/{test-modbus-sheet.xlsx => test-modbus-uart-sheet.xlsx} (100%) diff --git a/component/rulex_api_server/apis/device_api.go b/component/rulex_api_server/apis/device_api.go index 3cc1ee617..36d828d2f 100644 --- a/component/rulex_api_server/apis/device_api.go +++ b/component/rulex_api_server/apis/device_api.go @@ -144,15 +144,27 @@ func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { old.Device.Stop() } } - err1 := service.DeleteDevice(uuid) - if err1 != nil { - c.JSON(common.HTTP_OK, common.Error400(err1)) + // 事务 + txErr := interdb.DB().Transaction(func(tx *gorm.DB) error { + Group := service.GetVisualGroup(uuid) + err3 := service.DeleteDevice(uuid) + if err3 != nil { + return err3 + } + // 解除关联 + err2 := interdb.DB().Where("gid=? and rid =?", Group.UUID, uuid). + Delete(&model.MGenericGroupRelation{}).Error + if err2 != nil { + return err2 + } + ruleEngine.RemoveDevice(uuid) + return nil + }) + if txErr != nil { + c.JSON(common.HTTP_OK, common.Error400(txErr)) return } - - ruleEngine.RemoveDevice(uuid) c.JSON(common.HTTP_OK, common.Ok()) - } // 创建设备 @@ -249,6 +261,7 @@ func UpdateDevice(c *gin.Context, ruleEngine typex.RuleX) { if Group.UUID != form.Gid { // 取消绑定分组,删除原来旧的分组 txErr := interdb.DB().Transaction(func(tx *gorm.DB) error { + // 解除关联 err1 := tx.Where("gid=? and rid =?", Group.UUID, Device.UUID). Delete(&model.MGenericGroupRelation{}).Error if err1 != nil { diff --git a/component/rulex_api_server/apis/user_lua_template_api.go b/component/rulex_api_server/apis/user_lua_template_api.go index 3fbe1f7a4..b122dd784 100644 --- a/component/rulex_api_server/apis/user_lua_template_api.go +++ b/component/rulex_api_server/apis/user_lua_template_api.go @@ -2,11 +2,13 @@ package apis import ( "github.com/gin-gonic/gin" + "github.com/hootrhino/rulex/component/interdb" common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" + "gorm.io/gorm" ) type UserLuaTemplateVo struct { @@ -107,8 +109,22 @@ func UpdateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { */ func DeleteUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { uuid, _ := c.GetQuery("uuid") - if err := service.DeleteUserLuaTemplate(uuid); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + txErr := interdb.DB().Transaction(func(tx *gorm.DB) error { + Group := service.GetVisualGroup(uuid) + if err1 := service.DeleteUserLuaTemplate(uuid); err1 != nil { + c.JSON(common.HTTP_OK, common.Error400(err1)) + return err1 + } + // 解除关联 + err2 := interdb.DB().Where("gid=? and rid =?", Group.UUID, uuid). + Delete(&model.MGenericGroupRelation{}).Error + if err2 != nil { + return err2 + } + return nil + }) + if txErr != nil { + c.JSON(common.HTTP_OK, common.Error400(txErr)) return } c.JSON(common.HTTP_OK, common.Ok()) diff --git a/component/rulex_api_server/apis/visual_api.go b/component/rulex_api_server/apis/visual_api.go index 0bcc64af5..e5c934253 100644 --- a/component/rulex_api_server/apis/visual_api.go +++ b/component/rulex_api_server/apis/visual_api.go @@ -9,11 +9,13 @@ import ( "time" "github.com/gin-gonic/gin" + "github.com/hootrhino/rulex/component/interdb" common "github.com/hootrhino/rulex/component/rulex_api_server/common" "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" + "gorm.io/gorm" ) type VisualVo struct { @@ -136,12 +138,26 @@ func PublishVisual(c *gin.Context, ruleEngine typex.RuleX) { */ func DeleteVisual(c *gin.Context, ruleEngine typex.RuleX) { uuid, _ := c.GetQuery("uuid") - if err := service.DeleteVisual(uuid); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + // 事务 + txErr := interdb.DB().Transaction(func(tx *gorm.DB) error { + Group := service.GetVisualGroup(uuid) + if err1 := service.DeleteVisual(uuid); err1 != nil { + c.JSON(common.HTTP_OK, common.Error400(err1)) + return err1 + } + // 解除关联 + err2 := interdb.DB().Where("gid=? and rid =?", Group.UUID, uuid). + Delete(&model.MGenericGroupRelation{}).Error + if err2 != nil { + return err2 + } + return nil + }) + if txErr != nil { + c.JSON(common.HTTP_OK, common.Error400(txErr)) return } c.JSON(common.HTTP_OK, common.Ok()) - } /* diff --git a/component/rulex_api_server/service/group_service.go b/component/rulex_api_server/service/group_service.go index 5677f7be2..37ab47fc8 100644 --- a/component/rulex_api_server/service/group_service.go +++ b/component/rulex_api_server/service/group_service.go @@ -18,6 +18,7 @@ package service import ( "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/component/rulex_api_server/model" + "github.com/hootrhino/rulex/utils" ) // 获取GenericGroup列表 @@ -149,8 +150,9 @@ func BindResource(gid, rid string) error { return err } Relation := model.MGenericGroupRelation{ - Gid: m.UUID, - Rid: rid, + UUID: utils.MakeUUID("GR"), + Gid: m.UUID, + Rid: rid, } if err := interdb.DB().Save(&Relation).Error; err != nil { return err diff --git a/test/data/test-modbus-tcp-sheet.xlsx b/test/data/test-modbus-tcp-sheet.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..cf899fac713a79da6cbfa001131ae076e822f19e GIT binary patch literal 11920 zcmb_?Wn5HU_cqefAl)q;(nw1>fOMyXNOy;HNJt|o-6bh7prlAkN_WH19se1;&F6le z-}~X+A7;*(S!=Jou66Bo_St(W0AOH|pdc++eo+MS{iEFnUl`jMDcIZCI@w=Fztu2eIm1SD=r>8LN*b=9Hw;1njIG8Dw9?|=SJVwxR zBH^%^{3weRvo?6a%;HFKhG2bUqjH79@nEp9-rhxjccu9dF~cS~xq9BemNq}uPVzp! z3BXE?52%qI8A*4aPLAHff;?Xv(UIlk)ODd0CW;U`6o+=%F=E{`9IhrvGRUr4&XHk@ zDAewV(X{v}BX8wq-aUWIWRqYNZp6F*`{icjm*%N8XLDb_7Dck^u+*_YBYSV_l*YHa z=GHUdE*~yzEZqcFEj$*6`8J~~z2iU6+^?lzCV2mXTTdu=Sqpxh&|&gvdG4o)>5i|1 zTa$1{i`VD-JI5?63rrUqrHO6p3R^Jj8!(F7@Qr@$m=U_Ixt)ZqZmQBzK2XnsJ_?lxsuTJak5ww79JeTLomkz{s({Z!@F>Z+T~Y+9^rc)nTUx%g z#NlhwUvpGe%uGt3vU5Aa`6Yei%XyGkgWKMa%~DBu6dm_!iA|sbn#r&oYZ}^%3u6ea zd;OKlvxZHm@aF|0ud3mtL<4-9aI4vT^w#5|m2Ddp%Z6EYllsh9(ROPV{3~B3zmsXe zXYmODt*P_qs%G>!t79ufvnMN|wvRQKg)kAlVQl3PAgp6738{3b+o3^lZl-UZ)vE)s zPDKr%+~ShFw-|Krbz@PUF!v09u&qK{y;eF+Uz}IEGHizdpXnVa^5?ok}O2m z&*#CjR?gJ$5D$@|6`?D<4xT^Z7q2_&X8^;G35Nf{AMiUlINDf20+1Um3TR`)4+8n! zW-h1G%1v1jSanTWl9Lkiy2QuiX=lnjjgb#No9jzb7H}O}>N-8xYnn@B)-xd^4y;U5 z;|mc(fzGVA=C2v}H0+G}g1n+kO>V}5#@-eSmnm#2#nR}AJbWtvRY2?;F>xxu01x*Yvi4(Ws_1ivISq5AWMhmwG>(ZS2reRDtQYM+%RFOnygi%u;HGj} znKm2CV+PJC$KQTjybOc3(Q2f&+6hmH z&50RN<4$~$?8lTKBSvA^ouW_H`|(Bc%rLVpSrb;jp^FbHBCi@jov_ywNV5ERzuF4T zWodKMU7!d(W!28(%#-J4Tv%QBikCEP@_4}xXn}S-b9Q>cd9!g7Ss}Lm>pZ#~CW{s!@AHd;C+cUp{+HD=R#S5iSm2Aa ziw;jtoR3fJ8zzaHpV`&E+cZ_GyV)wVIziuZ7Hn>jdoe%0w0v`7H)X}1elb+(-9U7! zcWxHNQ|Y~%n0X36F zsDH`NJICs|{%|?(L`)GM8Zn;Ye5rNmKK||Y(H2YXZJuHSYa=_YTjXIm`!Iv9b_=Og z)ba4eR@rgiuJBaX$+`8FVYtz)+3byqjj(Xt3|m#Pb?2%@;}q#;%UJnw+2zL>R{|od zWL@=|ONZ(?XJLdio0gk|o7*w))aH*8)uOQT7PAh$yK4Nt*9}mk}$r+Q0 z(#@myk;2rYT`7^?572Ljqi9Q0c1B3NfGy2wP0sI9Kxpdx47+=|MqfzKbB#JlTH+%4 zTuPpH`8^if&@k=FnG)0MP|=kT_@ZtXE1aIN0#8C3SugE-W?QB@{=Bb6gk1d$GWR#;+in&${?AmHqZK=t=Zt3)_v5`pdhL-+;Lsrag_BBNF-7A>rYeB zcr5oT%qG^fLQzLM!GF_MJL16W8m%=nI?=81lj2M~&$XUdG#siJsKFvCia-rkdYo!e zjTHn`sa#U@mCFG6R0K1V;+j+kJCwEunH#lXTD+dp;~h7%44M%{h^r!rLb9}zvTwsh ze;wpi7C)h2Wy$;8%8gZc9Az6HsfS2QfT5z}=}bjOTb5yl1r4_f5mBT@3aP^Nz{v+w z1D8s%Pmxk^wHk#)wXPbR+rMleSb)9QF1iHxwx*#W+g7T$_;$UB3hHl<5$xgitZhG7 z{6v~$w$Np(thb~3){UW3=T0CjidIo&kD|pN9Z*6JEolH`zQVV~_FN`4*A3liFrQee zlIoDU2SfI#k6cot^5Bsa47w^S9Y zxIQR?NW$+ij?=$TtD|~&o)lcs8SFjDBS7-jP=XWN2A!Aig>GZ&cN}H!QDG~B3N^|B zWGgPx8~fj~53)l)p}#eyJ2RBQ5l6aT@}Yyw=uK;sqc|{MC3C>}KMmSZSFCah3g5D$ z(_e+ijCe4NZ50_t4Uoo@!J&A6=6v!A9Z*DWFJsWhe1jj3?Y&I1DTwoL1K$VtgX<$J zjU?>%;5a?(_`CNjQuqA9-Ye|2#V~|;Vre+|`xNE3IBHB!wY$&2k!A=I3P0#Mi#16R z*2Zd?kT)pmAcIkHyUG8odN&f5y|Zn_^C4Ti?qjm{6}u??6`~rrlfyYjNErSZ2)X>Hu=vCUDqF7GlW4))ydPq; zhx!+EEmG2Vj?4XUyo4O)sX<@qA=!ht)+hrB;EPAMa>0T^9xC40Y-be1C~(3|q580Y z*ptM$xZ)u>fec&m<9x6z2liD3wKt{$w1xce;g&EhT_D+~F!uql_rDJdg3pvJ2t%-b^qytR7KV-N2T7so3h>;IJ!zid+pJvQQr6w?ETV< z=WlP{TOPguEaFYw*BQ<5;SjvdZS&JF8P}bM*r1x1P+SPULi_2^nlNp_!9@mzh9cdJ%Gd#%;fz8@IW9;Hm1KaIY|yZZus_-$jdHZ>aG0g%Np1h?%#ds7iKCHpg3u{ zHR_Ww9=O$%RRGfl=Q#cKal?_Kchnm&F&KoC@vq*z4DusOP|^DnV|fV1M1NwO0~yj- zYTg=n;QwIU;XY&eTj(Jee|h~1%)!_HUqt+U%GUm7^3@%amE0=RKB~OdAMkO2W!x0R z+j7Elg-l{IEQvq}fQaf%O^6T{x1`^$g7JI3x(of2c%Z#DEXL3O471>1%_kB}JTQR2 ziE#S!!ZE7p1x104{BVWU_$CGY=S;Xu70=-az_hd8?}E+UqXNeJ zuqXsxvOnSdLE)+^o*(Q(uGC8u`jQd-^=@|EQR81|j0X@N2nLV+e}f08 z)cf~-e#Jdkqg)&1PikPbfceM8bJmFG$93~pHvZ0GNH+HT_Td)UU4_Qy_Q39z64Z0y za9wx2e|Ta`xU-qRD>1ZHoU%LSzOB!^+ww9cvHHz3xhbG!TC?Y_o@;qyqF4D+ao01s z;l-5Qv?V?5T>pLDwJXW%>)U((eT5Bqfd{X!9nDOvO#XU-54gBQIfH|OY6dTyA@4Xp z#qNafmd!hweNjYQ*ez81!r`m4yVQMM&ZCw!=bK_KQ>wAGn?o|G;Y0(j#*Z8OP-~>9 zsl`Qg-qhQPh~%m*D%~UpQqn2i!lmzYx62b};Rd`jm*+^I^YA8XIlYQzR41e6UP!qw^a`n2qwAi)wW0(nN5;0U4- zeHAc`ggwBJn&mx8{+?B@s~>gKL3e*hHpgJfV46Mls56%MS2k%yXme2dQR{VJKN?&| zA-1`JwA-_n?TjCXs&j;1e=t)dO{JVf6g>?|JKl#OfXBXnpN!Bj$7iAcCZ41^5n1tr z=vd6wrans|a(JGJ;KK}*Fd4>p^IT_z^>HYMal174{INou3r;B1;Q74Dj-e0Q<<-f2 zW6*D|Jnl>&ja($jJwm1VQGMcLqUlSVd z)o^*{YrRx`jHc)R{OQ*XLjJHXHS%0icyHLVgY{g2%A2Is4rf?!mUIQVdH7W-?x6|q zF2h|Gip3PEWe7jJ1$CJrR$Ea#g-?Z*GR6XMAxyS?zOW7odTu2xhZjQe@U3M4nJFTY zVd3%UAxKZqhp@^0X8CHN>M&S1UD)06W)C5|2U9?NqaD}tyf5F!^H_23a=2Vy=w>}B$V(xgJziN2W*tA)q(2Jb|3)`IsD=oPTx9?D+KclDNH9HY63Y;-!# zQB263o=Dmf@#kB8jUnIc3HPvfL*)o=0rHVhl{BI_I_2v>q@I~<>O%odI#UVEw`&Uo zGxoVZ*!7vnnlejBHz)`@rrFdD_8!k{t80E@Q?%mK%*v|G?)b8XfOEDgkp^_;`O11Od%qKZs24h;vaZXIpPFP~}wuqt;1b%>Z zWY?;zW|4Zf8N07gOlyF9L#R+8i%LRos6)1%QC7@70J6UU6~@PtOw5EWNm6-)kj3an z?1>fE6&d=&`L03887y(dw%E5(^|@x1F}BH*8~HD7;a#v9#0=TQHK~Z(d{IbaQ5LC3 zOyP#^>lmTX@VI$BXg1dQ%#Bsq-H;cfNrFYmj!q{-xKP#|ErTM*r8>*7bR$2+3tMdF z&CIJavfZMD=g=vb*nT4KZASWoXE&dF$67!+^5n8^!hKgGCLzFVL1RxNw{Qxa1( z{6n>ntO)tH^b{?EP>II7cEr9A)t|;l4w=N84r9W_bXgh)0o-T4Sd=AcKVI#vSZ87^ zWZp=^=~;NrKGW*lQzQ{$cwATdC>3_{qieV%@2M!4?Gg;rK7fpJw6sa6-lA!!D4xX` z+Br@gx;C|!T~4zJF~?-meuT?vf!y{JYPrQ^?M~NIYIEcoM!U-`t9ug)IYkp6uz?nb z{cy`_n#fONdN!*qi+`@f?Kh5l^Uiji9naf5Z;(u}r`{!oZ?A+LP2nrOGfj$%z z>h}kQgQJ_Ji34P3Wk$y$ib$Q{CbHcJpU)2+u`7N5?9tQ=YU3<-U7Ird$}1q zmiFC110K6;mU?`I^!B!7~j2l z)J}AiY7UXF%_#i%p(r4E4)A?L2rH~=3as=~fmF7&Hi`87fXv!Ch_48npo2l`+B-c+CCI`L%&#gSA zqJS*d=1Bp4v7;7N(r5%d+3kmV=G#&Sl!;h1ZZriWJ)?Y=6Ue@o@r)ain}=6MU!H>k zr;S>a9zXDTrkE#|-3a`48pQNj3nwdl*3u?&PRUx6B_}kDa^zTNKpk4-u{c2sffh_k zTvGbg=6MxD{Yd6Y6om|;p_~-RHf%5k1_A1|o>~aX!7XfjjPxNozc$TqNvrU%xXN3~ zVr0w-XkX@Db46(75~>sCuMKFRe%wVS*zyEGLNbpl8f%0<5~|*?xX%aiRg`oCJ+E)8 z_rF$bC2Yuw60XT6yC9?KA~9H)_E~bjalng*mdR60CHJjaSqM0!!7Je8C>G5#l`_bOX6a+rI)LQWY$xEC{srS=pKgUAX1L(^ z1_d+Pq~|SS!=kVMMek@&{q@dZMw;P((EH4(>5qchNcqlsIBPUPH3TXwJKXObao$f_ zwP{2%^#!zyex5AM27j9Kob;XCm>b`Flw2HJ(_+Cy6kKiniLY9`Ug~+4u{B}PkP=a; zTF;=x=H|+{XtSaP0V?W90Si%)-K7P2vu1hSW>MzG=KEqO1|JF2G0ik!0-M9ZIF_mW zjaF-Tqh`;*YG-m=Z?`@miSOLvzJo)z6=^AFvIQE)Lmy_t)#Y-U-k#l)uWW6eUK2xl zfZV`U#_PZT9ifyx78)O+jiMd5I=ra5|^ zlT;wRl@RSy=;?jmp5!noCNhFH=OsP~an;7iAYFIma_-}XF>;{+3q7-7D5*{6TJC6`0Ah(|40~9h!vPK9yH~*$6G9(HQiZv{GhLALK{7to2)7$*i;u&)Y zdMszaCPiIPvDH0=)4)}s`smU8H-_|ttazbpq7Ufd+}U!;L&x&5#~YBJmX0dxz@YUT zru!M|W#q?biF}U4&h5n+bE-%sp+NcAc?G|rfQ@rc-OyBw^KICMQ}^xx!V9{`8+$4% z$y_1UqVdaG+#xpLuVgfpTO1WY*@su92Y8}@0t)0!fY4&AMxFvezXkmf22w6f6d==y zr6fVjL6?sCJOr<9WuYcu&2N=As%NoQFg3xJwy2z`SsMv9wsaJAB+3m%w}K#VosLkgc`86PP@eq3ETRTQs7SE9^k;(H(fhr zyuXICocMU4Q4*a1qrdc>6h8-JJJvkj!9xdC<3$v`rMJbp{P(cE*YeCqJsI~WXy#$9 z8~y4vDeT|+_4ioE=RM0v7xE5PF6OY)nJ9Xi3PmLF9QG6>;N$Fb@j4>|cslh4#RP|n zDmbcb21})XqlN5Q#tkR6h`b@}ndg_LR6L(6;(*>8()*&eMx19A9RhuE!#fD0WPx85 zPW=@ZuP+bd#04Yao#63NXHiJA&j)6z5Hbe5uj%6alT9U`pj8iiFudsQ%73VzDk$K# zKl?cU@Tg$O_{gy;(^qG&7yK!?ol@K$G%Ot!f{4%8 zEiHd@wYY33PWfD{Ed^r@C&kOr<0M~d__8Hs7RYfqUlpR(9!QId?duti8zrduhU=yL zz>S-Y^JPmWuK>ofbWT#TkUMTX9z~`M1^e|fH3MswXl&NP_Q^oHuoqTzh{j-!Mw0i* z#)j}NRA>G((sZx0n+;ZB(~3Zj4`Od}WlB_A^5WuExGB}%Indm1O7D|wM?dnWwj}&! zDK0yjlN6KmU?rCp8rdBUOArf)Rr$$F79QVzze}L@0kCzVmrGq~n#Mh_()S@thJ`(E zXC;=ZKs`*yTdIy1S?c&im{nZ#rVzo9&!sZaDeE|$lHz475@oQAihWuS*pW}UfhcMa zu?l**R@x!P@Q4tdi6DBz*!B1j)Oz2pFqTph8a>~nHz)AA`W?P$kw~3CIIt~*`!hc`**X}x?$506-xUp{127|FuIqs zm{YzeUc^_FhhIX@FY&WT28T8R;~oG$AOUPb3tqj)lN8k;2+rm^QesQpxH2K&O+ON1 zn=LU>j_xK~upOH2zn~LP;8WdOJzZ~C_LgAZY}@KL*h{w8l%Y%z@pgTrH7MikBQ0BH z9aHrLfjWH>%UGsg74e06Kdx{3bXr-v)ZODDbH%<$bhmR}8DfA&&dA6|TDM0wo@+XVc|ioojY1pkPO=dv6T9wh z>2WNN7ZGV<(GDo5`}^Pc8Ko~jp;V9$eaIezC^hD5#a}zsXzpa`LLAzr{P3;#T-Egb zX>2l6l=Rv{HU>`DaC7zo(02CxCcb3*UZJcf0z>rmOkQQ3jroe2Q=RIVg)`7{#O3sz z{7ca8&Ra><;@UZQ+pOX>o=BBz&+$g}h%nKzcfrboMa}Ha3s|lhYE9M9!2VgQ_CRJ4ddYlkZz#zlu}V&!=Cgg3s^k!TVc~U%`7@4rYe-CdSH+_Ajkp z+`YM&jL1FnXCr>K-xxaQd$jw`hKL0PotAd?7>0Auidun|S+WJlrHAs2_xL=2ryMUi zzx*YW&^1;tUuwX#YSvz6$|Z%4{NnY_N+zy^EX$E~s=sik4Oxe>htGI>QdkpDdu)B4 zp0n64w$D0zU3Jq+C)7La(@EMoK>(X zfZQ@4C%6NExwA?(g>@s^;M6PNN+xWnlCtW{1nXz92(%h-;2oEor$iR$Y44bUwiZ{n&j_&JE6TOXw>JEJU&dzmv+yg{lWR!@z_5PERGJZm6BjRfzR zFrN>!)~jxegr{8h#2zuqM687K1Z<@Ey(VPb38RXMAm>e_p(rYQV=;wS&>8nhlmbJU z(^YXWoLa!bqIHCvQaUhRUO%BanoSF*nld<(@>R+z+BiQ*8BR1XcXC-JS|Gq-=OD5P zniMw6YB53WVk~2dMSKVleJb`iZxV(k&9fr{ng5IZtl(FjcnU|>>%auU3f2HpK)cIdGdR=*(1dp9$+SzU#AeP|>%J9ZBr9%0VvYmot4tY>-o*>zwr)CHGE>E2S=(-8 zt{&HjAa>8Bf+}$@&QC=+?uuEX?{M)s1+!TV*rC?G&Iw{{V<~^(yYOj802bi9m6k_; z5IXKMb?r=f>RffZpCnIHUT60{yXyal@KtJ}YSG!R57=m6ANS{^#%$!_`YJJ9gp zxa-@SSpHqQ;lbo6c=)injXa1>a^r8Q@?9M?THT@(oV7zi0MD3&ybo zJUriky^~N6$mMBpNvSC_s)SBpl5*JeicX6i)7vf`d9pB?cYWs~!^3N>pQ4Aft9zvR z18B0gZmA!2wJ#^Q332I5+aE9&yZm=7|Jlv|H#k@Jvha7nFgAeUBm{qhGv0Tx-zVG; zbj{n?P&z^WK>r~xyRQ-Kl4*LK@5W0#po|!O%$_3vv{ULbK4)sab4=7h$p~lxJ?xp9 z`2ZS0r!_ZXQ!wVELt(k#9)WL01EI6N3$fa(eSHr#T)Ki01ga&Q&`bb~RKw8Q-8X(` zNUB#uJ8ob@{~888^!aa6vfdBgVmHk5D$*joaE3zS?`oV5GI6+N2Oo`V9%IG9J>ouDuWHI6wtiO(dlu7=HXgvoEI`1#(pxQ5ZeoE? zDonBr>FP%wOVoa%Y68}{wI#`+7~u(&(aOz^o3E6t@8hVha!sti;xYE$&kk^2b@^Dk z8<7>NCCZM=4nzWQ*B{sudx^*g6}6~FP8owkT!r21={nCpJ?yV&tENBxg0#~=zs4*!=~c8bd)ypd+rrdz z`03Dy`wCtGa1R>$?$P|cn)L6;fP({d4~iW8IYsxcar)lDzgLYxQqK1VDNKDr`zrzc zY4qmJViSVoM5r!!L oti$|siy+f7N9w0O0N>D<-(e838QkzyQ(vKPe7yU;qFB literal 0 HcmV?d00001 diff --git a/test/data/test-modbus-sheet.xlsx b/test/data/test-modbus-uart-sheet.xlsx similarity index 100% rename from test/data/test-modbus-sheet.xlsx rename to test/data/test-modbus-uart-sheet.xlsx diff --git a/typex/version.go b/typex/version.go index ca8aaf5e6..bd9000a5d 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-12 22:03:44", + ReleaseTime: "2023-12-14 21:10:45", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-19b0e24ce3a0e75 +** Version: v0.6.4-1eadfee0a322c92 ** Document: https://hootrhino.github.io ` From e224070af70326e0be1e98a93d162374d3dbe8ce Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 16 Dec 2023 19:07:00 +0800 Subject: [PATCH 116/138] dev: enhancement queue --- device/generic_modbus_device.go | 18 +++++++------ device/s1200plc_device.go | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index 18b032b66..996ccd407 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -265,9 +265,11 @@ func (mdev *generic_modbus_device) Start(cctx typex.CCTX) error { mdev.retryTimes++ continue } - if n > 0 { - mdev.RuleEngine.WorkDevice(mdev.Details(), string(buffer[:n])) + // [] {} "" + if n < 3 { + continue } + mdev.RuleEngine.WorkDevice(mdev.Details(), string(buffer[:n])) } }(mdev.Ctx) @@ -410,7 +412,7 @@ func (mdev *generic_modbus_device) OnCtrl([]byte, []byte) ([]byte, error) { func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { var err error var results []byte - dataMap := map[string]common.RegisterRW{} + RegisterRWs := []common.RegisterRW{} count := len(mdev.Registers) if count == 0 { return 0, nil @@ -441,7 +443,7 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { Alias: r.Alias, Value: Value, } - dataMap[r.Tag] = Reg + RegisterRWs = append(RegisterRWs, Reg) modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ UUID: uuid, Status: 0, @@ -466,7 +468,7 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { Alias: r.Alias, Value: Value, } - dataMap[r.Tag] = Reg + RegisterRWs = append(RegisterRWs, Reg) modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ UUID: uuid, Status: 0, @@ -490,7 +492,7 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { Alias: r.Alias, Value: Value, } - dataMap[r.Tag] = Reg + RegisterRWs = append(RegisterRWs, Reg) modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ UUID: uuid, Status: 0, @@ -515,7 +517,7 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { Alias: r.Alias, Value: Value, } - dataMap[r.Tag] = Reg + RegisterRWs = append(RegisterRWs, Reg) modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ UUID: uuid, Status: func() int { @@ -530,7 +532,7 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { } time.Sleep(time.Duration(r.Frequency) * time.Millisecond) } - bytes, _ := json.Marshal(dataMap) + bytes, _ := json.Marshal(RegisterRWs) copy(buffer, bytes) return len(bytes), nil } diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index 14c8a1f18..a228caf9f 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -5,6 +5,9 @@ import ( "encoding/hex" "encoding/json" "errors" + "fmt" + "strconv" + "strings" "sync" "time" @@ -164,6 +167,10 @@ func (s1200 *SIEMENS_PLC) Start(cctx typex.CCTX) error { s1200.status = typex.DEV_DOWN return } + // [] {} "" + if n < 3 { + continue + } ok, err := s1200.RuleEngine.WorkDevice( s1200.RuleEngine.GetDevice(s1200.PointId), string(dataBuffer[:n]), @@ -332,3 +339,43 @@ func (s1200 *SIEMENS_PLC) Read(cmd []byte, data []byte) (int, error) { copy(data, bytes) return len(bytes), nil } + +/* +* +- 符号地址(Symbolic Addressing): +使用符号名称来表示变量或输入/输出地址。这种方式更加直观和易于理解,适用于高级编程语言和工程师使用。例如,可以使用变量名"MotorSpeed"或输入名"I1"来表示对应的地址。 +- 基于字节的地址(Byte-based Addressing): +使用字节地址和位地址的组合来表示变量或输入/输出地址。字节地址表示内存中的字节偏移,而位地址表示字节中的位偏移。例如,使用地址"DB1.DBX10.3"表示数据块1中偏移为10的字节的第3位。 +- 基于字的地址(Word-based Addressing): +类似于基于字节的地址,但是将地址表示为字(16位)的偏移。例如,使用地址"DB1.DBD20"表示数据块1中偏移为20的字。 +- 基于地址区域的地址(Address Area-based Addressing): +将地址按照不同的区域进行划分,如输入区域(I),输出区域(Q),数据块区域(DB)等。每个区域都有特定的地址范围。例如,使用地址"I10.3"表示输入区域的第10个输入的第3位。 +* +*/ + +// AddressInfo 包含解析后的地址信息 +type AddressInfo struct { + DataBlockNumber int // 数据块号 + DataType string // 数据类型 + ElementNumber int // 元素号 +} + +// 解析DB +func ParseDB_D(s string) string { + return "" +} + +// 解析DBX格式 +func ParseDB_X(s string) string { + return "" +} + +// 解析I格式 +func ParseADDR_I(s string) string { + return "" +} + +// 解析Q格式 +func ParseADDR_Q(s string) string { + return "" +} From 7e72a8fe9a1646668f606cdc725a05aef4d73b51 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 16 Dec 2023 19:30:35 +0800 Subject: [PATCH 117/138] fix: fix plc status and realtime Value --- .../apis/device_s1200_data_sheet_api.go | 27 +++++++++++++---- device/generic_modbus_device.go | 9 ++---- device/s1200plc_device.go | 30 +++---------------- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go index 5eb2a1bff..917765311 100644 --- a/component/rulex_api_server/apis/device_s1200_data_sheet_api.go +++ b/component/rulex_api_server/apis/device_s1200_data_sheet_api.go @@ -24,8 +24,10 @@ import ( "time" "github.com/gin-gonic/gin" + siemenscache "github.com/hootrhino/rulex/component/intercache/siemens" "github.com/hootrhino/rulex/component/interdb" common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" @@ -97,9 +99,10 @@ func SiemensSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { return } recordsVo := []SiemensPointVo{} - for _, record := range records { - recordsVo = append(recordsVo, SiemensPointVo{ + Slot := siemenscache.GetSlot(deviceUuid) + Value, ok := Slot[record.UUID] + Vo := SiemensPointVo{ UUID: record.UUID, DeviceUUID: record.DeviceUuid, Tag: record.Tag, @@ -109,10 +112,22 @@ func SiemensSheetPageList(c *gin.Context, ruleEngine typex.RuleX) { Frequency: record.Frequency, Start: record.Start, Size: record.Size, - Status: 1, // 运行时 - LastFetchTime: uint64(time.Now().UnixMilli()), // 运行时 - Value: "00000000", // 运行时 - }) + LastFetchTime: Value.LastFetchTime, // 运行时 + Value: Value.Value, // 运行时 + } + if ok { + Vo.Status = func() int { + if Value.Value == "" { + return 0 + } + return 1 + }() // 运行时 + Vo.LastFetchTime = Value.LastFetchTime // 运行时 + Vo.Value = Value.Value // 运行时 + recordsVo = append(recordsVo, Vo) + } else { + recordsVo = append(recordsVo, Vo) + } } Result := service.WrapPageResult(*pager, recordsVo, count) c.JSON(common.HTTP_OK, common.OkWithData(Result)) diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index 996ccd407..f291a7c4d 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -519,13 +519,8 @@ func (mdev *generic_modbus_device) modbusRead(buffer []byte) (int, error) { } RegisterRWs = append(RegisterRWs, Reg) modbuscache.SetValue(mdev.PointId, uuid, modbuscache.RegisterPoint{ - UUID: uuid, - Status: func() int { - if Value == "" { - return 0 - } - return 1 - }(), + UUID: uuid, + Status: 0, Value: Value, LastFetchTime: uint64(time.Now().UnixMilli()), }) diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index a228caf9f..13d5aa4e8 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -5,9 +5,6 @@ import ( "encoding/hex" "encoding/json" "errors" - "fmt" - "strconv" - "strings" "sync" "time" @@ -110,7 +107,6 @@ func (s1200 *SIEMENS_PLC) Init(devId string, configMap map[string]interface{}) e return errors.New("'frequency' must grate than 50 millisecond") } s1200.SiemensDataPoints[v.UUID] = &v - siemenscache.SetValue(s1200.PointId, v.UUID, siemenscache.SiemensPoint{ UUID: v.UUID, Status: 0, @@ -261,13 +257,6 @@ func (s1200 *SIEMENS_PLC) Read(cmd []byte, data []byte) (int, error) { if db.Type == "DB" { // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 if err := s1200.client.AGReadDB(*db.Address, *db.Start, *db.Size, rData[:]); err != nil { - Status := 0 - LastFetchTime := uint64(time.Now().UnixMilli()) - siemenscache.SetValue(s1200.PointId, uuid, siemenscache.SiemensPoint{ - UUID: uuid, - Status: Status, - LastFetchTime: LastFetchTime, - }) glogger.GLogger.Error(err) return 0, err } @@ -285,12 +274,10 @@ func (s1200 *SIEMENS_PLC) Read(cmd []byte, data []byte) (int, error) { Size: db.Size, Value: Value, }) - Status := 1 - LastFetchTime := uint64(time.Now().UnixMilli()) siemenscache.SetValue(s1200.PointId, uuid, siemenscache.SiemensPoint{ UUID: uuid, - Status: Status, - LastFetchTime: LastFetchTime, + Status: 0, + LastFetchTime: uint64(time.Now().UnixMilli()), Value: Value, }) } @@ -298,13 +285,6 @@ func (s1200 *SIEMENS_PLC) Read(cmd []byte, data []byte) (int, error) { if db.Type == "MB" { // 00.00.00.01 | 00.00.00.02 | 00.00.00.03 | 00.00.00.04 if err := s1200.client.AGReadMB(*db.Start, *db.Size, rData[:]); err != nil { - Status := 0 - LastFetchTime := uint64(time.Now().UnixMilli()) - siemenscache.SetValue(s1200.PointId, uuid, siemenscache.SiemensPoint{ - UUID: uuid, - Status: Status, - LastFetchTime: LastFetchTime, - }) glogger.GLogger.Error(err) return 0, err } @@ -321,12 +301,10 @@ func (s1200 *SIEMENS_PLC) Read(cmd []byte, data []byte) (int, error) { Size: db.Size, Value: Value, }) - Status := 1 - LastFetchTime := uint64(time.Now().UnixMilli()) siemenscache.SetValue(s1200.PointId, uuid, siemenscache.SiemensPoint{ UUID: uuid, - Status: Status, - LastFetchTime: LastFetchTime, + Status: 0, + LastFetchTime: uint64(time.Now().UnixMilli()), Value: Value, }) } From fc496b5cd2362baa343eb6e71b0b35788f635fcc Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 17 Dec 2023 18:23:42 +0800 Subject: [PATCH 118/138] dev: enhance CURD with Transaction --- component/rulex_api_server/apis/device_api.go | 63 ++++------------ .../apis/user_lua_template_api.go | 75 ++++++++++--------- component/rulex_api_server/apis/visual_api.go | 34 ++++----- .../rulex_api_server/dto/user_lua_template.go | 23 ++++++ .../model/user_lua_template.go | 45 +++++++++-- .../rulex_api_server/service/group_service.go | 49 ++++++++++++ typex/version.go | 4 +- 7 files changed, 182 insertions(+), 111 deletions(-) create mode 100644 component/rulex_api_server/dto/user_lua_template.go diff --git a/component/rulex_api_server/apis/device_api.go b/component/rulex_api_server/apis/device_api.go index 36d828d2f..71c44173c 100644 --- a/component/rulex_api_server/apis/device_api.go +++ b/component/rulex_api_server/apis/device_api.go @@ -239,59 +239,26 @@ func UpdateDevice(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error("missing 'uuid' fields")) return } - // 更新的时候从数据库往外面拿 - Device, err := service.GetMDeviceWithUUID(form.UUID) - if err != nil { - c.JSON(common.HTTP_OK, err) - return - } - MDevice := model.MDevice{ - Type: form.Type, - Name: form.Name, - Description: form.Description, - Config: string(configJson), - } - if err := service.UpdateDevice(Device.UUID, &MDevice); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - - // 只有检查到分组变了才更改 - Group := service.GetVisualGroup(Device.UUID) - if Group.UUID != form.Gid { - // 取消绑定分组,删除原来旧的分组 - txErr := interdb.DB().Transaction(func(tx *gorm.DB) error { - // 解除关联 - err1 := tx.Where("gid=? and rid =?", Group.UUID, Device.UUID). - Delete(&model.MGenericGroupRelation{}).Error - if err1 != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return err1 - } - // 重新绑定分组,首先确定分组是否存在 - MGroup := model.MGenericGroup{} - if err2 := interdb.DB().Where("uuid=?", Group.UUID).First(&MGroup).Error; err2 != nil { - return err2 - } - Relation := model.MGenericGroupRelation{ - Gid: MGroup.UUID, - Rid: Device.UUID, - } - err3 := tx.Save(&Relation).Error - if err3 != nil { - return err3 - } - return nil - }) - if txErr != nil { - c.JSON(common.HTTP_OK, common.Error400(txErr)) - return + // + // 取消绑定分组,删除原来旧的分组 + txErr := service.ReBindResource(func(tx *gorm.DB) error { + MDevice := model.MDevice{ + Type: form.Type, + Name: form.Name, + Description: form.Description, + Config: string(configJson), } + return tx.Model(MDevice). + Where("uuid=?", form.UUID). + Updates(&MDevice).Error + }, form.UUID, form.Gid) + if txErr != nil { + c.JSON(common.HTTP_OK, common.Error400(txErr)) + return } if err := server.LoadNewestDevice(form.UUID, ruleEngine); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } - c.JSON(common.HTTP_OK, common.Ok()) } diff --git a/component/rulex_api_server/apis/user_lua_template_api.go b/component/rulex_api_server/apis/user_lua_template_api.go index b122dd784..c88483396 100644 --- a/component/rulex_api_server/apis/user_lua_template_api.go +++ b/component/rulex_api_server/apis/user_lua_template_api.go @@ -4,6 +4,7 @@ import ( "github.com/gin-gonic/gin" "github.com/hootrhino/rulex/component/interdb" common "github.com/hootrhino/rulex/component/rulex_api_server/common" + "github.com/hootrhino/rulex/component/rulex_api_server/dto" "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/component/rulex_api_server/service" "github.com/hootrhino/rulex/typex" @@ -12,12 +13,13 @@ import ( ) type UserLuaTemplateVo struct { - Gid string `json:"gid,omitempty"` // 分组ID - UUID string `json:"uuid,omitempty"` // 名称 - Label string `json:"label"` // 快捷代码名称 - Apply string `json:"apply"` // 快捷代码 - Type string `json:"type"` // 类型 固定为function类型detail - Detail string `json:"detail"` + Gid string `json:"gid,omitempty"` // 分组ID + UUID string `json:"uuid,omitempty"` // 名称 + Label string `json:"label"` // 快捷代码名称 + Apply string `json:"apply"` // 快捷代码 + Type string `json:"type"` // 类型 固定为function类型detail + Detail string `json:"detail"` // 细节 + Variables []dto.LuaTemplateVariables `json:"variables"` // 变量 } /* @@ -80,20 +82,20 @@ func UpdateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { Detail: form.Detail, Gid: form.Gid, } - - if err := service.UpdateUserLuaTemplate(MUserLuaTemplate); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // 取消绑定分组,删除原来旧的分组 - Group := service.GetUserLuaTemplateGroup(MUserLuaTemplate.UUID) - if err := service.UnBindResource(Group.UUID, MUserLuaTemplate.UUID); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + Variables, errVariables := MUserLuaTemplate.GenVariables(form.Variables) + if errVariables != nil { + c.JSON(common.HTTP_OK, common.Error400(errVariables)) return } - // 重新绑定分组 - if err := service.BindResource(form.Gid, MUserLuaTemplate.UUID); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + MUserLuaTemplate.Variables = Variables + // 事务 + txErr := service.ReBindResource(func(tx *gorm.DB) error { + return tx.Model(MUserLuaTemplate). + Where("uuid=?", MUserLuaTemplate.UUID). + Updates(&MUserLuaTemplate).Error + }, form.UUID, form.Gid) + if txErr != nil { + c.JSON(common.HTTP_OK, common.Error400(txErr)) return } // 返回新建的用户模板字段 用来跳转编辑器 @@ -173,12 +175,13 @@ func ListUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { UserLuaTemplates := []UserLuaTemplateVo{} for _, vv := range service.AllUserLuaTemplate() { Vo := UserLuaTemplateVo{ - UUID: vv.UUID, - Label: vv.Label, - Type: vv.Type, - Apply: vv.Apply, - Detail: vv.Detail, - Gid: vv.Gid, + UUID: vv.UUID, + Label: vv.Label, + Type: vv.Type, + Apply: vv.Apply, + Detail: vv.Detail, + Gid: vv.Gid, + Variables: vv.GetVariables(), } Group := service.GetUserLuaTemplateGroup(vv.UUID) if Group.UUID != "" { @@ -203,12 +206,13 @@ func ListUserLuaTemplateByGroup(c *gin.Context, ruleEngine typex.RuleX) { MUserLuaTemplates := service.FindUserTemplateByGroup(Gid) for _, vv := range MUserLuaTemplates { Vo := UserLuaTemplateVo{ - UUID: vv.UUID, - Label: vv.Label, - Type: vv.Type, - Apply: vv.Apply, - Detail: vv.Detail, - Gid: vv.Gid, + UUID: vv.UUID, + Label: vv.Label, + Type: vv.Type, + Apply: vv.Apply, + Detail: vv.Detail, + Gid: vv.Gid, + Variables: vv.GetVariables(), } Group := service.GetUserLuaTemplateGroup(vv.UUID) Vo.Gid = Group.UUID @@ -230,11 +234,12 @@ func UserLuaTemplateDetail(c *gin.Context, ruleEngine typex.RuleX) { return } Vo := UserLuaTemplateVo{ - UUID: mUserLuaTemplate.UUID, - Label: mUserLuaTemplate.Label, - Type: mUserLuaTemplate.Type, - Apply: mUserLuaTemplate.Apply, - Detail: mUserLuaTemplate.Detail, + UUID: mUserLuaTemplate.UUID, + Label: mUserLuaTemplate.Label, + Type: mUserLuaTemplate.Type, + Apply: mUserLuaTemplate.Apply, + Detail: mUserLuaTemplate.Detail, + Variables: mUserLuaTemplate.GetVariables(), } Group := service.GetUserLuaTemplateGroup(mUserLuaTemplate.UUID) if Group.UUID != "" { diff --git a/component/rulex_api_server/apis/visual_api.go b/component/rulex_api_server/apis/visual_api.go index e5c934253..197e0515a 100644 --- a/component/rulex_api_server/apis/visual_api.go +++ b/component/rulex_api_server/apis/visual_api.go @@ -79,31 +79,25 @@ func UpdateVisual(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } - MVisual := model.MVisual{ - UUID: form.UUID, - Name: form.Name, - Type: form.Type, - Content: form.Content, - } - - if err := service.UpdateVisual(MVisual); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } // 取消绑定分组,删除原来旧的分组 - Group := service.GetVisualGroup(MVisual.UUID) - if err := service.UnBindResource(Group.UUID, MVisual.UUID); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // 重新绑定分组 - if err := service.BindResource(form.Gid, MVisual.UUID); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) + txErr := service.ReBindResource(func(tx *gorm.DB) error { + MVisual := model.MVisual{ + UUID: form.UUID, + Name: form.Name, + Type: form.Type, + Content: form.Content, + } + return tx.Model(MVisual). + Where("uuid=?", MVisual.UUID). + Updates(&MVisual).Error + }, form.UUID, form.Gid) + if txErr != nil { + c.JSON(common.HTTP_OK, common.Error400(txErr)) return } // 返回新建的大屏字段 用来跳转编辑器 c.JSON(common.HTTP_OK, common.OkWithData(map[string]string{ - "uuid": MVisual.UUID, + "uuid": form.UUID, })) } diff --git a/component/rulex_api_server/dto/user_lua_template.go b/component/rulex_api_server/dto/user_lua_template.go new file mode 100644 index 000000000..09d4f9271 --- /dev/null +++ b/component/rulex_api_server/dto/user_lua_template.go @@ -0,0 +1,23 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +package dto + +// 变量 +type LuaTemplateVariables struct { + Name string `json:"name"` + Type string `json:"type"` + Label string `json:"label"` + Value any `json:"value"` +} diff --git a/component/rulex_api_server/model/user_lua_template.go b/component/rulex_api_server/model/user_lua_template.go index b764f9c9c..0d4103934 100644 --- a/component/rulex_api_server/model/user_lua_template.go +++ b/component/rulex_api_server/model/user_lua_template.go @@ -14,6 +14,11 @@ // along with this program. If not, see . package model +import ( + "github.com/hootrhino/rulex/component/rulex_api_server/dto" + "gopkg.in/square/go-jose.v2/json" +) + /* * * 用户自定义代码模板 @@ -21,10 +26,38 @@ package model */ type MUserLuaTemplate struct { RulexModel - UUID string - Gid string // 分组 - Type string // 类型 固定为 'function' - Label string //快捷代码名称 - Apply string //快捷代码 - Detail string + UUID string + Gid string // 分组 + Type string // 类型 固定为 'function' + Label string //快捷代码名称 + Apply string //快捷代码 + Variables string //变量 + Detail string +} + +/* +* +* 获取其变量表 +* + */ +func (md MUserLuaTemplate) GetVariables() []dto.LuaTemplateVariables { + result := make([]dto.LuaTemplateVariables, 0) + err := json.Unmarshal([]byte(md.Variables), &result) + if err != nil { + return result + } + return result +} + +/* +* +* 生成字符串 +* + */ +func (md MUserLuaTemplate) GenVariables(V []dto.LuaTemplateVariables) (string, error) { + B, err := json.Marshal(V) + if err != nil { + return "", err + } + return string(B), nil } diff --git a/component/rulex_api_server/service/group_service.go b/component/rulex_api_server/service/group_service.go index 37ab47fc8..6a3eeab6f 100644 --- a/component/rulex_api_server/service/group_service.go +++ b/component/rulex_api_server/service/group_service.go @@ -19,6 +19,7 @@ import ( "github.com/hootrhino/rulex/component/interdb" "github.com/hootrhino/rulex/component/rulex_api_server/model" "github.com/hootrhino/rulex/utils" + "gorm.io/gorm" ) // 获取GenericGroup列表 @@ -200,3 +201,51 @@ func CheckAlreadyBinding(gid, rid string) (uint, error) { } return uint(count), nil } + +/* +* +* 重新绑定分组需要事务支持 +* + */ +func ReBindResource(action func(tx *gorm.DB) error, Rid, Gid string) error { + return interdb.DB().Transaction(func(tx *gorm.DB) error { + // 1 执行的操作 + if err0 := action(tx); err0 != nil { + return err0 + } + // 2 解除分组关联 + sql := ` +SELECT m_generic_groups.* +FROM m_generic_group_relations +LEFT JOIN +m_generic_groups ON (m_generic_groups.uuid = m_generic_group_relations.gid) +WHERE m_generic_group_relations.rid = ?; + ` + OldGroup := model.MGenericGroup{} + if errA := tx.Raw(sql, Rid).Find(&OldGroup).Error; errA != nil { + return errA + } + if err1 := tx.Model(model.MGenericGroupRelation{}). + Where("gid=? and rid =?", OldGroup.UUID, Rid). + Delete(&model.MGenericGroupRelation{}).Error; err1 != nil { + return err1 + } + // 3 重新绑定分组,首先确定分组是否存在 + MGroup := model.MGenericGroup{} + if err2 := tx.Model(MGroup). + Where("uuid=?", Gid). + First(&MGroup).Error; err2 != nil { + return err2 + } + // 4 重新绑定分组 + err3 := tx.Save(&model.MGenericGroupRelation{ + UUID: utils.MakeUUID("GRLT"), + Gid: Gid, + Rid: Rid, + }).Error + if err3 != nil { + return err3 + } + return nil + }) +} diff --git a/typex/version.go b/typex/version.go index bd9000a5d..1bf20d181 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-14 21:10:45", + ReleaseTime: "2023-12-16 22:18:59", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-1eadfee0a322c92 +** Version: v0.6.4-7e72a8fe9a16466 ** Document: https://hootrhino.github.io ` From ddaa19732b59596f99202e751dc09534516d6055 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 17 Dec 2023 23:31:29 +0800 Subject: [PATCH 119/138] feat: design internal Event Bus first version --- component/eventbus/eventbus.go | 127 +++++++++++++++++++++++++++++++++ component/eventbus/eventbus.md | 33 ++++++++- test/eventbus_test.go | 45 ++++++++++++ 3 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 test/eventbus_test.go diff --git a/component/eventbus/eventbus.go b/component/eventbus/eventbus.go index 2de0fe3b3..dfc71488e 100644 --- a/component/eventbus/eventbus.go +++ b/component/eventbus/eventbus.go @@ -15,10 +15,137 @@ package eventbus +import ( + "context" + "fmt" + + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" +) + +var __DefaultEventBus *EventBus + /* * * 内部消息总线 * */ +type EventMessage struct { + Payload string +} + +func (E EventMessage) String() string { + return fmt.Sprintf("Event Message@ Payload: %s", E.Payload) +} + +type Topic struct { + Topic string + channel chan EventMessage + Subscribers map[string]*Subscriber + ctx context.Context + cancel context.CancelFunc +} +type Subscriber struct { + id string + Callback func(Topic string, Msg EventMessage) +} type EventBus struct { + // Topic, chan EventMessage + // 给每个订阅者分配一个Channel,实现消息订阅 + // Topic一样的会挂在同一个树上 + Topics map[string]*Topic // 订阅树: MAP[]Subscribers +} + +func InitEventBus() *EventBus { + __DefaultEventBus = &EventBus{ + Topics: map[string]*Topic{}, + } + return __DefaultEventBus +} + +/* +* +* 订阅 +* + */ +func Subscribe(topic string, subscribe *Subscriber) { + NewUUID := utils.MakeUUID("SUB") + subscribe.id = NewUUID + var T *Topic + Ok := false + if T, Ok = __DefaultEventBus.Topics[topic]; Ok { + T.Subscribers[subscribe.id] = subscribe + } else { + T = new(Topic) + T.channel = make(chan EventMessage, 100) + T.Subscribers = map[string]*Subscriber{} + T.Topic = topic + T.Subscribers[subscribe.id] = subscribe + __DefaultEventBus.Topics[topic] = T + ctx, cancel := context.WithCancel(typex.GCTX) + T.ctx = ctx + T.cancel = cancel + go func(T *Topic) { + for { + select { + case <-T.ctx.Done(): + { + return + } + case Msg := <-T.channel: + for _, Subscriber := range T.Subscribers { + if Subscriber.Callback != nil { + Subscriber.Callback(T.Topic, Msg) + } + } + } + } + + }(T) + } + +} + +/* +* +* 取消订阅 +* + */ +func UnSubscribe(topic string, subscribe Subscriber) { + T, Ok1 := __DefaultEventBus.Topics[topic] + if Ok1 { + if _, Ok2 := T.Subscribers[subscribe.id]; Ok2 { + delete(__DefaultEventBus.Topics[topic].Subscribers, subscribe.id) + } + } + if len(T.Subscribers) == 0 { + T.cancel() + } +} + +/* +* +* 发布 +* + */ +func Publish(topic string, Msg EventMessage) { + T, Ok1 := __DefaultEventBus.Topics[topic] + if Ok1 { + T.channel <- Msg + } +} + +/* +* +* 释放所有 +* + */ +func Flush() { + for _, T := range __DefaultEventBus.Topics { + for _, S := range T.Subscribers { + delete(T.Subscribers, S.id) + } + T.cancel() + delete(__DefaultEventBus.Topics, T.Topic) + } } diff --git a/component/eventbus/eventbus.md b/component/eventbus/eventbus.md index 9e13357a9..f7e50b84a 100644 --- a/component/eventbus/eventbus.md +++ b/component/eventbus/eventbus.md @@ -2,6 +2,35 @@ 类似于Nats一样的简单Pub\Sub框架 ## 示例 ```go - ebus.publish("a.b.c", "data") - ebus.subscribe("a.b.c", func(data)) + +package test + +import ( + "fmt" + "testing" + "time" + + "github.com/hootrhino/rulex/component/eventbus" +) + +func TestEventBus(t *testing.T) { + + eventbus.InitEventBus() + eventbus.Subscribe("hello", &eventbus.Subscriber{ + Callback: func(Topic string, Msg eventbus.EventMessage) { + t.Log("hello:", Msg) + }, + }) + start := time.Now() + for i := 0; i < 100; i++ { + eventbus.Publish("hello", eventbus.EventMessage{ + Payload: fmt.Sprintf("world:%d", i), + }) + } + duration := time.Since(start) + t.Log("time.Since(start):", duration) + time.Sleep(3 * time.Second) + eventbus.Flush() +} + ``` \ No newline at end of file diff --git a/test/eventbus_test.go b/test/eventbus_test.go new file mode 100644 index 000000000..e7b839cb1 --- /dev/null +++ b/test/eventbus_test.go @@ -0,0 +1,45 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package test + +import ( + "fmt" + "testing" + "time" + + "github.com/hootrhino/rulex/component/eventbus" +) + +// @ go test -timeout 30s -run ^TestEventBus github.com/hootrhino/rulex/test -v -count=1 +func TestEventBus(t *testing.T) { + + eventbus.InitEventBus() + eventbus.Subscribe("hello", &eventbus.Subscriber{ + Callback: func(Topic string, Msg eventbus.EventMessage) { + t.Log("hello:", Msg) + }, + }) + start := time.Now() + for i := 0; i < 100; i++ { + eventbus.Publish("hello", eventbus.EventMessage{ + Payload: fmt.Sprintf("world:%d", i), + }) + } + duration := time.Since(start) + t.Log("time.Since(start):", duration) + time.Sleep(3 * time.Second) + eventbus.Flush() +} From 9d05ccb0d131b4058f1e8df7d437275bab9f1359 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sun, 17 Dec 2023 23:41:22 +0800 Subject: [PATCH 120/138] dev: delete Topics when no subscribers --- component/eventbus/eventbus.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/component/eventbus/eventbus.go b/component/eventbus/eventbus.go index dfc71488e..403ea4706 100644 --- a/component/eventbus/eventbus.go +++ b/component/eventbus/eventbus.go @@ -35,7 +35,7 @@ type EventMessage struct { } func (E EventMessage) String() string { - return fmt.Sprintf("Event Message@ Payload: %s", E.Payload) + return fmt.Sprintf("Event Message@ Payload: %s", E.Payload) } type Topic struct { @@ -118,8 +118,10 @@ func UnSubscribe(topic string, subscribe Subscriber) { delete(__DefaultEventBus.Topics[topic].Subscribers, subscribe.id) } } + // 当没有订阅者的时候直接删除这个Topic if len(T.Subscribers) == 0 { T.cancel() + delete(__DefaultEventBus.Topics, topic) } } From bc8db3b3a6144a283f6313e7da402009dcc8fbe5 Mon Sep 17 00:00:00 2001 From: wwhai Date: Mon, 18 Dec 2023 23:55:03 +0800 Subject: [PATCH 121/138] dev: add http device; add get snapshot, get logfile API --- common/modbus_config.go | 2 +- component/hwportmanager/hwport_manager.go | 3 +- .../apis/rhinoh3_firmware_api.go | 31 ++++ component/rulex_api_server/apis/system_api.go | 6 +- component/rulex_api_server/http_api_server.go | 4 +- device/__device_template.go | 107 +++++++++++++ device/generic_http_device.go | 142 ++++++++++++++++++ device/generic_snmp_device.go | 2 +- device/generic_snmp_device.md | 2 +- device/generic_uart_device.go | 2 +- device/generic_uart_device.md | 2 +- device/network_icmp_sender.go | 2 +- device/usr_g776_4gdtu_device.go | 2 +- device/usr_g776_4gdtu_device.md | 2 +- engine/engine.go | 6 + ossupport/linux_const_value.go | 2 + test/modbus_master_test.go | 11 +- typex/version.go | 4 +- typex/xdevice.go | 1 + 19 files changed, 311 insertions(+), 22 deletions(-) create mode 100644 device/__device_template.go create mode 100644 device/generic_http_device.go diff --git a/common/modbus_config.go b/common/modbus_config.go index e36e357ab..49757a49a 100644 --- a/common/modbus_config.go +++ b/common/modbus_config.go @@ -81,7 +81,7 @@ type ModBusConfig struct { Mode string `json:"mode" title:"工作模式" info:"UART/TCP"` Timeout int `json:"timeout" validate:"required" title:"连接超时"` // Weather allow AutoRequest? - AutoRequest bool `json:"autoRequest" title:"启动轮询"` + AutoRequest bool `json:"autoRequest" validate:"required"` // Request Frequency, default 5 second Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` Config interface{} `json:"config" validate:"required" title:"工作模式"` diff --git a/component/hwportmanager/hwport_manager.go b/component/hwportmanager/hwport_manager.go index 7d7a7b8db..f45adf1db 100644 --- a/component/hwportmanager/hwport_manager.go +++ b/component/hwportmanager/hwport_manager.go @@ -171,10 +171,9 @@ func FreeInterfaceBusy(name string) { defer __HwPortsManager.lock.Unlock() if Port, ok := __HwPortsManager.Interfaces[name]; ok { if Port.OccupyBy.Type == "DEVICE" { - // OccupierDevice := __HwPortsManager.rulex.GetDevice(Port.OccupyBy.UUID) Port.Busy = false Port.OccupyBy = HwPortOccupy{ - "", "", "", + "-", "-", "-", } __HwPortsManager.Interfaces[name] = Port } diff --git a/component/rulex_api_server/apis/rhinoh3_firmware_api.go b/component/rulex_api_server/apis/rhinoh3_firmware_api.go index b33d8e01e..02f7abfb0 100644 --- a/component/rulex_api_server/apis/rhinoh3_firmware_api.go +++ b/component/rulex_api_server/apis/rhinoh3_firmware_api.go @@ -17,7 +17,10 @@ package apis import ( + "fmt" + "net/http" "os" + "time" "github.com/gin-gonic/gin" common "github.com/hootrhino/rulex/component/rulex_api_server/common" @@ -66,3 +69,31 @@ func GetUpGradeLog(c *gin.Context, ruleEngine typex.RuleX) { byteS, _ := os.ReadFile(ossupport.UpgradeLogPath) c.JSON(common.HTTP_OK, common.OkWithData(string(byteS))) } + +/* +* +* 下载运行日志 +* + */ +func GetRunningLog(c *gin.Context, ruleEngine typex.RuleX) { + c.Writer.WriteHeader(http.StatusOK) + if RunningLogPathExists(ossupport.RunningLogPath) { + c.FileAttachment(ossupport.RunningLogPath, + fmt.Sprintf("running_log_%d_.txt", time.Now().UnixNano())) + } else { + js := `` + c.Writer.Write([]byte(js)) + } + c.Writer.Flush() + +} +func RunningLogPathExists(path string) bool { + _, err := os.Stat(path) + if err == nil { + return true + } + if os.IsNotExist(err) { + return false + } + return false +} diff --git a/component/rulex_api_server/apis/system_api.go b/component/rulex_api_server/apis/system_api.go index ef9163e7c..f3804fc8c 100644 --- a/component/rulex_api_server/apis/system_api.go +++ b/component/rulex_api_server/apis/system_api.go @@ -139,7 +139,11 @@ func System(c *gin.Context, ruleEngine typex.RuleX) { * */ func SnapshotDump(c *gin.Context, ruleEngine typex.RuleX) { - c.JSON(common.HTTP_OK, common.OkWithData(ruleEngine.SnapshotDump())) + c.Header("Content-Type", "text/plain") + c.Header("Content-Disposition", + fmt.Sprintf("attachment;filename=SnapshotDump_%v.json", time.Now().UnixMilli())) + c.Writer.Write([]byte(ruleEngine.SnapshotDump())) + c.Writer.Flush() } // Get all Drivers diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 79a0b1bbe..e7fbf70d7 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -233,7 +233,6 @@ func (hs *ApiServerPlugin) LoadRoute() { systemApi := server.RouteGroup(server.ContextUrl("/")) { systemApi.GET(("/ping"), server.AddRoute(apis.Ping)) - systemApi.POST(("/logout"), server.AddRoute(apis.LogOut)) } // @@ -245,7 +244,6 @@ func (hs *ApiServerPlugin) LoadRoute() { // Get statistics data // server.DefaultApiServer.Route().GET(server.ContextUrl("statistics"), server.AddRoute(apis.Statistics)) - server.DefaultApiServer.Route().GET(server.ContextUrl("snapshot"), server.AddRoute(apis.SnapshotDump)) // // Auth // @@ -322,6 +320,8 @@ func (hs *ApiServerPlugin) LoadRoute() { { backupApi.GET(("/download"), server.AddRoute(apis.DownloadSqlite)) backupApi.POST(("/upload"), server.AddRoute(apis.UploadSqlite)) + backupApi.GET(("/snapshot"), server.AddRoute(apis.SnapshotDump)) + backupApi.GET(("/runningLog"), server.AddRoute(apis.GetRunningLog)) } // // 设备管理 diff --git a/device/__device_template.go b/device/__device_template.go new file mode 100644 index 000000000..a2a327ca5 --- /dev/null +++ b/device/__device_template.go @@ -0,0 +1,107 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package device + +import ( + "sync" + + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" +) + +type TemplateDevice struct { + typex.XStatus +} + +func NewTemplateDevice(e typex.RuleX) typex.XDevice { + hd := new(TemplateDevice) + hd.RuleEngine = e + return hd +} + +//  初始化 +func (hd *TemplateDevice) Init(devId string, configMap map[string]interface{}) error { + hd.PointId = devId + if err := utils.BindSourceConfig(configMap, &hd.mainConfig); err != nil { + glogger.GLogger.Error(err) + return err + } + + return nil +} + +// 启动 +func (hd *TemplateDevice) Start(cctx typex.CCTX) error { + hd.Ctx = cctx.Ctx + hd.CancelCTX = cctx.CancelCTX + + hd.status = typex.DEV_UP + return nil +} + +func (hd *TemplateDevice) OnRead(cmd []byte, data []byte) (int, error) { + + return 0, nil +} + +// 把数据写入设备 +func (hd *TemplateDevice) OnWrite(cmd []byte, b []byte) (int, error) { + return 0, nil +} + +// 设备当前状态 +func (hd *TemplateDevice) Status() typex.DeviceState { + return typex.DEV_UP +} + +// 停止设备 +func (hd *TemplateDevice) Stop() { + hd.status = typex.DEV_STOP + hd.CancelCTX() +} + +// 设备属性,是一系列属性描述 +func (hd *TemplateDevice) Property() []typex.DeviceProperty { + return []typex.DeviceProperty{} +} + +// 真实设备 +func (hd *TemplateDevice) Details() *typex.Device { + return hd.RuleEngine.GetDevice(hd.PointId) +} + +// 状态 +func (hd *TemplateDevice) SetState(status typex.DeviceState) { + hd.status = status + +} + +// 驱动 +func (hd *TemplateDevice) Driver() typex.XExternalDriver { + return nil +} + +// -------------------------------------------------------------------------------------------------- +// +// -------------------------------------------------------------------------------------------------- + +func (hd *TemplateDevice) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { + return typex.DCAResult{} +} +func (hd *TemplateDevice) OnCtrl(cmd []byte, args []byte) ([]byte, error) { + return []byte{}, nil +} diff --git a/device/generic_http_device.go b/device/generic_http_device.go new file mode 100644 index 000000000..171b04e6d --- /dev/null +++ b/device/generic_http_device.go @@ -0,0 +1,142 @@ +package device + +import ( + "net/http" + "sync" + "time" + + "github.com/hootrhino/rulex/common" + "github.com/hootrhino/rulex/glogger" + "github.com/hootrhino/rulex/typex" + "github.com/hootrhino/rulex/utils" +) + +type __HttpCommonConfig struct { + Timeout int `json:"timeout" validate:"required"` + AutoRequest bool `json:"autoRequest" validate:"required"` + Frequency int64 `json:"frequency" validate:"required"` +} +type __HttpMainConfig struct { + CommonConfig __HttpCommonConfig `json:"commonConfig" validate:"required"` + HttpConfig common.HTTPConfig `json:"httpConfig" validate:"required"` +} + +type GenericHttpDevice struct { + typex.XStatus + client http.Client + status typex.DeviceState + RuleEngine typex.RuleX + mainConfig __HttpMainConfig + locker sync.Locker +} + +/* +* +* 通用串口透传 +* + */ +func NewGenericHttpDevice(e typex.RuleX) typex.XDevice { + hd := new(GenericHttpDevice) + hd.locker = &sync.Mutex{} + hd.client = *http.DefaultClient + hd.mainConfig = __HttpMainConfig{} + hd.RuleEngine = e + return hd +} + +//  初始化 +func (hd *GenericHttpDevice) Init(devId string, configMap map[string]interface{}) error { + hd.PointId = devId + if err := utils.BindSourceConfig(configMap, &hd.mainConfig); err != nil { + glogger.GLogger.Error(err) + return err + } + + return nil +} + +// 启动 +func (hd *GenericHttpDevice) Start(cctx typex.CCTX) error { + hd.Ctx = cctx.Ctx + hd.CancelCTX = cctx.CancelCTX + + if hd.mainConfig.CommonConfig.AutoRequest { + ticker := time.NewTicker( + time.Duration(hd.mainConfig.CommonConfig.Frequency) * time.Millisecond) + go func() { + for { + select { + case <-hd.Ctx.Done(): + { + ticker.Stop() + return + } + default: + { + } + } + body := utils.Get(hd.client, hd.mainConfig.HttpConfig.Url) + if body != "" { + hd.RuleEngine.WorkDevice(hd.Details(), body) + } + <-ticker.C + } + }() + + } + hd.status = typex.DEV_UP + return nil +} + +func (hd *GenericHttpDevice) OnRead(cmd []byte, data []byte) (int, error) { + + return 0, nil +} + +// 把数据写入设备 +func (hd *GenericHttpDevice) OnWrite(cmd []byte, b []byte) (int, error) { + return 0, nil +} + +// 设备当前状态 +func (hd *GenericHttpDevice) Status() typex.DeviceState { + return typex.DEV_UP +} + +// 停止设备 +func (hd *GenericHttpDevice) Stop() { + hd.status = typex.DEV_STOP + hd.CancelCTX() +} + +// 设备属性,是一系列属性描述 +func (hd *GenericHttpDevice) Property() []typex.DeviceProperty { + return []typex.DeviceProperty{} +} + +// 真实设备 +func (hd *GenericHttpDevice) Details() *typex.Device { + return hd.RuleEngine.GetDevice(hd.PointId) +} + +// 状态 +func (hd *GenericHttpDevice) SetState(status typex.DeviceState) { + hd.status = status + +} + +// 驱动 +func (hd *GenericHttpDevice) Driver() typex.XExternalDriver { + return nil +} + +// -------------------------------------------------------------------------------------------------- +// +// -------------------------------------------------------------------------------------------------- + +func (hd *GenericHttpDevice) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { + return typex.DCAResult{} +} +func (hd *GenericHttpDevice) OnCtrl(cmd []byte, args []byte) ([]byte, error) { + return []byte{}, nil +} diff --git a/device/generic_snmp_device.go b/device/generic_snmp_device.go index a8957ee49..5c2d647c7 100644 --- a/device/generic_snmp_device.go +++ b/device/generic_snmp_device.go @@ -14,7 +14,7 @@ import ( ) type _SNMPCommonConfig struct { - AutoRequest bool `json:"autoRequest" title:"启动轮询"` + AutoRequest bool `json:"autoRequest" validate:"required"` Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` } diff --git a/device/generic_snmp_device.md b/device/generic_snmp_device.md index e4168df06..5165f0989 100644 --- a/device/generic_snmp_device.md +++ b/device/generic_snmp_device.md @@ -14,7 +14,7 @@ SNMP协议支持各种版本,其中最常用的是SNMPv1、SNMPv2c和SNMPv3。 ```go type _SNMPCommonConfig struct { - AutoRequest bool `json:"autoRequest" title:"启动轮询"` + AutoRequest bool `json:"autoRequest" validate:"required"` Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` } type GenericSnmpConfig struct { diff --git a/device/generic_uart_device.go b/device/generic_uart_device.go index 09ccf33df..225f374e5 100644 --- a/device/generic_uart_device.go +++ b/device/generic_uart_device.go @@ -18,7 +18,7 @@ import ( type _GUDCommonConfig struct { Tag string `json:"tag" validate:"required"` Frequency int64 `json:"frequency"` - AutoRequest bool `json:"autoRequest"` + AutoRequest bool `json:"autoRequest" validate:"required"` // 协议报文结束符号 Separator string `json:"separator"` } diff --git a/device/generic_uart_device.md b/device/generic_uart_device.md index f1e5b258c..65a299f30 100644 --- a/device/generic_uart_device.md +++ b/device/generic_uart_device.md @@ -9,7 +9,7 @@ type GenericUartConfig struct { // 结束符, 默认是 '\n';但是可以自己定义 Decollator string `json:"decollator" title:"协议分隔符"` // Weather allow AutoRequest? - AutoRequest bool `json:"autoRequest" title:"启动轮询"` + AutoRequest bool `json:"autoRequest" validate:"required"` // Request Frequency, default 5 second Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` Timeout int `json:"timeout" validate:"required" title:"连接超时"` diff --git a/device/network_icmp_sender.go b/device/network_icmp_sender.go index c9c3d74b3..bbbea2e86 100644 --- a/device/network_icmp_sender.go +++ b/device/network_icmp_sender.go @@ -16,7 +16,7 @@ import ( type _IcmpSenderCommonConfig struct { Timeout int `json:"timeout" validate:"required"` // // Weather allow AutoRequest? - AutoRequest bool `json:"autoRequest" title:"启动轮询"` + AutoRequest bool `json:"autoRequest" validate:"required"` // // Request Frequency, default 5 second Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` } diff --git a/device/usr_g776_4gdtu_device.go b/device/usr_g776_4gdtu_device.go index 70b17f49a..80d61c2f0 100644 --- a/device/usr_g776_4gdtu_device.go +++ b/device/usr_g776_4gdtu_device.go @@ -21,7 +21,7 @@ import ( type _G776CommonConfig struct { Tag string `json:"tag" validate:"required" title:"数据Tag" info:"给数据打标签"` Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` - AutoRequest bool `json:"autoRequest" title:"启动轮询"` + AutoRequest bool `json:"autoRequest" validate:"required"` } type _G776Config struct { diff --git a/device/usr_g776_4gdtu_device.md b/device/usr_g776_4gdtu_device.md index 5b4cad925..4795028e0 100644 --- a/device/usr_g776_4gdtu_device.md +++ b/device/usr_g776_4gdtu_device.md @@ -11,7 +11,7 @@ RULEX对USR-G776做了一个非常简单的支持:直接向串口透传数据 type _G776CommonConfig struct { Tag string `json:"tag" validate:"required" title:"数据Tag" info:"给数据打标签"` Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` - AutoRequest bool `json:"autoRequest" title:"启动轮询"` + AutoRequest bool `json:"autoRequest" validate:"required"` } type CommonUartConfig struct { Timeout int `json:"timeout" validate:"required"` diff --git a/engine/engine.go b/engine/engine.go index 1825f0f73..682fc30a5 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -467,6 +467,12 @@ func (e *RuleEngine) RestartDevice(uuid string) error { * */ func (e *RuleEngine) InitDeviceTypeManager() error { + e.DeviceTypeManager.Register(typex.GENERIC_HTTP_DEVICE, + &typex.XConfig{ + Engine: e, + NewDevice: device.NewGenericHttpDevice, + }, + ) e.DeviceTypeManager.Register(typex.GENERIC_CAMERA, &typex.XConfig{ Engine: e, diff --git a/ossupport/linux_const_value.go b/ossupport/linux_const_value.go index 05312fb59..0efe3d7c0 100644 --- a/ossupport/linux_const_value.go +++ b/ossupport/linux_const_value.go @@ -29,6 +29,8 @@ const ( FirmwarePath = "/usr/local/upload/Firmware/Firmware.zip" // 升级日志 UpgradeLogPath = "/usr/local/local-upgrade-log.txt" + // 运行时日志 + RunningLogPath = "/usr/local/rulexlog.txt" // 数据恢复日志 RecoverLogPath = "/usr/local/local-recover-log.txt" // 备份锁 diff --git a/test/modbus_master_test.go b/test/modbus_master_test.go index 5da1081f2..d48719e2e 100644 --- a/test/modbus_master_test.go +++ b/test/modbus_master_test.go @@ -13,13 +13,10 @@ type registerParam struct { } type ModBusConfig struct { - Mode string `json:"mode" title:"工作模式" info:"可以在 UART/TCP 两个模式之间切换"` - Timeout int `json:"timeout" validate:"required" title:"连接超时"` - SlaverId byte `json:"slaverId" validate:"required" title:"TCP端口"` - // - // Weather allow AutoRequest? - AutoRequest bool `json:"autoRequest" title:"启动轮询"` - // Request Frequency, default 5 second + Mode string `json:"mode" title:"工作模式" info:"可以在 UART/TCP 两个模式之间切换"` + Timeout int `json:"timeout" validate:"required" title:"连接超时"` + SlaverId byte `json:"slaverId" validate:"required" title:"TCP端口"` + AutoRequest bool `json:"autoRequest" validate:"required"` Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` Config interface{} `json:"config" validate:"required" title:"工作模式配置"` RegisterParams []registerParam `json:"registerParams" validate:"required" title:"寄存器配置"` diff --git a/typex/version.go b/typex/version.go index 1bf20d181..4b2c878ff 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-16 22:18:59", + ReleaseTime: "2023-12-18 20:59:21", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-7e72a8fe9a16466 +** Version: v0.6.4-9d05ccb0d131b40 ** Document: https://hootrhino.github.io ` diff --git a/typex/xdevice.go b/typex/xdevice.go index d04a3008b..b9bdcf8cd 100644 --- a/typex/xdevice.go +++ b/typex/xdevice.go @@ -64,6 +64,7 @@ const ( GENERIC_AIS_RECEIVER DeviceType = "GENERIC_AIS_RECEIVER" // 通用AIS GENERIC_BACNET_IP DeviceType = "GENERIC_BACNET_IP" // 通用BacnetIP RHINOPI_IR DeviceType = "RHINOPI_IR" // 大犀牛PI的红外线接收器 + GENERIC_HTTP_DEVICE DeviceType = "GENERIC_HTTP_DEVICE" // GENERIC_HTTP ) // 设备元数据, 本质是保存在配置里面的数据的一个内存映射实例 From 9478c389bf9eda5dd05aacaee4d379e1cc1fe54f Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 19 Dec 2023 00:22:10 +0800 Subject: [PATCH 122/138] fix: fix panic when CancelCTX is nil --- device/generic_modbus_device.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index f291a7c4d..5db34cb89 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -364,7 +364,9 @@ func (mdev *generic_modbus_device) Status() typex.DeviceState { // 停止设备 func (mdev *generic_modbus_device) Stop() { mdev.status = typex.DEV_DOWN - mdev.CancelCTX() + if mdev.CancelCTX != nil { + mdev.CancelCTX() + } if mdev.mainConfig.CommonConfig.Mode == "UART" { hwportmanager.FreeInterfaceBusy(mdev.mainConfig.PortUuid) } From c088a66f466d66c1729801b51f005eeee28b474e Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 19 Dec 2023 13:40:50 +0800 Subject: [PATCH 123/138] fix: concurrent map write error --- component/hwportmanager/hwport_manager.go | 2 ++ component/intercache/modbus/modbus_cache.go | 32 ++++++++++++++----- component/intercache/siemens/siemens_cache.go | 32 ++++++++++++++----- device/generic_http_device.go | 4 ++- typex/version.go | 4 +-- 5 files changed, 55 insertions(+), 19 deletions(-) diff --git a/component/hwportmanager/hwport_manager.go b/component/hwportmanager/hwport_manager.go index f45adf1db..03fe869c2 100644 --- a/component/hwportmanager/hwport_manager.go +++ b/component/hwportmanager/hwport_manager.go @@ -104,6 +104,8 @@ func RefreshPort(Port RhinoH3HwPort) { * */ func refreshHwPort(name string) { + __HwPortsManager.lock.Lock() + defer __HwPortsManager.lock.Unlock() Port, ok := __HwPortsManager.Interfaces[name] if !ok { return diff --git a/component/intercache/modbus/modbus_cache.go b/component/intercache/modbus/modbus_cache.go index 52881d03d..907521253 100644 --- a/component/intercache/modbus/modbus_cache.go +++ b/component/intercache/modbus/modbus_cache.go @@ -15,6 +15,8 @@ package modbus import ( + "sync" + "github.com/hootrhino/rulex/component/intercache" "github.com/hootrhino/rulex/typex" ) @@ -59,48 +61,62 @@ func Flush() { type ModbusPointCache struct { Slots map[string]map[string]RegisterPoint ruleEngine typex.RuleX + lock sync.Mutex } func InitModbusPointCache(ruleEngine typex.RuleX) intercache.InterCache { __DefaultModbusPointCache = &ModbusPointCache{ ruleEngine: ruleEngine, Slots: map[string]map[string]RegisterPoint{}, + lock: sync.Mutex{}, } return __DefaultModbusPointCache } -func (M ModbusPointCache) RegisterSlot(Slot string) { +func (M *ModbusPointCache) RegisterSlot(Slot string) { + M.lock.Lock() + defer M.lock.Unlock() M.Slots[Slot] = map[string]RegisterPoint{} } -func (M ModbusPointCache) GetSlot(Slot string) map[string]RegisterPoint { +func (M *ModbusPointCache) GetSlot(Slot string) map[string]RegisterPoint { + M.lock.Lock() + defer M.lock.Unlock() if S, ok := M.Slots[Slot]; ok { return S } return nil } -func (M ModbusPointCache) SetValue(Slot, K string, V RegisterPoint) { +func (M *ModbusPointCache) SetValue(Slot, K string, V RegisterPoint) { + M.lock.Lock() + defer M.lock.Unlock() if S, ok := M.Slots[Slot]; ok { S[K] = V M.Slots[Slot] = S } } -func (M ModbusPointCache) GetValue(Slot, K string) RegisterPoint { +func (M *ModbusPointCache) GetValue(Slot, K string) RegisterPoint { + M.lock.Lock() + defer M.lock.Unlock() if S, ok := M.Slots[Slot]; ok { return S[K] } return RegisterPoint{} } -func (M ModbusPointCache) DeleteValue(Slot, K string) { +func (M *ModbusPointCache) DeleteValue(Slot, K string) { + M.lock.Lock() + defer M.lock.Unlock() if S, ok := M.Slots[Slot]; ok { delete(S, Slot) } } -func (M ModbusPointCache) UnRegisterSlot(Slot string) { +func (M *ModbusPointCache) UnRegisterSlot(Slot string) { + M.lock.Lock() + defer M.lock.Unlock() delete(M.Slots, Slot) } -func (M ModbusPointCache) Size() uint64 { +func (M *ModbusPointCache) Size() uint64 { return uint64(len(M.Slots)) } -func (M ModbusPointCache) Flush() { +func (M *ModbusPointCache) Flush() { for slotName, slot := range M.Slots { for k, _ := range slot { delete(slot, k) diff --git a/component/intercache/siemens/siemens_cache.go b/component/intercache/siemens/siemens_cache.go index 367773d4f..51050bc1e 100644 --- a/component/intercache/siemens/siemens_cache.go +++ b/component/intercache/siemens/siemens_cache.go @@ -15,6 +15,8 @@ package siemens import ( + "sync" + "github.com/hootrhino/rulex/component/intercache" "github.com/hootrhino/rulex/typex" ) @@ -57,48 +59,62 @@ func Flush() { type SiemensPointCache struct { Slots map[string]map[string]SiemensPoint ruleEngine typex.RuleX + lock sync.Mutex } func InitSiemensPointCache(ruleEngine typex.RuleX) intercache.InterCache { __DefaultSiemensPointCache = &SiemensPointCache{ ruleEngine: ruleEngine, Slots: map[string]map[string]SiemensPoint{}, + lock: sync.Mutex{}, } return __DefaultSiemensPointCache } -func (M SiemensPointCache) RegisterSlot(Slot string) { +func (M *SiemensPointCache) RegisterSlot(Slot string) { + M.lock.Lock() + defer M.lock.Unlock() M.Slots[Slot] = map[string]SiemensPoint{} } -func (M SiemensPointCache) GetSlot(Slot string) map[string]SiemensPoint { +func (M *SiemensPointCache) GetSlot(Slot string) map[string]SiemensPoint { + M.lock.Lock() + defer M.lock.Unlock() if S, ok := M.Slots[Slot]; ok { return S } return nil } -func (M SiemensPointCache) SetValue(Slot, K string, V SiemensPoint) { +func (M *SiemensPointCache) SetValue(Slot, K string, V SiemensPoint) { + M.lock.Lock() + defer M.lock.Unlock() if S, ok := M.Slots[Slot]; ok { S[K] = V M.Slots[Slot] = S } } -func (M SiemensPointCache) GetValue(Slot, K string) SiemensPoint { +func (M *SiemensPointCache) GetValue(Slot, K string) SiemensPoint { + M.lock.Lock() + defer M.lock.Unlock() if S, ok := M.Slots[Slot]; ok { return S[K] } return SiemensPoint{} } -func (M SiemensPointCache) DeleteValue(Slot, K string) { +func (M *SiemensPointCache) DeleteValue(Slot, K string) { + M.lock.Lock() + defer M.lock.Unlock() if S, ok := M.Slots[Slot]; ok { delete(S, Slot) } } -func (M SiemensPointCache) UnRegisterSlot(Slot string) { +func (M *SiemensPointCache) UnRegisterSlot(Slot string) { + M.lock.Lock() + defer M.lock.Unlock() delete(M.Slots, Slot) } -func (M SiemensPointCache) Size() uint64 { +func (M *SiemensPointCache) Size() uint64 { return uint64(len(M.Slots)) } -func (M SiemensPointCache) Flush() { +func (M *SiemensPointCache) Flush() { for slotName, slot := range M.Slots { for k, _ := range slot { delete(slot, k) diff --git a/device/generic_http_device.go b/device/generic_http_device.go index 171b04e6d..110982854 100644 --- a/device/generic_http_device.go +++ b/device/generic_http_device.go @@ -106,7 +106,9 @@ func (hd *GenericHttpDevice) Status() typex.DeviceState { // 停止设备 func (hd *GenericHttpDevice) Stop() { hd.status = typex.DEV_STOP - hd.CancelCTX() + if hd.CancelCTX != nil { + hd.CancelCTX() + } } // 设备属性,是一系列属性描述 diff --git a/typex/version.go b/typex/version.go index 4b2c878ff..75212c13e 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-18 20:59:21", + ReleaseTime: "2023-12-19 13:36:12", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-9d05ccb0d131b40 +** Version: v0.6.4-9478c389bf9eda5 ** Document: https://hootrhino.github.io ` From 262636351d2bae71ff9a09ed48825a08ae01f3ad Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 19 Dec 2023 19:09:31 +0800 Subject: [PATCH 124/138] fix: fix http, modbus nil panic --- component/hwportmanager/hwport_manager.go | 2 -- device/generic_http_device.go | 10 +++---- device/generic_http_device.md | 32 +++++++++++++++++++++++ device/generic_modbus_device.go | 8 ++++-- device/s1200plc_device.go | 14 ++++++---- typex/version.go | 4 +-- 6 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 device/generic_http_device.md diff --git a/component/hwportmanager/hwport_manager.go b/component/hwportmanager/hwport_manager.go index 03fe869c2..f45adf1db 100644 --- a/component/hwportmanager/hwport_manager.go +++ b/component/hwportmanager/hwport_manager.go @@ -104,8 +104,6 @@ func RefreshPort(Port RhinoH3HwPort) { * */ func refreshHwPort(name string) { - __HwPortsManager.lock.Lock() - defer __HwPortsManager.lock.Unlock() Port, ok := __HwPortsManager.Interfaces[name] if !ok { return diff --git a/device/generic_http_device.go b/device/generic_http_device.go index 110982854..8d669f6f4 100644 --- a/device/generic_http_device.go +++ b/device/generic_http_device.go @@ -12,9 +12,9 @@ import ( ) type __HttpCommonConfig struct { - Timeout int `json:"timeout" validate:"required"` - AutoRequest bool `json:"autoRequest" validate:"required"` - Frequency int64 `json:"frequency" validate:"required"` + Timeout *int `json:"timeout" validate:"required"` + AutoRequest *bool `json:"autoRequest" validate:"required"` + Frequency *int64 `json:"frequency" validate:"required"` } type __HttpMainConfig struct { CommonConfig __HttpCommonConfig `json:"commonConfig" validate:"required"` @@ -60,9 +60,9 @@ func (hd *GenericHttpDevice) Start(cctx typex.CCTX) error { hd.Ctx = cctx.Ctx hd.CancelCTX = cctx.CancelCTX - if hd.mainConfig.CommonConfig.AutoRequest { + if *hd.mainConfig.CommonConfig.AutoRequest { ticker := time.NewTicker( - time.Duration(hd.mainConfig.CommonConfig.Frequency) * time.Millisecond) + time.Duration(*hd.mainConfig.CommonConfig.Frequency) * time.Millisecond) go func() { for { select { diff --git a/device/generic_http_device.md b/device/generic_http_device.md new file mode 100644 index 000000000..7b5cd1885 --- /dev/null +++ b/device/generic_http_device.md @@ -0,0 +1,32 @@ +## Http 采集器 +主要用来请求远程HTTP接口,采集这类设备的数据。 + +## 配置 + +```json +{ + "code": 200, + "msg": "Success", + "data": { + "uuid": "DEVICEP6VNYAAK", + "gid": "DROOT", + "name": "HTTP请求设备", + "type": "GENERIC_HTTP_DEVICE", + "state": 1, + "config": { + "commonConfig": { + "autoRequest": true, + "frequency": 1000, + "timeout": 3000 + }, + "httpConfig": { + "headers": { + "token": "12345" + }, + "url": "http://127.0.0.1:8080" + } + }, + "description": "" + } +} +``` \ No newline at end of file diff --git a/device/generic_modbus_device.go b/device/generic_modbus_device.go index 5db34cb89..c45695323 100644 --- a/device/generic_modbus_device.go +++ b/device/generic_modbus_device.go @@ -371,10 +371,14 @@ func (mdev *generic_modbus_device) Stop() { hwportmanager.FreeInterfaceBusy(mdev.mainConfig.PortUuid) } if mdev.mainConfig.CommonConfig.Mode == "UART" { - mdev.rtuHandler.Close() + if mdev.rtuHandler != nil { + mdev.rtuHandler.Close() + } } if mdev.mainConfig.CommonConfig.Mode == "TCP" { - mdev.tcpHandler.Close() + if mdev.tcpHandler != nil { + mdev.tcpHandler.Close() + } } modbuscache.UnRegisterSlot(mdev.PointId) diff --git a/device/s1200plc_device.go b/device/s1200plc_device.go index 13d5aa4e8..d6924a523 100644 --- a/device/s1200plc_device.go +++ b/device/s1200plc_device.go @@ -52,6 +52,7 @@ type SIEMENS_PLC struct { RuleEngine typex.RuleX mainConfig S1200Config client gos7.Client + handler *gos7.TCPClientHandler lock sync.Mutex SiemensDataPoints map[string]*SiemensDataPoint } @@ -122,21 +123,21 @@ func (s1200 *SIEMENS_PLC) Start(cctx typex.CCTX) error { s1200.Ctx = cctx.Ctx s1200.CancelCTX = cctx.CancelCTX // - handler := gos7.NewTCPClientHandler( + s1200.handler = gos7.NewTCPClientHandler( s1200.mainConfig.CommonConfig.Host, // 127.0.0.1:1500 *s1200.mainConfig.CommonConfig.Rack, // 0 *s1200.mainConfig.CommonConfig.Slot) // 1 - handler.Timeout = time.Duration( + s1200.handler.Timeout = time.Duration( *s1200.mainConfig.CommonConfig.Timeout) * time.Millisecond - handler.IdleTimeout = time.Duration( + s1200.handler.IdleTimeout = time.Duration( *s1200.mainConfig.CommonConfig.IdleTimeout) * time.Millisecond - if err := handler.Connect(); err != nil { + if err := s1200.handler.Connect(); err != nil { return err } else { s1200.status = typex.DEV_UP } - s1200.client = gos7.NewClient(handler) + s1200.client = gos7.NewClient(s1200.handler) if !*s1200.mainConfig.CommonConfig.AutoRequest { s1200.status = typex.DEV_UP return nil @@ -213,6 +214,9 @@ func (s1200 *SIEMENS_PLC) Stop() { if s1200.CancelCTX != nil { s1200.CancelCTX() } + if s1200.handler != nil { + s1200.handler.Close() + } siemenscache.UnRegisterSlot(s1200.PointId) } diff --git a/typex/version.go b/typex/version.go index 75212c13e..1f33f6b29 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-19 13:36:12", + ReleaseTime: "2023-12-19 18:39:58", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-9478c389bf9eda5 +** Version: v0.6.4-c088a66f466d66c ** Document: https://hootrhino.github.io ` From 929b604aa62b118f4e82d6d26df78ac2bcf0b41c Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 19 Dec 2023 21:55:29 +0800 Subject: [PATCH 125/138] dev: enhance binary operate --- rulexlib/binary_lib.go | 44 ++++++++++++++++--- rulexlib/hex_lib.go | 61 +++++++++++++++++++++++--- rulexlib/rhinoh3_audio_lib.go | 2 +- test/Bin2F32Little_test.go | 33 ++++++++++++++ test/apps/hex_and_uint_covert_demo.lua | 31 +++++++++++++ test/lua/_exit.lua | 2 - test/lua/data_tag.lua | 4 +- typex/version.go | 4 +- 8 files changed, 162 insertions(+), 19 deletions(-) create mode 100644 test/Bin2F32Little_test.go create mode 100644 test/apps/hex_and_uint_covert_demo.lua delete mode 100644 test/lua/_exit.lua diff --git a/rulexlib/binary_lib.go b/rulexlib/binary_lib.go index 39116b328..804aa1505 100644 --- a/rulexlib/binary_lib.go +++ b/rulexlib/binary_lib.go @@ -231,7 +231,7 @@ func bitStringToBytes(s string) ([]byte, error) { for i := 0; i < len(s); i++ { c := s[i] if c < '0' || c > '1' { - return nil, errors.New("bitstring to bytes error, bit value out of range, only can be 0 or 1") + return nil, errors.New("bit string to bytes error, bit value out of range, only can be 0 or 1") } b[i>>3] |= (c - '0') << uint(7-i&7) } @@ -520,10 +520,20 @@ func BinToFloat32(rx typex.RuleX) func(*lua.LState) int { l.Push(lua.LNil) return 1 } - l.Push(lua.LNumber(math.Float32frombits(binary.BigEndian.Uint32(dBytes)))) + if len(dBytes) == 4 { + l.Push(lua.LNumber(math.Float32frombits(binary.BigEndian.Uint32(dBytes)))) + } else { + l.Push(lua.LNumber(0)) + } return 1 } } + +/* +* +* 二进制转浮点数 +* + */ func BinToFloat64(rx typex.RuleX) func(*lua.LState) int { return func(l *lua.LState) int { bin := l.ToString(2) @@ -532,10 +542,20 @@ func BinToFloat64(rx typex.RuleX) func(*lua.LState) int { l.Push(lua.LNil) return 1 } - l.Push(lua.LNumber(math.Float64frombits(binary.BigEndian.Uint64(dBytes)))) + if len(dBytes) == 8 { + l.Push(lua.LNumber(math.Float64frombits(binary.BigEndian.Uint64(dBytes)))) + } else { + l.Push(lua.LNumber(0)) + } return 1 } } + +/* +* +* 二进制转浮点小端 +* + */ func BinToFloat32Little(rx typex.RuleX) func(*lua.LState) int { return func(l *lua.LState) int { bin := l.ToString(2) @@ -544,10 +564,20 @@ func BinToFloat32Little(rx typex.RuleX) func(*lua.LState) int { l.Push(lua.LNil) return 1 } - l.Push(lua.LNumber(math.Float32frombits(binary.LittleEndian.Uint32(dBytes)))) + if len(dBytes) == 4 { + l.Push(lua.LNumber(math.Float32frombits(binary.LittleEndian.Uint32(dBytes)))) + } else { + l.Push(lua.LNumber(0)) + } return 1 } } + +/* +* +* 二进制转8字节浮点小端 +* + */ func BinToFloat64Little(rx typex.RuleX) func(*lua.LState) int { return func(l *lua.LState) int { bin := l.ToString(2) @@ -556,7 +586,11 @@ func BinToFloat64Little(rx typex.RuleX) func(*lua.LState) int { l.Push(lua.LNil) return 1 } - l.Push(lua.LNumber(math.Float64frombits(binary.LittleEndian.Uint64(dBytes)))) + if len(dBytes) == 8 { + l.Push(lua.LNumber(math.Float64frombits(binary.LittleEndian.Uint64(dBytes)))) + } else { + l.Push(lua.LNumber(0)) + } return 1 } } diff --git a/rulexlib/hex_lib.go b/rulexlib/hex_lib.go index 672ed5606..00343facb 100644 --- a/rulexlib/hex_lib.go +++ b/rulexlib/hex_lib.go @@ -83,25 +83,37 @@ func MatchUInt(rx typex.RuleX) func(*lua.LState) int { ntb := lua.LTable{} for _, v := range mhs { size := len(v.Value) - - if size == 2 { + // 空 + if size == 0 { + ntb.RawSetString(v.Name, lua.LNumber(0)) + } + // 单字节 + if size == 1 { + ntb.RawSetString(v.Name, lua.LNumber(v.ToUint8())) + } + // 长度是 2 3 字节全看成2字节 + if size == 2 || size == 3 { ntb.RawSetString(v.Name, lua.LNumber(v.ToUint16())) } - if size == 4 { + // 长度是 4 5 6 7 字节全看成4字节 + if size == 4 || size == 5 || size == 6 || size == 7 { ntb.RawSetString(v.Name, lua.LNumber(v.ToUint32())) } - if size == 8 { + // 不支持超过8位的 + if size >= 8 { ntb.RawSetString(v.Name, lua.LNumber(v.ToUInt64())) } - if size > 8 { - ntb.RawSetString(v.Name, lua.LNumber(-0xFFFFFFFF)) - } } l.Push(&ntb) return 1 } } +/* +* +* 十六进制字节表示字符串 +* + */ type HexSegment struct { Name string Value []byte @@ -111,14 +123,35 @@ func (sgm HexSegment) ToHexString() string { return fmt.Sprintf("%X", sgm.Value) } +func (sgm HexSegment) ToUint8() uint8 { + return uint8(sgm.Value[0]) +} + +/* +* +* 大端表示法 +* + */ func (sgm HexSegment) ToUint16() uint16 { value := binary.BigEndian.Uint16(sgm.Value) return value } + +/* +* +* 大端表示法 +* + */ func (sgm HexSegment) ToUint32() uint32 { value := binary.BigEndian.Uint32(sgm.Value) return value } + +/* +* +* 大端表示法 +* + */ func (sgm HexSegment) ToUInt64() uint64 { value := binary.BigEndian.Uint64(sgm.Value) return value @@ -177,3 +210,17 @@ func extHex(hexStr string, start, end int) string { } return hexStr[start*2 : (end+1)*2] } + +// func extHex(hexStr string, start, end int) string { +// // 检查输入边界的有效性 +// if start < 0 || end < 0 || start > end || end*2 >= len(hexStr) { +// return "" +// } + +// // 计算起始和结束索引 +// startIdx := start * 2 +// endIdx := (end + 1) * 2 + +// // 切片并返回结果 +// return hexStr[startIdx:endIdx] +// } diff --git a/rulexlib/rhinoh3_audio_lib.go b/rulexlib/rhinoh3_audio_lib.go index e1ce755d0..f7df76199 100644 --- a/rulexlib/rhinoh3_audio_lib.go +++ b/rulexlib/rhinoh3_audio_lib.go @@ -33,7 +33,7 @@ var __mkv_playing bool = false func __MPVPlay(filePath string, duration time.Duration) error { if __mkv_playing { - return fmt.Errorf("Audio output device busying now") + return fmt.Errorf("audio output device busying now") } __mkv_playing = true cmd := exec.Command("mpv", filePath) diff --git a/test/Bin2F32Little_test.go b/test/Bin2F32Little_test.go new file mode 100644 index 000000000..aae98d865 --- /dev/null +++ b/test/Bin2F32Little_test.go @@ -0,0 +1,33 @@ +// Copyright (C) 2023 wwhai +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package test + +import ( + "encoding/binary" + "encoding/hex" + "math" + "testing" +) + +// go test -timeout 30s -run ^Test_Binary_to_Float github.com/hootrhino/rulex/test -v -count=1 +func Test_Binary_to_Float(t *testing.T) { + // Hex 40 49 0E 56 = D3.141 + dBytes, _ := hex.DecodeString("40490E56") + V1 := math.Float32frombits(binary.LittleEndian.Uint32(dBytes)) + t.Log(V1) + V2 := math.Float32frombits(binary.BigEndian.Uint32(dBytes)) + t.Log(V2) +} diff --git a/test/apps/hex_and_uint_covert_demo.lua b/test/apps/hex_and_uint_covert_demo.lua new file mode 100644 index 000000000..fd4405580 --- /dev/null +++ b/test/apps/hex_and_uint_covert_demo.lua @@ -0,0 +1,31 @@ +-- Copyright (C) 2023 wwhai +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU Affero 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 Affero General Public License for more details. +-- +-- You should have received a copy of the GNU Affero General Public License +-- along with this program. If not, see . + + +function Main(arg) + -- MatchHexS 是一个Map结构,K为表达式的name,Value为十六进制字符串, + -- binary:MatchUInt:表示提取值转换成4字节无符号数,也就是原始字节。 + -- "hum:[0,1];temp:[2,3]": 表示提取第 0 1 个字节,赋值给hum;提取第 2 3个字节赋值给humi + local MatchHexS = hex:MatchUInt("hum:[0,1];temp:[2,3]", "000102030405060708") + -- 大端输出温度 + stdlib:Debug("Bin2F32Big hum: " .. binary:Bin2F32Big(MatchHexS['hum'])) + -- 大端输出湿度 + stdlib:Debug("Bin2F32Big temp: " .. binary:Bin2F32Big(MatchHexS['temp'])) + -- 小端输出温度 + stdlib:Debug("Bin2F32Little hum: " .. binary:Bin2F32Little(MatchHexS['hum'])) + -- 小端输出湿度 + stdlib:Debug("Bin2F32Little temp: " .. binary:Bin2F32Little(MatchHexS['temp'])) + return 0 +end diff --git a/test/lua/_exit.lua b/test/lua/_exit.lua deleted file mode 100644 index 19a0eac8f..000000000 --- a/test/lua/_exit.lua +++ /dev/null @@ -1,2 +0,0 @@ -function _exit() end -_exit() \ No newline at end of file diff --git a/test/lua/data_tag.lua b/test/lua/data_tag.lua index 8b96e5f4e..d7cfe049c 100644 --- a/test/lua/data_tag.lua +++ b/test/lua/data_tag.lua @@ -3,9 +3,9 @@ -- {"tag":"add2", "id": "002", "value": 0x0002}, -- ] -function ParseData(data) +function ParseData(args) -- data: {"in":"AA0011...","out":"AABBCDD..."} - local DataT, err = rulexlib:J2T(data) + local DataT, err = rulexlib:J2T(args) if err ~= nil then return true, args end diff --git a/typex/version.go b/typex/version.go index 1f33f6b29..020474d81 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-19 18:39:58", + ReleaseTime: "2023-12-19 20:07:08", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-c088a66f466d66c +** Version: v0.6.4-262636351d2bae7 ** Document: https://hootrhino.github.io ` From 2df6a043ee55baa1c1d08d7ac143164da3b8a0b5 Mon Sep 17 00:00:00 2001 From: wwhai Date: Tue, 19 Dec 2023 23:40:56 +0800 Subject: [PATCH 126/138] dev: enhance XStore Fuzzy Get --- component/internotify/internotify.go | 4 ++++ component/rulex_api_server/apis/user_api.go | 15 --------------- core/internal_kvstore.go | 16 ++++++++++++++-- engine/load_device.go | 5 +++++ typex/version.go | 4 ++-- typex/xstore.go | 2 +- 6 files changed, 26 insertions(+), 20 deletions(-) diff --git a/component/internotify/internotify.go b/component/internotify/internotify.go index 46b2284c9..7719aaab1 100644 --- a/component/internotify/internotify.go +++ b/component/internotify/internotify.go @@ -121,7 +121,11 @@ func StartInternalEventQueue() { return case Event := <-InternalEventBus.Queue: { + // + // TODO 内部事件应该写入数据库, 主要是起通知作用 + // glogger.GLogger.Debug("Internal Event:", Event) + } } } diff --git a/component/rulex_api_server/apis/user_api.go b/component/rulex_api_server/apis/user_api.go index 94e2de056..109410229 100644 --- a/component/rulex_api_server/apis/user_api.go +++ b/component/rulex_api_server/apis/user_api.go @@ -152,21 +152,6 @@ func Login(c *gin.Context, ruleEngine typex.RuleX) { } } -/* -* -* 日志管理 -* - */ -func Logs(c *gin.Context, ruleEngine typex.RuleX) { - type Data struct { - Id int `json:"id" binding:"required"` - Content string `json:"content" binding:"required"` - } - //TODO 日志暂时不记录 - logs := []Data{} - c.JSON(common.HTTP_OK, common.OkWithData(logs)) -} - func LogOut(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Ok()) } diff --git a/core/internal_kvstore.go b/core/internal_kvstore.go index b45fbddab..83fc58f39 100644 --- a/core/internal_kvstore.go +++ b/core/internal_kvstore.go @@ -16,6 +16,7 @@ package core import ( + "strings" "time" "github.com/hootrhino/rulex/glogger" @@ -82,7 +83,18 @@ func (rs *RulexStore) Count() int { // 模糊查询匹配 // 支持: *AAA AAA* A*B -func (rs *RulexStore) FuzzyGet(k string) string { - // TODO 未来实现 +func (rs *RulexStore) FuzzyGet(Key string) any { + for k, v := range rs.cache.Items() { + if fuzzyMatch(k, Key) { + return v + } + } return "" } + +// 将主字符串和子字符串都转换为小写,以进行不区分大小写的匹配 +func fuzzyMatch(mainStr, subStr string) bool { + mainStr = strings.ToLower(mainStr) + subStr = strings.ToLower(subStr) + return strings.Contains(mainStr, subStr) +} diff --git a/engine/load_device.go b/engine/load_device.go index caea9cbc2..31e478a9c 100644 --- a/engine/load_device.go +++ b/engine/load_device.go @@ -107,6 +107,11 @@ func (e *RuleEngine) loadDevices(abstractDevice typex.XDevice, deviceInfo *typex return nil } +/* +* +* Start是异步进行的,当设备的GetStatus返回状态UP时,正常运行,当Down时重启 +* + */ func startDevice(abstractDevice typex.XDevice, e *RuleEngine, ctx context.Context, cancelCTX context.CancelFunc) error { if err := abstractDevice.Start(typex.CCTX{Ctx: ctx, CancelCTX: cancelCTX}); err != nil { diff --git a/typex/version.go b/typex/version.go index 020474d81..5a8485ca0 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-19 20:07:08", + ReleaseTime: "2023-12-19 23:34:20", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-262636351d2bae7 +** Version: v0.6.4-929b604aa62b118 ** Document: https://hootrhino.github.io ` diff --git a/typex/xstore.go b/typex/xstore.go index 64aeaa990..0c8b72b66 100644 --- a/typex/xstore.go +++ b/typex/xstore.go @@ -16,5 +16,5 @@ type XStore interface { Count() int // 模糊查询匹配 // 支持: *AAA AAA* A*B - FuzzyGet(k string) string + FuzzyGet(k string) any } From 4d6a3c7179f833065619aa991483a129c55bbd45 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 20 Dec 2023 23:32:22 +0800 Subject: [PATCH 127/138] fix: fix state error --- component/rulex_api_server/apis/appstack_api.go | 16 ++++++++-------- glogger/ws_logger.go | 9 +++++++++ typex/version.go | 4 ++-- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/component/rulex_api_server/apis/appstack_api.go b/component/rulex_api_server/apis/appstack_api.go index b52029642..efae50233 100644 --- a/component/rulex_api_server/apis/appstack_api.go +++ b/component/rulex_api_server/apis/appstack_api.go @@ -20,14 +20,14 @@ import ( * */ type appStackDto struct { - UUID string `json:"uuid,omitempty"` // 名称 - Name string `json:"name,omitempty"` // 名称 - Version string `json:"version,omitempty"` // 版本号 - AutoStart *bool `json:"autoStart,omitempty"` // 自动启动 - AppState int `json:"appState,omitempty"` // 状态: 1 运行中, 0 停止 - Type string `json:"type,omitempty"` // 默认就是lua, 留个扩展以后可能支持别的 - LuaSource string `json:"luaSource,omitempty"` - Description string `json:"description,omitempty"` + UUID string `json:"uuid,omitempty"` // 名称 + Name string `json:"name"` // 名称 + Version string `json:"version"` // 版本号 + AutoStart *bool `json:"autoStart"` // 自动启动 + AppState int `json:"appState"` // 状态: 1 运行中, 0 停止 + Type string `json:"type"` // 默认就是lua, 留个扩展以后可能支持别的 + LuaSource string `json:"luaSource"` // Lua源码 + Description string `json:"description"` } /* diff --git a/glogger/ws_logger.go b/glogger/ws_logger.go index 9ba675122..c4d763c19 100644 --- a/glogger/ws_logger.go +++ b/glogger/ws_logger.go @@ -117,18 +117,24 @@ func WsLogger(c *gin.Context) { wsConn.SetReadDeadline(time.Time{}) token := string(b) if token != "WsTerminal" { + private_GRealtimeLogger.lock.Lock() wsConn.WriteMessage(1, []byte("Invalid client token")) + private_GRealtimeLogger.lock.Unlock() wsConn.Close() return } // 最多允许连接10个客户端,实际情况下根本用不了那么多 if len(private_GRealtimeLogger.Clients) > 5 { + private_GRealtimeLogger.lock.Lock() wsConn.WriteMessage(websocket.CloseMessage, []byte{}) + private_GRealtimeLogger.lock.Unlock() wsConn.Close() return } private_GRealtimeLogger.Clients[wsConn.RemoteAddr().String()] = wsConn + private_GRealtimeLogger.lock.Lock() wsConn.WriteMessage(websocket.TextMessage, []byte("Connected")) + private_GRealtimeLogger.lock.Unlock() GLogger.Info("WebSocket Terminal connected:" + wsConn.RemoteAddr().String()) wsConn.SetCloseHandler(func(code int, text string) error { GLogger.Info("wsConn Auto Close:", wsConn.RemoteAddr().String()) @@ -166,7 +172,10 @@ func WsLogger(c *gin.Context) { if err != nil { break } + private_GRealtimeLogger.lock.Lock() err = wsConn.WriteMessage(websocket.PingMessage, []byte{}) + private_GRealtimeLogger.lock.Unlock() + if err != nil { break } diff --git a/typex/version.go b/typex/version.go index 5a8485ca0..f5edb7a91 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-19 23:34:20", + ReleaseTime: "2023-12-20 21:47:33", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-929b604aa62b118 +** Version: v0.6.4-2df6a043ee55baa ** Document: https://hootrhino.github.io ` From b15814744d1dba9f90142641614d096221a741dc Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 21 Dec 2023 16:01:05 +0800 Subject: [PATCH 128/138] dev: remove unused code --- component/rulex_api_server/apis/rule_api.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/component/rulex_api_server/apis/rule_api.go b/component/rulex_api_server/apis/rule_api.go index e44dfaebe..edc9bbe07 100644 --- a/component/rulex_api_server/apis/rule_api.go +++ b/component/rulex_api_server/apis/rule_api.go @@ -560,9 +560,6 @@ func TestOutEndCallback(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error(fmt.Sprintf("'OutEnd' not exists: %v", form.UUID))) return } - glogger.GLogger.WithFields(logrus.Fields{ - "topic": "rule/test/" + form.UUID, - }).Debug(form.TestData) err1 := interqueue.DefaultDataCacheQueue.PushOutQueue(outend, form.TestData) if err1 != nil { c.JSON(common.HTTP_OK, common.Error400(err1)) From d8d77ab575cab3a983ef78c046b4badff2b8e0c6 Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 21 Dec 2023 18:15:06 +0800 Subject: [PATCH 129/138] doc: add docs --- script/readme-daemon.md | 8 ++++++++ script/readme-openwrt.md | 8 ++++++++ typex/version.go | 4 ++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/script/readme-daemon.md b/script/readme-daemon.md index 56168a340..177e3a5d8 100644 --- a/script/readme-daemon.md +++ b/script/readme-daemon.md @@ -28,3 +28,11 @@ unzip rulex-arm32linux-$VERSION.zip -d rulex # 状态 ./rulex-daemon.sh status ``` + +## 守护进程 +```sh +# 打开crontab +sudo crontab -e +# 输入 +@reboot (export ARCHSUPPORT=EEKITH3 && /etc/init.d/rulex.service start > /var/log/rulex.log 2>&1) +``` \ No newline at end of file diff --git a/script/readme-openwrt.md b/script/readme-openwrt.md index 44fcac3c7..4059c561c 100644 --- a/script/readme-openwrt.md +++ b/script/readme-openwrt.md @@ -28,3 +28,11 @@ unzip rulex-arm32linux-$VERSION.zip -d rulex # 状态 ./rulex-openwrt.sh status ``` + +## 守护进程 +```sh +# 打开crontab +sudo crontab -e +# 输入 +@reboot (export ARCHSUPPORT=EEKITH3 && /etc/init.d/rulex.service start > /var/log/rulex.log 2>&1) +``` \ No newline at end of file diff --git a/typex/version.go b/typex/version.go index f5edb7a91..9306783cc 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-20 21:47:33", + ReleaseTime: "2023-12-21 14:56:01", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-2df6a043ee55baa +** Version: v0.6.4-4d6a3c7179f8330 ** Document: https://hootrhino.github.io ` From 40b0767b39d249cdfc653b24060ce612b1803edb Mon Sep 17 00:00:00 2001 From: wwhai Date: Thu, 21 Dec 2023 23:19:42 +0800 Subject: [PATCH 130/138] dev: remove history heavy bag --- common/modbus_config.go | 29 +--- device/decoder/h264decoder.go | 140 ------------------- device/generic_ais_txrx_device.go | 8 +- device/generic_http_device.go | 6 +- device/generic_snmp_device.go | 4 +- device/generic_snmp_device.md | 2 +- device/generic_uart_device.go | 6 +- device/generic_uart_device.md | 2 +- device/network_icmp_sender.go | 4 +- device/rtu485_ther_device.go | 184 ------------------------- device/rtu485_ther_device.md | 106 --------------- device/tss200_device.go | 186 ------------------------- device/tss200_device.md | 17 --- device/type_loader.go | 4 - device/usr_g776_4gdtu_device.go | 177 ------------------------ device/usr_g776_4gdtu_device.md | 61 --------- device/yk8_controller_device.go | 187 -------------------------- device/yk8_controller_device.md | 17 --- driver/rtu485_ther_driver.go | 129 ------------------ driver/trailer_driver.go | 125 ----------------- driver/tss200_v_0_2_driver.go | 130 ------------------ driver/usr_g776_4gdtu_driver.go | 81 ----------- driver/yk8_relay_controller_driver.go | 142 ------------------- engine/engine.go | 24 ---- typex/xdevice.go | 4 - 25 files changed, 24 insertions(+), 1751 deletions(-) delete mode 100644 device/decoder/h264decoder.go delete mode 100644 device/rtu485_ther_device.go delete mode 100644 device/rtu485_ther_device.md delete mode 100644 device/tss200_device.go delete mode 100644 device/tss200_device.md delete mode 100644 device/usr_g776_4gdtu_device.go delete mode 100644 device/usr_g776_4gdtu_device.md delete mode 100644 device/yk8_controller_device.go delete mode 100644 device/yk8_controller_device.md delete mode 100644 driver/rtu485_ther_driver.go delete mode 100644 driver/trailer_driver.go delete mode 100644 driver/tss200_v_0_2_driver.go delete mode 100644 driver/usr_g776_4gdtu_driver.go delete mode 100644 driver/yk8_relay_controller_driver.go diff --git a/common/modbus_config.go b/common/modbus_config.go index 49757a49a..b85dd016f 100644 --- a/common/modbus_config.go +++ b/common/modbus_config.go @@ -62,28 +62,11 @@ type RegisterW struct { Values []byte `json:"values"` // Value } -// Uart "/dev/ttyUSB0" -// BaudRate = 115200 -// DataBits = 8 -// Parity = "N" -// StopBits = 1 -// SlaveId = 1 -// Timeout = 5 * time.Second -// TODO: 在0.5以后删除这两个结构体 -type RTUConfig struct { - Uart string `json:"uart" validate:"required" title:"串口路径" info:"本地系统的串口路径"` - BaudRate int `json:"baudRate" validate:"required" title:"波特率" info:"串口通信波特率"` - DataBits int `json:"dataBits" validate:"required" title:"数据位" info:"串口通信数据位"` - Parity string `json:"parity" validate:"required" title:"奇偶校验" info:"奇偶校验"` - StopBits int `json:"stopBits" validate:"required" title:"停止位" info:"串口通信停止位"` -} type ModBusConfig struct { - Mode string `json:"mode" title:"工作模式" info:"UART/TCP"` - Timeout int `json:"timeout" validate:"required" title:"连接超时"` - // Weather allow AutoRequest? - AutoRequest bool `json:"autoRequest" validate:"required"` - // Request Frequency, default 5 second - Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` - Config interface{} `json:"config" validate:"required" title:"工作模式"` - Registers []RegisterRW `json:"registers" validate:"required" title:"寄存器配置"` + Mode string `json:"mode" title:"工作模式" info:"UART/TCP"` + Timeout *int `json:"timeout" validate:"required" title:"连接超时"` + AutoRequest *bool `json:"autoRequest" validate:"required"` + Frequency *int64 `json:"frequency" validate:"required" title:"采集频率"` + Config interface{} `json:"config" validate:"required" title:"工作模式"` + Registers []RegisterRW `json:"registers" validate:"required" title:"寄存器配置"` } diff --git a/device/decoder/h264decoder.go b/device/decoder/h264decoder.go deleted file mode 100644 index 35b6b6eba..000000000 --- a/device/decoder/h264decoder.go +++ /dev/null @@ -1,140 +0,0 @@ -package decoder - -// import ( -// "fmt" -// "image" -// "unsafe" -// ) - -// // #cgo pkg-config: libavcodec libavutil libswscale -// // #include -// // #include -// // #include -// import "C" - -// func FrameData(frame *C.AVFrame) **C.uint8_t { -// return (**C.uint8_t)(unsafe.Pointer(&frame.data[0])) -// } - -// func FrameLineSize(frame *C.AVFrame) *C.int { -// return (*C.int)(unsafe.Pointer(&frame.linesize[0])) -// } - -// // h264Decoder is a wrapper around ffmpeg's H264 decoder. -// type h264Decoder struct { -// codecCtx *C.AVCodecContext -// srcFrame *C.AVFrame -// swsCtx *C.struct_SwsContext -// dstFrame *C.AVFrame -// dstFramePtr []uint8 -// } - -// // newH264Decoder allocates a new h264Decoder. -// func NewH264Decoder() (*h264Decoder, error) { -// codec := C.avcodec_find_decoder(C.AV_CODEC_ID_H264) -// if codec == nil { -// return nil, fmt.Errorf("avcodec_find_decoder() failed") -// } - -// codecCtx := C.avcodec_alloc_context3(codec) -// if codecCtx == nil { -// return nil, fmt.Errorf("avcodec_alloc_context3() failed") -// } - -// res := C.avcodec_open2(codecCtx, codec, nil) -// if res < 0 { -// C.avcodec_close(codecCtx) -// return nil, fmt.Errorf("avcodec_open2() failed") -// } - -// srcFrame := C.av_frame_alloc() -// if srcFrame == nil { -// C.avcodec_close(codecCtx) -// return nil, fmt.Errorf("av_frame_alloc() failed") -// } - -// return &h264Decoder{ -// codecCtx: codecCtx, -// srcFrame: srcFrame, -// }, nil -// } - -// // close closes the decoder. -// func (d *h264Decoder) Close() { -// if d.dstFrame != nil { -// C.av_frame_free(&d.dstFrame) -// } - -// if d.swsCtx != nil { -// C.sws_freeContext(d.swsCtx) -// } - -// C.av_frame_free(&d.srcFrame) -// C.avcodec_close(d.codecCtx) -// } - -// func (d *h264Decoder) Decode(nalu []byte) (image.Image, error) { -// nalu = append([]uint8{0x00, 0x00, 0x00, 0x01}, []uint8(nalu)...) - -// // send frame to decoder -// var avPacket C.AVPacket -// avPacket.data = (*C.uint8_t)(C.CBytes(nalu)) -// defer C.free(unsafe.Pointer(avPacket.data)) -// avPacket.size = C.int(len(nalu)) -// res := C.avcodec_send_packet(d.codecCtx, &avPacket) -// if res < 0 { -// return nil, nil -// } - -// // receive frame if available -// res = C.avcodec_receive_frame(d.codecCtx, d.srcFrame) -// if res < 0 { -// return nil, nil -// } - -// // if frame size has changed, allocate needed objects -// if d.dstFrame == nil || d.dstFrame.width != d.srcFrame.width || d.dstFrame.height != d.srcFrame.height { -// if d.dstFrame != nil { -// C.av_frame_free(&d.dstFrame) -// } - -// if d.swsCtx != nil { -// C.sws_freeContext(d.swsCtx) -// } - -// d.dstFrame = C.av_frame_alloc() -// d.dstFrame.format = C.AV_PIX_FMT_RGBA -// d.dstFrame.width = d.srcFrame.width -// d.dstFrame.height = d.srcFrame.height -// d.dstFrame.color_range = C.AVCOL_RANGE_JPEG -// res = C.av_frame_get_buffer(d.dstFrame, 1) -// if res < 0 { -// return nil, fmt.Errorf("av_frame_get_buffer() err") -// } - -// d.swsCtx = C.sws_getContext(d.srcFrame.width, d.srcFrame.height, C.AV_PIX_FMT_YUV420P, -// d.dstFrame.width, d.dstFrame.height, (int32)(d.dstFrame.format), C.SWS_BILINEAR, nil, nil, nil) -// if d.swsCtx == nil { -// return nil, fmt.Errorf("sws_getContext() err") -// } - -// dstFrameSize := C.av_image_get_buffer_size((int32)(d.dstFrame.format), d.dstFrame.width, d.dstFrame.height, 1) -// d.dstFramePtr = (*[1 << 30]uint8)(unsafe.Pointer(d.dstFrame.data[0]))[:dstFrameSize:dstFrameSize] -// } - -// // convert frame from YUV420 to RGB -// res = C.sws_scale(d.swsCtx, frameData(d.srcFrame), frameLineSize(d.srcFrame), -// 0, d.srcFrame.height, frameData(d.dstFrame), frameLineSize(d.dstFrame)) -// if res < 0 { -// return nil, fmt.Errorf("sws_scale() err") -// } - -// // embed frame into an image.Image -// return &image.RGBA{ -// Pix: d.dstFramePtr, -// Stride: 4 * (int)(d.dstFrame.width), -// Rect: image.Rectangle{ -// Max: image.Point{(int)(d.dstFrame.width), (int)(d.dstFrame.height)}, -// }, -// }, nil -// } diff --git a/device/generic_ais_txrx_device.go b/device/generic_ais_txrx_device.go index 40e77407a..5849a2563 100644 --- a/device/generic_ais_txrx_device.go +++ b/device/generic_ais_txrx_device.go @@ -29,7 +29,7 @@ var __AisCodec = aislib.CodecNew(false, false, false) // -------------------------------------------------------------------------------------------------- type _AISCommonConfig struct { Mode string `json:"mode" title:"工作模式" info:"UART/TCP"` - ParseAis bool `json:"parseAis"` + ParseAis *bool `json:"parseAis"` GwSN string `json:"gwsn"` } type _AISDeviceMasterConfig struct { @@ -66,7 +66,7 @@ func NewAISDeviceMaster(e typex.RuleX) typex.XDevice { }, CommonConfig: _AISCommonConfig{ Mode: "TCP", - ParseAis: false, + ParseAis: new(bool), GwSN: "HR0001", }, } @@ -235,7 +235,7 @@ func (aism *AISDeviceMaster) Start(cctx typex.CCTX) error { } // 如果不需要解析,直接原文透传 - if !aism.mainConfig.CommonConfig.ParseAis { + if !*aism.mainConfig.CommonConfig.ParseAis { // { // "ais_receiver_device":"%s", // "gwsn":"%s" @@ -425,7 +425,7 @@ func (aism *AISDeviceMaster) handleIO(session *__AISDeviceSession) { return } // 如果不需要解析,直接原文透传 - if !aism.mainConfig.CommonConfig.ParseAis { + if !*aism.mainConfig.CommonConfig.ParseAis { // { // "ais_receiver_device":"%s", // "ais_data":"%s" diff --git a/device/generic_http_device.go b/device/generic_http_device.go index 8d669f6f4..7f7b925cd 100644 --- a/device/generic_http_device.go +++ b/device/generic_http_device.go @@ -39,7 +39,11 @@ func NewGenericHttpDevice(e typex.RuleX) typex.XDevice { hd := new(GenericHttpDevice) hd.locker = &sync.Mutex{} hd.client = *http.DefaultClient - hd.mainConfig = __HttpMainConfig{} + hd.mainConfig = __HttpMainConfig{ + CommonConfig: __HttpCommonConfig{ + AutoRequest: new(bool), + }, + } hd.RuleEngine = e return hd } diff --git a/device/generic_snmp_device.go b/device/generic_snmp_device.go index 5c2d647c7..7955a2e4a 100644 --- a/device/generic_snmp_device.go +++ b/device/generic_snmp_device.go @@ -14,7 +14,7 @@ import ( ) type _SNMPCommonConfig struct { - AutoRequest bool `json:"autoRequest" validate:"required"` + AutoRequest *bool `json:"autoRequest" validate:"required"` Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` } @@ -82,7 +82,7 @@ func (sd *genericSnmpDevice) Start(cctx typex.CCTX) error { //--------------------------------------------------------------------------------- // Start //--------------------------------------------------------------------------------- - if !sd.mainConfig.CommonConfig.AutoRequest { + if !*sd.mainConfig.CommonConfig.AutoRequest { sd.status = typex.DEV_UP return nil } diff --git a/device/generic_snmp_device.md b/device/generic_snmp_device.md index 5165f0989..d060ccfb2 100644 --- a/device/generic_snmp_device.md +++ b/device/generic_snmp_device.md @@ -14,7 +14,7 @@ SNMP协议支持各种版本,其中最常用的是SNMPv1、SNMPv2c和SNMPv3。 ```go type _SNMPCommonConfig struct { - AutoRequest bool `json:"autoRequest" validate:"required"` + AutoRequest *bool `json:"autoRequest" validate:"required"` Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` } type GenericSnmpConfig struct { diff --git a/device/generic_uart_device.go b/device/generic_uart_device.go index 225f374e5..b9f802b0d 100644 --- a/device/generic_uart_device.go +++ b/device/generic_uart_device.go @@ -17,8 +17,8 @@ import ( type _GUDCommonConfig struct { Tag string `json:"tag" validate:"required"` - Frequency int64 `json:"frequency"` - AutoRequest bool `json:"autoRequest" validate:"required"` + Frequency *int64 `json:"frequency"` + AutoRequest *bool `json:"autoRequest" validate:"required"` // 协议报文结束符号 Separator string `json:"separator"` } @@ -90,7 +90,7 @@ func (uart *genericUartDevice) Start(cctx typex.CCTX) error { return err } uart.driver = driver.NewRawUartDriver(uart.Ctx, uart.RuleEngine, uart.Details(), serialPort) - if !uart.mainConfig.CommonConfig.AutoRequest { + if !*uart.mainConfig.CommonConfig.AutoRequest { uart.status = typex.DEV_UP return nil } diff --git a/device/generic_uart_device.md b/device/generic_uart_device.md index 65a299f30..3c78311f5 100644 --- a/device/generic_uart_device.md +++ b/device/generic_uart_device.md @@ -9,7 +9,7 @@ type GenericUartConfig struct { // 结束符, 默认是 '\n';但是可以自己定义 Decollator string `json:"decollator" title:"协议分隔符"` // Weather allow AutoRequest? - AutoRequest bool `json:"autoRequest" validate:"required"` + AutoRequest *bool `json:"autoRequest" validate:"required"` // Request Frequency, default 5 second Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` Timeout int `json:"timeout" validate:"required" title:"连接超时"` diff --git a/device/network_icmp_sender.go b/device/network_icmp_sender.go index bbbea2e86..fbd88f625 100644 --- a/device/network_icmp_sender.go +++ b/device/network_icmp_sender.go @@ -16,7 +16,7 @@ import ( type _IcmpSenderCommonConfig struct { Timeout int `json:"timeout" validate:"required"` // // Weather allow AutoRequest? - AutoRequest bool `json:"autoRequest" validate:"required"` + AutoRequest *bool `json:"autoRequest" validate:"required"` // // Request Frequency, default 5 second Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` } @@ -55,7 +55,7 @@ func (sender *IcmpSender) Init(devId string, configMap map[string]interface{}) e return errors.New("invalid ip:" + ip) } } - if !sender.mainConfig.CommonConfig.AutoRequest { + if !*sender.mainConfig.CommonConfig.AutoRequest { sender.status = typex.DEV_UP return nil } diff --git a/device/rtu485_ther_device.go b/device/rtu485_ther_device.go deleted file mode 100644 index 062d91fae..000000000 --- a/device/rtu485_ther_device.go +++ /dev/null @@ -1,184 +0,0 @@ -package device - -import ( - "context" - "errors" - golog "log" - "sync" - "time" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/core" - "github.com/hootrhino/rulex/driver" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" - "github.com/mitchellh/mapstructure" - modbus "github.com/wwhai/gomodbus" -) - -type rtu485_ther struct { - typex.XStatus - status typex.DeviceState - RuleEngine typex.RuleX - driver typex.XExternalDriver - rtuHandler *modbus.RTUClientHandler - mainConfig common.ModBusConfig - rtuConfig common.RTUConfig - locker sync.Locker -} - -// Example: 0x02 0x92 0xFF 0x98 -/* -* -* 温湿度传感器 -* - */ -func NewRtu485Ther(e typex.RuleX) typex.XDevice { - ther := new(rtu485_ther) - ther.RuleEngine = e - ther.locker = &sync.Mutex{} - ther.mainConfig = common.ModBusConfig{} - ther.rtuConfig = common.RTUConfig{} - return ther -} - -//  初始化 -func (ther *rtu485_ther) Init(devId string, configMap map[string]interface{}) error { - ther.PointId = devId - if err := utils.BindSourceConfig(configMap, &ther.mainConfig); err != nil { - return err - } - if errs := mapstructure.Decode(ther.mainConfig.Config, &ther.rtuConfig); errs != nil { - glogger.GLogger.Error(errs) - return errs - } - // 检查Tag有没有重复 - tags := []string{} - for _, register := range ther.mainConfig.Registers { - tags = append(tags, register.Tag) - } - - if utils.IsListDuplicated(tags) { - return errors.New("tag duplicated") - } - return nil -} - -// 启动 -func (ther *rtu485_ther) Start(cctx typex.CCTX) error { - ther.Ctx = cctx.Ctx - ther.CancelCTX = cctx.CancelCTX - // - // 串口配置固定写法 - ther.rtuHandler = modbus.NewRTUClientHandler(ther.rtuConfig.Uart) - ther.rtuHandler.BaudRate = ther.rtuConfig.BaudRate - ther.rtuHandler.DataBits = ther.rtuConfig.DataBits - ther.rtuHandler.Parity = ther.rtuConfig.Parity - ther.rtuHandler.StopBits = ther.rtuConfig.StopBits - ther.rtuHandler.Timeout = time.Duration(ther.mainConfig.Timeout) * time.Second - if core.GlobalConfig.AppDebugMode { - ther.rtuHandler.Logger = golog.New(glogger.GLogger.Writer(), "485-TEMP-HUMI-DEVICE: ", golog.LstdFlags) - } - if err := ther.rtuHandler.Connect(); err != nil { - return err - } - client := modbus.NewClient(ther.rtuHandler) - ther.driver = driver.NewRtu485THerDriver(ther.Details(), - ther.RuleEngine, ther.mainConfig.Registers, ther.rtuHandler, client) - //--------------------------------------------------------------------------------- - // Start - //--------------------------------------------------------------------------------- - if !ther.mainConfig.AutoRequest { - ther.status = typex.DEV_UP - return nil - } - go func(ctx context.Context, Driver typex.XExternalDriver) { - ticker := time.NewTicker(time.Duration(ther.mainConfig.Frequency) * time.Millisecond) - buffer := make([]byte, common.T_64KB) - ther.driver.Read([]byte{}, buffer) //清理缓存 - for { - <-ticker.C - select { - case <-ctx.Done(): - { - ticker.Stop() - if ther.rtuHandler != nil { - ther.rtuHandler.Close() - } - return - } - default: - { - } - } - ther.locker.Lock() - n, err := Driver.Read([]byte{}, buffer) - ther.locker.Unlock() - if err != nil { - glogger.GLogger.Error(err) - } else { - ther.RuleEngine.WorkDevice(ther.Details(), string(buffer[:n])) - } - } - - }(ther.Ctx, ther.driver) - ther.status = typex.DEV_UP - return nil -} - -// 从设备里面读数据出来 -func (ther *rtu485_ther) OnRead(cmd []byte, data []byte) (int, error) { - - n, err := ther.driver.Read(cmd, data) - if err != nil { - glogger.GLogger.Error(err) - ther.status = typex.DEV_DOWN - } - return n, err -} - -// 把数据写入设备 -func (ther *rtu485_ther) OnWrite(cmd []byte, _ []byte) (int, error) { - return 0, nil -} - -// 设备当前状态 -func (ther *rtu485_ther) Status() typex.DeviceState { - return ther.status -} - -// 停止设备 -func (ther *rtu485_ther) Stop() { - ther.status = typex.DEV_DOWN - ther.CancelCTX() - -} - -// 设备属性,是一系列属性描述 -func (ther *rtu485_ther) Property() []typex.DeviceProperty { - return []typex.DeviceProperty{} -} - -// 真实设备 -func (ther *rtu485_ther) Details() *typex.Device { - return ther.RuleEngine.GetDevice(ther.PointId) -} - -// 状态 -func (ther *rtu485_ther) SetState(status typex.DeviceState) { - ther.status = status - -} - -// 驱动 -func (ther *rtu485_ther) Driver() typex.XExternalDriver { - return ther.driver -} - -func (ther *rtu485_ther) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { - return typex.DCAResult{} -} -func (ther *rtu485_ther) OnCtrl(cmd []byte, args []byte) ([]byte, error) { - return []byte{}, nil -} diff --git a/device/rtu485_ther_device.md b/device/rtu485_ther_device.md deleted file mode 100644 index 7ccfff5a8..000000000 --- a/device/rtu485_ther_device.md +++ /dev/null @@ -1,106 +0,0 @@ -# TSS200 -## 简介 - -TC-S200 系列空气质量监测仪内置 PM2.5、TVOC、甲醛、CO2,温湿度等高精度传感器套件,可通过吸顶式或壁挂安装,RS-485 接口通过 Modbus-RTU 协议进行数据输出,通过网关组网,或配合联动模块可以用于新风联动控制。 - -## 配置 - -```json -{ - "name": "RTU485_THER", - "type": "RTU485_THER", - "config": { - "mode": "UART", - "timeout": 10, - "frequency": 5, - "autoRequest": true, - "config": { - "uart": "/dev/ttyUSB0", - "dataBits": 8, - "parity": "N", - "stopBits": 1, - "baudRate": 9600, - "ip": "127.0.0.1", - "port": 502 - }, - "registers": [ - { - "tag": "node1", - "function": 3, - "slaverId": 1, - "address": 0, - "quantity": 2 - } - ] - }, - "description": "RTU485_THER" -} -``` - -## 数据 - -### 读 -#### 1. CMD -无指令。 -#### 1. Args -无参数。 - -#### 3. 数据样例 -```json -{ - float32 `json:"temp"` //系数: 0.01 - float32 `json:"hum"` //系数: 0.01 - uint16 `json:"pm1"` - uint16 `json:"pm25"` - uint16 `json:"pm10"` - uint16 `json:"co2"` - float32 `json:"tvoc"` //系数: 0.001 - float32 `json:"choh"` //系数: 0.001 - float32 `json:"eco2"` //系数: 0.001 -} -``` - -### 写 -#### 1. CMD -无指令。 - -#### 2. Args -无参数。 - -#### 3. 数据样例 -无写数据。 - -## 案例 - -```lua --- Success -function Success() - print("Success") -end --- Failed -function Failed(error) - print("Error:", error) -end - --- Actions -Actions = { - function(args) - local _, err = rulexlib:ReadDevice(device, 0, "all") - if (err ~= nil) then - return false, data - end - return true, args - end -} - -``` - -## 说明 - -- 暂无 - -## 社区 - -### 维护者 - -- wwhai diff --git a/device/tss200_device.go b/device/tss200_device.go deleted file mode 100644 index 76694e120..000000000 --- a/device/tss200_device.go +++ /dev/null @@ -1,186 +0,0 @@ -package device - -import ( - "context" - "errors" - golog "log" - "sync" - "time" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/core" - "github.com/hootrhino/rulex/driver" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" - "github.com/mitchellh/mapstructure" - modbus "github.com/wwhai/gomodbus" -) - -type tss200V2 struct { - typex.XStatus - status typex.DeviceState - RuleEngine typex.RuleX - driver typex.XExternalDriver - rtuHandler *modbus.RTUClientHandler - mainConfig common.ModBusConfig - rtuConfig common.RTUConfig - locker sync.Locker -} - -/* -* -* TSS200环境传感器 -* - */ -func NewTS200Sensor(e typex.RuleX) typex.XDevice { - tss := new(tss200V2) - tss.locker = &sync.Mutex{} - tss.mainConfig = common.ModBusConfig{} - tss.rtuConfig = common.RTUConfig{} - tss.RuleEngine = e - return tss -} - -//  初始化 -func (tss *tss200V2) Init(devId string, configMap map[string]interface{}) error { - tss.PointId = devId - if err := utils.BindSourceConfig(configMap, &tss.mainConfig); err != nil { - glogger.GLogger.Error(err) - return err - } - - if errs := mapstructure.Decode(tss.mainConfig.Config, &tss.rtuConfig); errs != nil { - glogger.GLogger.Error(errs) - return errs - } - // 检查Tag有没有重复 - tags := []string{} - for _, register := range tss.mainConfig.Registers { - tags = append(tags, register.Tag) - } - if utils.IsListDuplicated(tags) { - return errors.New("tag duplicated") - } - return nil -} - -// 启动 -func (tss *tss200V2) Start(cctx typex.CCTX) error { - tss.Ctx = cctx.Ctx - tss.CancelCTX = cctx.CancelCTX - - // 串口配置固定写法 - // 下面的参数是传感器固定写法 - tss.rtuHandler = modbus.NewRTUClientHandler(tss.rtuConfig.Uart) - tss.rtuHandler.BaudRate = tss.rtuConfig.BaudRate - tss.rtuHandler.DataBits = tss.rtuConfig.DataBits - tss.rtuHandler.Parity = tss.rtuConfig.Parity - tss.rtuHandler.StopBits = tss.rtuConfig.StopBits - tss.rtuHandler.Timeout = time.Duration(tss.mainConfig.Timeout) * time.Second - if core.GlobalConfig.AppDebugMode { - tss.rtuHandler.Logger = golog.New(glogger.GLogger.Writer(), "TSS200-DEVICE: ", golog.LstdFlags) - } - - if err := tss.rtuHandler.Connect(); err != nil { - return err - } - //--------------------------------------------------------------------------------- - // Start - //--------------------------------------------------------------------------------- - client := modbus.NewClient(tss.rtuHandler) - tss.driver = driver.NewTSS200Driver(tss.Details(), - tss.RuleEngine, tss.mainConfig.Registers, tss.rtuHandler, client) - if !tss.mainConfig.AutoRequest { - tss.status = typex.DEV_UP - return nil - } - go func(ctx context.Context, Driver typex.XExternalDriver) { - ticker := time.NewTicker(time.Duration(tss.mainConfig.Frequency) * time.Millisecond) - defer ticker.Stop() - buffer := make([]byte, common.T_64KB) - tss.driver.Read([]byte{}, buffer) //清理缓存 - for { - <-ticker.C - select { - case <-ctx.Done(): - { - ticker.Stop() - if tss.rtuHandler != nil { - tss.rtuHandler.Close() - } - return - } - default: - { - } - } - tss.locker.Lock() - n, err := Driver.Read([]byte{}, buffer) - tss.locker.Unlock() - if err != nil { - glogger.GLogger.Error(err) - } else { - tss.RuleEngine.WorkDevice(tss.Details(), string(buffer[:n])) - } - } - - }(tss.Ctx, tss.driver) - tss.status = typex.DEV_UP - return nil -} - -// 从设备里面读数据出来 -func (tss *tss200V2) OnRead(cmd []byte, data []byte) (int, error) { - - n, err := tss.driver.Read(cmd, data) - if err != nil { - glogger.GLogger.Error(err) - tss.status = typex.DEV_DOWN - } - return n, err -} - -// 把数据写入设备 -func (tss *tss200V2) OnWrite(cmd []byte, b []byte) (int, error) { - return tss.driver.Write(cmd, b) -} - -// 设备当前状态 -func (tss *tss200V2) Status() typex.DeviceState { - return typex.DEV_UP -} - -// 停止设备 -func (tss *tss200V2) Stop() { - tss.status = typex.DEV_DOWN - tss.CancelCTX() -} - -// 设备属性,是一系列属性描述 -func (tss *tss200V2) Property() []typex.DeviceProperty { - return []typex.DeviceProperty{} -} - -// 真实设备 -func (tss *tss200V2) Details() *typex.Device { - return tss.RuleEngine.GetDevice(tss.PointId) -} - -// 状态 -func (tss *tss200V2) SetState(status typex.DeviceState) { - tss.status = status - -} - -// 驱动 -func (tss *tss200V2) Driver() typex.XExternalDriver { - return tss.driver -} - -func (tss *tss200V2) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { - return typex.DCAResult{} -} -func (tss *tss200V2) OnCtrl(cmd []byte, args []byte) ([]byte, error) { - return []byte{}, nil -} diff --git a/device/tss200_device.md b/device/tss200_device.md deleted file mode 100644 index 65f4e272d..000000000 --- a/device/tss200_device.md +++ /dev/null @@ -1,17 +0,0 @@ - - diff --git a/device/type_loader.go b/device/type_loader.go index fb8edcf61..622d9da0d 100644 --- a/device/type_loader.go +++ b/device/type_loader.go @@ -14,14 +14,10 @@ var DM typex.DeviceRegistry */ func LoadDt() { DM = core.NewDeviceTypeManager() - DM.Register(typex.TSS200V02, &typex.XConfig{}) - DM.Register(typex.RTU485_THER, &typex.XConfig{}) - DM.Register(typex.YK08_RELAY, &typex.XConfig{}) DM.Register(typex.SIEMENS_PLC, &typex.XConfig{}) DM.Register(typex.GENERIC_MODBUS, &typex.XConfig{}) DM.Register(typex.GENERIC_MODBUS_POINT_EXCEL, &typex.XConfig{}) DM.Register(typex.GENERIC_UART, &typex.XConfig{}) DM.Register(typex.GENERIC_SNMP, &typex.XConfig{}) - DM.Register(typex.USER_G776, &typex.XConfig{}) DM.Register(typex.ICMP_SENDER, &typex.XConfig{}) } diff --git a/device/usr_g776_4gdtu_device.go b/device/usr_g776_4gdtu_device.go deleted file mode 100644 index 80d61c2f0..000000000 --- a/device/usr_g776_4gdtu_device.go +++ /dev/null @@ -1,177 +0,0 @@ -package device - -import ( - "errors" - "fmt" - "sync" - "time" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" - serial "github.com/wwhai/goserial" -) - -/* -* -* 有人G776串口4G模块 -* - */ -type _G776CommonConfig struct { - Tag string `json:"tag" validate:"required" title:"数据Tag" info:"给数据打标签"` - Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` - AutoRequest bool `json:"autoRequest" validate:"required"` -} - -type _G776Config struct { - CommonConfig _G776CommonConfig `json:"commonConfig" validate:"required"` - UartConfig common.CommonUartConfig `json:"uartConfig" validate:"required"` -} - -// 这是有人G776型号的4G DTU模块,主要用来TCP远程透传数据, 实际上就是个很普通的串口读写程序 -// 详细文档: https://www.usr.cn/Download/806.html -type UsrG776DTU struct { - typex.XStatus - status typex.DeviceState - RuleEngine typex.RuleX - mainConfig _G776Config - locker sync.Locker - serialPort serial.Port - errCount int -} - -/* -* -* 有人4G DTU -* - */ -func NewUsrG776DTU(e typex.RuleX) typex.XDevice { - uart := new(UsrG776DTU) - uart.locker = &sync.Mutex{} - uart.mainConfig = _G776Config{} - uart.RuleEngine = e - uart.serialPort = nil - return uart -} - -//  初始化 -func (uart *UsrG776DTU) Init(devId string, configMap map[string]interface{}) error { - uart.PointId = devId - if err := utils.BindSourceConfig(configMap, &uart.mainConfig); err != nil { - glogger.GLogger.Error(err) - return err - } - if !utils.SContains([]string{"N", "E", "O"}, uart.mainConfig.UartConfig.Parity) { - return errors.New("parity value only one of 'N','O','E'") - } - return nil -} - -// 启动 -func (uart *UsrG776DTU) Start(cctx typex.CCTX) error { - uart.Ctx = cctx.Ctx - uart.CancelCTX = cctx.CancelCTX - config := serial.Config{ - Address: uart.mainConfig.UartConfig.Uart, - BaudRate: uart.mainConfig.UartConfig.BaudRate, - DataBits: uart.mainConfig.UartConfig.DataBits, - Parity: uart.mainConfig.UartConfig.Parity, - StopBits: uart.mainConfig.UartConfig.StopBits, - Timeout: time.Duration(uart.mainConfig.UartConfig.Timeout) * time.Millisecond, - } - serialPort, err := serial.Open(&config) - if err != nil { - glogger.GLogger.Error("Serial.Open failed:", err) - return err - } - uart.errCount = 0 - uart.serialPort = serialPort - uart.status = typex.DEV_UP - return nil -} - -/* -* -* 不支持读, 仅仅是个数据透传DTU -* - */ -func (uart *UsrG776DTU) OnRead(cmd []byte, data []byte) (int, error) { - return 0, fmt.Errorf("UsrG776DTU not support read data") -} - -/* -* -* 有人G776-DTU写入串口的数据会被不加修改的透传到上层 -* data:ToUsrG776DTU("uuid", "DATA", "data-....") -* - */ -func (uart *UsrG776DTU) OnWrite(cmd []byte, b []byte) (int, error) { - if string(cmd) != ("DATA") { - return 0, nil - } - n, err := uart.serialPort.Write(b) - if err != nil { - uart.errCount++ - glogger.GLogger.Error(err) - if uart.errCount > 5 { - return n, err - } - } - return n, nil -} - -// 设备当前状态 -func (uart *UsrG776DTU) Status() typex.DeviceState { - if uart.serialPort != nil { - // https://www.usr.cn/Download/806.html - // 发送: AT\r - // 接收: \r\nOK\r\n\r\n - _, err := uart.serialPort.Write([]byte("AT\r")) - if err != nil { - uart.errCount++ - glogger.GLogger.Error(err) - if uart.errCount > 5 { - return typex.DEV_DOWN - } - } - } - return typex.DEV_UP -} - -// 停止设备 -func (uart *UsrG776DTU) Stop() { - uart.CancelCTX() - uart.status = typex.DEV_DOWN - if uart.serialPort != nil { - uart.serialPort.Close() - } -} - -// 设备属性,是一系列属性描述 -func (uart *UsrG776DTU) Property() []typex.DeviceProperty { - return []typex.DeviceProperty{} -} - -// 真实设备 -func (uart *UsrG776DTU) Details() *typex.Device { - return uart.RuleEngine.GetDevice(uart.PointId) -} - -// 状态 -func (uart *UsrG776DTU) SetState(status typex.DeviceState) { - uart.status = status - -} - -// 驱动 -func (uart *UsrG776DTU) Driver() typex.XExternalDriver { - return nil -} - -func (uart *UsrG776DTU) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { - return typex.DCAResult{} -} -func (uart *UsrG776DTU) OnCtrl(cmd []byte, args []byte) ([]byte, error) { - return []byte{}, nil -} diff --git a/device/usr_g776_4gdtu_device.md b/device/usr_g776_4gdtu_device.md deleted file mode 100644 index 4795028e0..000000000 --- a/device/usr_g776_4gdtu_device.md +++ /dev/null @@ -1,61 +0,0 @@ -## 简介 -USR-G776 是有人第二代 4G DTU 产品,支持移动,联通,电信 4G 和移动,联通3G和2G 网络制式,以“透 -传”作为功能核心,高度易用性,用户可方便快速的集成于自己的系统中。该 DTU 软件功能完善,覆盖绝大多 -数常规应用场景,用户只需通过简单的设置,即可实现串口到网络的双向数据透明传输。 - -RULEX对USR-G776做了一个非常简单的支持:直接向串口透传数据,因此在使用该设备之前最好是配置好。 - -官方文档:https://www.usr.cn/Download/806.html -## 配置 -```go -type _G776CommonConfig struct { - Tag string `json:"tag" validate:"required" title:"数据Tag" info:"给数据打标签"` - Frequency int64 `json:"frequency" validate:"required" title:"采集频率"` - AutoRequest bool `json:"autoRequest" validate:"required"` -} -type CommonUartConfig struct { - Timeout int `json:"timeout" validate:"required"` - Uart string `json:"uart" validate:"required"` - BaudRate int `json:"baudRate" validate:"required"` - DataBits int `json:"dataBits" validate:"required"` - Parity string `json:"parity" validate:"required"` - StopBits int `json:"stopBits" validate:"required"` -} -type _G776Config struct { - CommonConfig _G776CommonConfig `json:"commonConfig" validate:"required"` - UartConfig common.CommonUartConfig `json:"uartConfig" validate:"required"` -} - -``` - -## 数据处理示例 - -```lua --- Success -function Success() - -end - --- Failed -function Failed(error) - print("failed:", error) -end - --- Actions - -Actions = { - function(args) - local dataTable, err1 = rulexlib:J2T(data) - if err1 ~= nil then - return true, args - end - for _k, entity in pairs(dataTable) do - data:ToUsrG776DTU("uuid", "DATA" ,rulexlib:T2J(entity["value"])) - end - return true, args - end -} - -``` -### 注意事项 -第二个参数必须是“DATA”,第三个参数可以是字符串、十六进制等. \ No newline at end of file diff --git a/device/yk8_controller_device.go b/device/yk8_controller_device.go deleted file mode 100644 index af5f5a6d5..000000000 --- a/device/yk8_controller_device.go +++ /dev/null @@ -1,187 +0,0 @@ -package device - -import ( - "context" - "errors" - golog "log" - "sync" - "time" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/core" - "github.com/hootrhino/rulex/driver" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" - "github.com/mitchellh/mapstructure" - modbus "github.com/wwhai/gomodbus" -) - -type YK8Controller struct { - typex.XStatus - status typex.DeviceState - RuleEngine typex.RuleX - driver typex.XExternalDriver - rtuHandler *modbus.RTUClientHandler - mainConfig common.ModBusConfig - rtuConfig common.RTUConfig - locker sync.Locker -} - -/* -* -* 8路继电器 -* - */ -func NewYK8Controller(e typex.RuleX) typex.XDevice { - yk8 := new(YK8Controller) - yk8.locker = &sync.Mutex{} - yk8.mainConfig = common.ModBusConfig{} - yk8.rtuConfig = common.RTUConfig{} - yk8.RuleEngine = e - return yk8 -} - -//  初始化 -func (yk8 *YK8Controller) Init(devId string, configMap map[string]interface{}) error { - yk8.PointId = devId - if err := utils.BindSourceConfig(configMap, &yk8.mainConfig); err != nil { - glogger.GLogger.Error(err) - return err - } - - if errs := mapstructure.Decode(yk8.mainConfig.Config, &yk8.rtuConfig); errs != nil { - glogger.GLogger.Error(errs) - return errs - } - // 检查Tag有没有重复 - tags := []string{} - for _, register := range yk8.mainConfig.Registers { - tags = append(tags, register.Tag) - } - if utils.IsListDuplicated(tags) { - return errors.New("tag duplicated") - } - return nil -} - -// 启动 -func (yk8 *YK8Controller) Start(cctx typex.CCTX) error { - yk8.Ctx = cctx.Ctx - yk8.CancelCTX = cctx.CancelCTX - - // 串口配置固定写法 - // 下面的参数是传感器固定写法 - yk8.rtuHandler = modbus.NewRTUClientHandler(yk8.rtuConfig.Uart) - yk8.rtuHandler.BaudRate = yk8.rtuConfig.BaudRate - yk8.rtuHandler.DataBits = yk8.rtuConfig.DataBits - yk8.rtuHandler.Parity = yk8.rtuConfig.Parity - yk8.rtuHandler.StopBits = yk8.rtuConfig.StopBits - yk8.rtuHandler.Timeout = time.Duration(yk8.mainConfig.Timeout) * time.Second - if core.GlobalConfig.AppDebugMode { - yk8.rtuHandler.Logger = golog.New(glogger.GLogger.Writer(), "YK8-DEVICE: ", golog.LstdFlags) - } - - if err := yk8.rtuHandler.Connect(); err != nil { - return err - } - //--------------------------------------------------------------------------------- - // Start - //--------------------------------------------------------------------------------- - client := modbus.NewClient(yk8.rtuHandler) - yk8.driver = driver.NewYK8RelayControllerDriver(yk8.Details(), - yk8.RuleEngine, yk8.mainConfig.Registers, yk8.rtuHandler, client) - if !yk8.mainConfig.AutoRequest { - yk8.status = typex.DEV_UP - return nil - } - go func(ctx context.Context, Driver typex.XExternalDriver) { - ticker := time.NewTicker(time.Duration(yk8.mainConfig.Frequency) * time.Millisecond) - buffer := make([]byte, common.T_64KB) - yk8.driver.Read([]byte{}, buffer) //清理缓存 - for { - select { - case <-ctx.Done(): - { - ticker.Stop() - if yk8.rtuHandler != nil { - yk8.rtuHandler.Close() - } - return - } - default: - { - } - } - yk8.locker.Lock() - n, err := Driver.Read([]byte{}, buffer) - yk8.locker.Unlock() - if err != nil { - glogger.GLogger.Error(err) - } else { - yk8.RuleEngine.WorkDevice(yk8.Details(), string(buffer[:n])) - } - <-ticker.C - - } - - }(yk8.Ctx, yk8.driver) - yk8.status = typex.DEV_UP - return nil -} - -// 从设备里面读数据出来 -func (yk8 *YK8Controller) OnRead(cmd []byte, data []byte) (int, error) { - - n, err := yk8.driver.Read(cmd, data) - if err != nil { - glogger.GLogger.Error(err) - yk8.status = typex.DEV_DOWN - } - return n, err -} - -// 把数据写入设备 -func (yk8 *YK8Controller) OnWrite(cmd []byte, b []byte) (int, error) { - return yk8.driver.Write(cmd, b) -} - -// 设备当前状态 -func (yk8 *YK8Controller) Status() typex.DeviceState { - return typex.DEV_UP -} - -// 停止设备 -func (yk8 *YK8Controller) Stop() { - yk8.status = typex.DEV_DOWN - yk8.CancelCTX() - -} - -// 设备属性,是一系列属性描述 -func (yk8 *YK8Controller) Property() []typex.DeviceProperty { - return []typex.DeviceProperty{} -} - -// 真实设备 -func (yk8 *YK8Controller) Details() *typex.Device { - return yk8.RuleEngine.GetDevice(yk8.PointId) -} - -// 状态 -func (yk8 *YK8Controller) SetState(status typex.DeviceState) { - yk8.status = status - -} - -// 驱动 -func (yk8 *YK8Controller) Driver() typex.XExternalDriver { - return yk8.driver -} - -func (yk8 *YK8Controller) OnDCACall(UUID string, Command string, Args interface{}) typex.DCAResult { - return typex.DCAResult{} -} -func (yk8 *YK8Controller) OnCtrl(cmd []byte, args []byte) ([]byte, error) { - return []byte{}, nil -} diff --git a/device/yk8_controller_device.md b/device/yk8_controller_device.md deleted file mode 100644 index 65f4e272d..000000000 --- a/device/yk8_controller_device.md +++ /dev/null @@ -1,17 +0,0 @@ - - diff --git a/driver/rtu485_ther_driver.go b/driver/rtu485_ther_driver.go deleted file mode 100644 index 5b5deebd5..000000000 --- a/driver/rtu485_ther_driver.go +++ /dev/null @@ -1,129 +0,0 @@ -// 485 温湿度传感器驱动案例 -// 这是个很简单的485温湿度传感器驱动, 目的是为了演示厂商如何实现自己的设备底层驱动 -// 本驱动完成于2022年4月28日, 温湿度传感器资料请移步文档 -// 备注:THer 的含义是 ·temperature and humidity detector· 的简写 -package driver - -import ( - "encoding/json" - "sync" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" - modbus "github.com/wwhai/gomodbus" -) - -// Example: 0x02 0x92 0xFF 0x98 -type sensor_data struct { - Temperature float32 `json:"t"` //系数: 0.1 - Humidity float32 `json:"h"` //系数: 0.1 -} - -// 协议:UART:485 baud=4800 无校验 数据位1 停止位1 -// 功能码为: 3(ReadHoldingRegisters) -// 站号为:1 -// 寄存器:0000H保存湿度 0001H保存温度,数据一共两个寄存器,4个字节(uint16*2) -// --------------------- -// | 00H 00H | 00H 01H | -// --------------------- -// | 湿度 | 温度 | -// --------------------- -// ** 其中低位保存小数 -type rtu485_THer_Driver struct { - state typex.DriverState - handler *modbus.RTUClientHandler - client modbus.Client - RuleEngine typex.RuleX - Registers []common.RegisterRW - device *typex.Device - lock sync.Mutex -} - -func NewRtu485THerDriver(d *typex.Device, e typex.RuleX, - registers []common.RegisterRW, - handler *modbus.RTUClientHandler, - client modbus.Client) typex.XExternalDriver { - return &rtu485_THer_Driver{ - state: typex.DRIVER_STOP, - device: d, - RuleEngine: e, - handler: handler, - client: client, - Registers: registers, - lock: sync.Mutex{}, - } -} - -func (rtu485 *rtu485_THer_Driver) Test() error { - _, err := rtu485.client.ReadHoldingRegisters(0x00, 2) - return err -} - -func (rtu485 *rtu485_THer_Driver) Init(map[string]string) error { - - return nil -} - -func (rtu485 *rtu485_THer_Driver) Work() error { - return nil -} - -func (rtu485 *rtu485_THer_Driver) State() typex.DriverState { - return typex.DRIVER_UP -} - -func (rtu485 *rtu485_THer_Driver) Read(cmd []byte, data []byte) (int, error) { - dataMap := map[string]common.RegisterRW{} - for _, r := range rtu485.Registers { - rtu485.handler.SlaveId = r.SlaverId - rtu485.lock.Lock() - results, err := rtu485.client.ReadHoldingRegisters(0x00, 2) - rtu485.lock.Unlock() - if err != nil { - return 0, err - } - if len(results) == 4 { - sd := sensor_data{ - Humidity: float32(utils.BToU16(results, 0, 2)) * 0.1, - Temperature: float32(utils.BToU16(results, 2, 4)) * 0.1, - } - bytes, _ := json.Marshal(sd) - value := common.RegisterRW{ - Tag: r.Tag, - Function: r.Function, - SlaverId: r.SlaverId, - Address: r.Address, - Quantity: r.Quantity, - Value: string(bytes), - } - dataMap[r.Tag] = value - if err != nil { - glogger.GLogger.Error(err) - } - } - } - bytes, _ := json.Marshal(dataMap) - copy(data, bytes) - return len(bytes), nil -} - -func (rtu485 *rtu485_THer_Driver) Write(cmd []byte, _ []byte) (int, error) { - return 0, nil - -} - -// --------------------------------------------------- -func (rtu485 *rtu485_THer_Driver) DriverDetail() typex.DriverDetail { - return typex.DriverDetail{ - Name: "Temperature And Humidity Sensor Driver", - Type: "UART", - Description: "RTU 485 Temperature And Humidity Sensor Driver", - } -} - -func (rtu485 *rtu485_THer_Driver) Stop() error { - rtu485.state = typex.DRIVER_STOP - return nil -} diff --git a/driver/trailer_driver.go b/driver/trailer_driver.go deleted file mode 100644 index 66a5273e7..000000000 --- a/driver/trailer_driver.go +++ /dev/null @@ -1,125 +0,0 @@ -// 拖车驱动 -package driver - -import ( - "context" - - "github.com/hootrhino/rulex/component/trailer" - "github.com/hootrhino/rulex/glogger" - "github.com/hootrhino/rulex/typex" - - "google.golang.org/grpc" -) - -type TrailerDriver struct { - state typex.DriverState - RuleEngine typex.RuleX - client trailer.TrailerClient - config map[string]string -} - -func NewTrailerDriver(e typex.RuleX, grpcConn *grpc.ClientConn) typex.XExternalDriver { - TrailerDriver := &TrailerDriver{ - state: typex.DRIVER_STOP, - RuleEngine: e, - client: trailer.NewTrailerClient(grpcConn), - } - return TrailerDriver - -} -func (sc *TrailerDriver) Test() error { - if err := sc.t(); err != nil { - glogger.GLogger.Error(err) - return err - } - return nil -} - -func (sc *TrailerDriver) Init(config map[string]string) error { - sc.config = config - _, err := sc.client.Init(context.Background(), &trailer.Config{ - Kv: []byte{}, - }) - if err != nil { - glogger.GLogger.Error(err) - return err - } - return nil -} - -func (sc *TrailerDriver) Work() error { - _, err := sc.client.Start(context.Background(), &trailer.Request{}) - if err != nil { - glogger.GLogger.Error(err) - return err - } - return nil -} - -func (sc *TrailerDriver) State() typex.DriverState { - if sc.t() != nil { - return typex.DRIVER_STOP - } - return typex.DRIVER_UP -} - -/* -* -* 读取 -* - */ -func (sc *TrailerDriver) Read(cmd []byte, data []byte) (int, error) { - response, err := sc.client.Service(context.Background(), - &trailer.ServiceRequest{Cmd: cmd, Args: data}) - if err != nil { - glogger.GLogger.Error(err) - return 0, err - } - copy(data, response.GetData()) - return len(response.Data), nil -} - -/* -* -* 写入 -* - */ -func (sc *TrailerDriver) Write(cmd []byte, data []byte) (int, error) { - response, err := sc.client.Service(context.Background(), - &trailer.ServiceRequest{Cmd: cmd, Args: data}) - if err != nil { - glogger.GLogger.Error(err) - return 0, err - } - return int(response.Code), nil -} - -// --------------------------------------------------- -func (sc *TrailerDriver) DriverDetail() typex.DriverDetail { - return typex.DriverDetail{ - Name: "Trailer-DRIVER", - Type: "Trailer", - Description: "Trailer 通用GRPC协议驱动", - } -} - -func (sc *TrailerDriver) Stop() error { - _, err := sc.client.Stop(context.Background(), &trailer.Request{}) - if err != nil { - glogger.GLogger.Error(err) - return err - } - return nil -} - -// ---------------------------------------------------------------------- -// 私有函数 -// ---------------------------------------------------------------------- -func (sc *TrailerDriver) t() error { - _, err := sc.client.Status(context.Background(), &trailer.Request{}) - if err != nil { - glogger.GLogger.Error(err) - return err - } - return nil -} diff --git a/driver/tss200_v_0_2_driver.go b/driver/tss200_v_0_2_driver.go deleted file mode 100644 index 808e197dd..000000000 --- a/driver/tss200_v_0_2_driver.go +++ /dev/null @@ -1,130 +0,0 @@ -// TC-S200 系列空气质量监测仪内置 PM2.5、TVOC、甲醛、CO2,温湿度等高精 -// 度传感器套件,可通过吸顶式或壁挂安装,RS-485 接口通过 Modbus-RTU 协议进行 -// 数据输出,通过网关组网,或配合联动模块可以用于新风联动控制。 -// 该驱动是V0.2版本 -package driver - -import ( - "encoding/json" - "sync" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/typex" - "github.com/hootrhino/rulex/utils" - modbus "github.com/wwhai/gomodbus" -) - -type tss200_v_0_2_Driver struct { - state typex.DriverState - handler *modbus.RTUClientHandler - client modbus.Client - RuleEngine typex.RuleX - Registers []common.RegisterRW - device *typex.Device - lock sync.Mutex -} - -func NewTSS200Driver(d *typex.Device, e typex.RuleX, - registers []common.RegisterRW, - handler *modbus.RTUClientHandler, - client modbus.Client) typex.XExternalDriver { - return &tss200_v_0_2_Driver{ - state: typex.DRIVER_STOP, - device: d, - RuleEngine: e, - handler: handler, - client: client, - Registers: registers, - lock: sync.Mutex{}, - } -} -func (tss *tss200_v_0_2_Driver) Test() error { - return nil -} - -func (tss *tss200_v_0_2_Driver) Init(map[string]string) error { - return nil -} - -func (tss *tss200_v_0_2_Driver) Work() error { - return nil -} - -func (tss *tss200_v_0_2_Driver) State() typex.DriverState { - return typex.DRIVER_UP -} - -type _sensor_data struct { - TEMP float32 `json:"temp"` //系数: 0.01 - HUM float32 `json:"hum"` //系数: 0.01 - PM1 uint16 `json:"pm1"` - PM25 uint16 `json:"pm25"` - PM10 uint16 `json:"pm10"` - CO2 uint16 `json:"co2"` - TVOC float32 `json:"tvoc"` //系数: 0.001 - CHOH float32 `json:"choh"` //系数: 0.001 - ECO2 float32 `json:"eco2"` //系数: 0.001 -} - -func (tss *tss200_v_0_2_Driver) Read(cmd []byte, data []byte) (int, error) { - // 获取全部传感器数据: - // |地址码|功能码|寄存器地址|寄存器长度|校验码|校验码 - // |XX |03 |17 | 长度 |CRC | CRC - // ----------------------------------------------- - // 01 03 00 11 00 08 14 09 09 45 1A F7 00 6F 00 89 00 89 FF FF FF FF 00 0B - // TEMP HUM PM1 PM2.5 Pm10 CO2 TVOC CHOH - // - dataMap := map[string]common.RegisterRW{} - for _, r := range tss.Registers { - tss.handler.SlaveId = r.SlaverId - tss.lock.Lock() - result, err := tss.client.ReadHoldingRegisters(17, 9) - tss.lock.Unlock() - if err != nil { - return 0, err - } - if len(result) == 18 { - sd := _sensor_data{ - TEMP: float32(utils.BToU16(result, 0, 2)) * 0.01, - HUM: float32(utils.BToU16(result, 2, 4)) * 0.01, - PM1: utils.BToU16(result, 4, 6), - PM25: utils.BToU16(result, 6, 8), - PM10: utils.BToU16(result, 8, 10), - CO2: utils.BToU16(result, 10, 12), - TVOC: float32(utils.BToU16(result, 12, 14)) * 0.01, - CHOH: float32(utils.BToU16(result, 14, 16)) * 0.001, - ECO2: float32(utils.BToU16(result, 16, 18)) * 0.01, - } - bytes, _ := json.Marshal(sd) - value := common.RegisterRW{ - Tag: r.Tag, - Function: r.Function, - SlaverId: r.SlaverId, - Address: r.Address, - Quantity: r.Quantity, - Value: string(bytes), - } - dataMap[r.Tag] = value - } - } - bytes, _ := json.Marshal(dataMap) - copy(data, bytes) - return len(bytes), nil -} -func (tss *tss200_v_0_2_Driver) Write(cmd []byte, _ []byte) (int, error) { - return 0, nil -} - -// --------------------------------------------------- -func (tss *tss200_v_0_2_Driver) DriverDetail() typex.DriverDetail { - return typex.DriverDetail{ - Name: "TC-S200", - Type: "UART", - Description: "TC-S200 系列空气质量监测仪", - } -} - -func (tss *tss200_v_0_2_Driver) Stop() error { - tss.state = typex.DRIVER_STOP - return nil -} diff --git a/driver/usr_g776_4gdtu_driver.go b/driver/usr_g776_4gdtu_driver.go deleted file mode 100644 index e4dd4b3d5..000000000 --- a/driver/usr_g776_4gdtu_driver.go +++ /dev/null @@ -1,81 +0,0 @@ -package driver - -import ( - "context" - "errors" - - "github.com/hootrhino/rulex/typex" - serial "github.com/wwhai/goserial" -) - -type UsrG776Driver struct { - state typex.DriverState - serialPort serial.Port - ctx context.Context - RuleEngine typex.RuleX - device *typex.Device -} - -// 初始化一个驱动 -func NewUsrG776Driver( - ctx context.Context, - e typex.RuleX, - device *typex.Device, - serialPort serial.Port, -) typex.XExternalDriver { - return &UsrG776Driver{ - RuleEngine: e, - ctx: ctx, - serialPort: serialPort, - device: device, - } -} - -func (d *UsrG776Driver) Init(map[string]string) error { - d.state = typex.DRIVER_UP - - return nil -} - -func (d *UsrG776Driver) Work() error { - - return nil - -} -func (d *UsrG776Driver) State() typex.DriverState { - return d.state -} -func (d *UsrG776Driver) Stop() error { - d.state = typex.DRIVER_STOP - return d.serialPort.Close() -} - -func (d *UsrG776Driver) Test() error { - if d.serialPort == nil { - return errors.New("serialPort is nil") - } - _, err := d.serialPort.Write([]byte("AT\n")) - return err - -} - -func (d *UsrG776Driver) Read(cmd []byte, b []byte) (int, error) { - return 0, nil -} - -func (d *UsrG776Driver) Write(cmd []byte, b []byte) (int, error) { - if string(cmd) == "AT" { - return d.serialPort.Write(b) - } - if string(cmd) == "DATA" { - return d.serialPort.Write(b) - } - return 0, nil -} -func (d *UsrG776Driver) DriverDetail() typex.DriverDetail { - return typex.DriverDetail{ - Name: "UsrG776Driver Driver", - Type: "RAW_UART", - Description: "UsrG776Driver Driver", - } -} diff --git a/driver/yk8_relay_controller_driver.go b/driver/yk8_relay_controller_driver.go deleted file mode 100644 index b3c451c25..000000000 --- a/driver/yk8_relay_controller_driver.go +++ /dev/null @@ -1,142 +0,0 @@ -package driver - -// -// RS232/RS485 控制继电器模块,可利用电脑通过串口(没有串口的可利用 USB 转 -// 串口)连接控制器进行对设备的控制,接口采用开关输出,有常开常闭点。 -// 资料首页:http://www.yi-kun.com -// -import ( - "encoding/json" - - "github.com/hootrhino/rulex/common" - "github.com/hootrhino/rulex/typex" - modbus "github.com/wwhai/gomodbus" -) - -type YK8RelayControllerDriver struct { - state typex.DriverState - handler *modbus.RTUClientHandler - client modbus.Client - RuleEngine typex.RuleX - Registers []common.RegisterRW - device *typex.Device -} - -func NewYK8RelayControllerDriver(d *typex.Device, e typex.RuleX, - registers []common.RegisterRW, - handler *modbus.RTUClientHandler, - client modbus.Client) typex.XExternalDriver { - return &YK8RelayControllerDriver{ - state: typex.DRIVER_STOP, - device: d, - RuleEngine: e, - handler: handler, - Registers: registers, - client: client, - } -} - -func (yk8 *YK8RelayControllerDriver) Test() error { - return nil -} - -func (yk8 *YK8RelayControllerDriver) Init(map[string]string) error { - return nil -} - -func (yk8 *YK8RelayControllerDriver) Work() error { - return nil -} - -func (yk8 *YK8RelayControllerDriver) State() typex.DriverState { - return typex.DRIVER_UP -} - -// - -type yk08sw struct { - Sw1 uint8 `json:"sw1"` - Sw2 uint8 `json:"sw2"` - Sw3 uint8 `json:"sw3"` - Sw4 uint8 `json:"sw4"` - Sw5 uint8 `json:"sw5"` - Sw6 uint8 `json:"sw6"` - Sw7 uint8 `json:"sw7"` - Sw8 uint8 `json:"sw8"` -} - -/* -* -* 读出来的是个JSON, 记录了8个开关的状态 -* - */ -func (yk8 *YK8RelayControllerDriver) Read(cmd []byte, data []byte) (int, error) { - dataMap := map[string]common.RegisterRW{} - for _, r := range yk8.Registers { - yk8.handler.SlaveId = r.SlaverId - results, err := yk8.client.ReadCoils(0x00, 0x08) - if err != nil { - return 0, err - } - if len(results) == 1 { - yks := yk08sw{ - Sw1: common.BitToUint8(results[0], 0), - Sw2: common.BitToUint8(results[0], 1), - Sw3: common.BitToUint8(results[0], 2), - Sw4: common.BitToUint8(results[0], 3), - Sw5: common.BitToUint8(results[0], 4), - Sw6: common.BitToUint8(results[0], 5), - Sw7: common.BitToUint8(results[0], 6), - Sw8: common.BitToUint8(results[0], 7), - } - bytes, _ := json.Marshal(yks) - value := common.RegisterRW{ - Tag: r.Tag, - Function: r.Function, - SlaverId: r.SlaverId, - Address: r.Address, - Quantity: r.Quantity, - Value: string(bytes), - } - dataMap[r.Tag] = value - } - } - - bytes, _ := json.Marshal(dataMap) - copy(data, bytes) - return len(bytes), nil -} - -// 写入数据 -func (yk8 *YK8RelayControllerDriver) Write(cmd []byte, data []byte) (int, error) { - dataMap := []common.RegisterRW{} - if err := json.Unmarshal(data, &dataMap); err != nil { - return 0, err - } - for _, r := range dataMap { - yk8.handler.SlaveId = r.SlaverId - bytes, err0 := common.BitStringToBytes(string(r.Value)) - if err0 != nil { - return 0, err0 - } - _, err1 := yk8.client.WriteMultipleCoils(0, 1, bytes) - if err1 != nil { - return 0, err1 - } - } - return 0, nil -} - -// --------------------------------------------------- -func (yk8 *YK8RelayControllerDriver) DriverDetail() typex.DriverDetail { - return typex.DriverDetail{ - Name: "YK-08-RELAY CONTROLLER", - Type: "UART", - Description: "一个支持RS232和485的国产8路继电器控制器", - } -} - -func (yk8 *YK8RelayControllerDriver) Stop() error { - yk8.state = typex.DRIVER_STOP - return nil -} diff --git a/engine/engine.go b/engine/engine.go index 682fc30a5..ce4bdacd5 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -485,24 +485,6 @@ func (e *RuleEngine) InitDeviceTypeManager() error { NewDevice: device.NewIRDevice, }, ) - e.DeviceTypeManager.Register(typex.TSS200V02, - &typex.XConfig{ - Engine: e, - NewDevice: device.NewTS200Sensor, - }, - ) - e.DeviceTypeManager.Register(typex.YK08_RELAY, - &typex.XConfig{ - Engine: e, - NewDevice: device.NewYK8Controller, - }, - ) - e.DeviceTypeManager.Register(typex.RTU485_THER, - &typex.XConfig{ - Engine: e, - NewDevice: device.NewRtu485Ther, - }, - ) e.DeviceTypeManager.Register(typex.SIEMENS_PLC, &typex.XConfig{ Engine: e, @@ -527,12 +509,6 @@ func (e *RuleEngine) InitDeviceTypeManager() error { NewDevice: device.NewGenericSnmpDevice, }, ) - e.DeviceTypeManager.Register(typex.USER_G776, - &typex.XConfig{ - Engine: e, - NewDevice: device.NewUsrG776DTU, - }, - ) e.DeviceTypeManager.Register(typex.ICMP_SENDER, &typex.XConfig{ Engine: e, diff --git a/typex/xdevice.go b/typex/xdevice.go index b9bdcf8cd..955f14c3d 100644 --- a/typex/xdevice.go +++ b/typex/xdevice.go @@ -48,15 +48,11 @@ func (d DeviceType) String() string { // 支持的设备类型 const ( - TSS200V02 DeviceType = "TSS200V02" // Multi params Sensor - RTU485_THER DeviceType = "RTU485_THER" // RS485 Sensor - YK08_RELAY DeviceType = "YK08_RELAY" // YK8 RS485 Relay SIEMENS_PLC DeviceType = "SIEMENS_PLC" // SIEMENS-S71200 GENERIC_MODBUS DeviceType = "GENERIC_MODBUS" // 通用Modbus GENERIC_MODBUS_POINT_EXCEL DeviceType = "GENERIC_MODBUS_POINT_EXCEL" // 通用Modbus通过Excel表配置点位 GENERIC_UART DeviceType = "GENERIC_UART" // 通用串口 GENERIC_SNMP DeviceType = "GENERIC_SNMP" // SNMP 支持 - USER_G776 DeviceType = "USER_G776" // 有人 G776 4G模组 ICMP_SENDER DeviceType = "ICMP_SENDER" // ICMP_SENDER GENERIC_PROTOCOL DeviceType = "GENERIC_PROTOCOL" // 通用自定义协议处理器 GENERIC_OPCUA DeviceType = "GENERIC_OPCUA" // 通用OPCUA From 86a3017553e4e8bf97c8c7cbeb9aefbb5234f328 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 22 Dec 2023 19:44:38 +0800 Subject: [PATCH 131/138] dev: support Variables --- .../apis/user_lua_template_api.go | 20 +++++++++++++------ typex/version.go | 4 ++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/component/rulex_api_server/apis/user_lua_template_api.go b/component/rulex_api_server/apis/user_lua_template_api.go index c88483396..f575df5cf 100644 --- a/component/rulex_api_server/apis/user_lua_template_api.go +++ b/component/rulex_api_server/apis/user_lua_template_api.go @@ -47,10 +47,17 @@ func CreateUserLuaTemplate(c *gin.Context, ruleEngine typex.RuleX) { Detail: form.Detail, Gid: form.Gid, } + Variables, err1 := MUserLuaTemplate.GenVariables(form.Variables) + if err1 != nil { + c.JSON(common.HTTP_OK, common.Error("Group not found")) + return + } + MUserLuaTemplate.Variables = Variables if err := service.InsertUserLuaTemplate(MUserLuaTemplate); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } + // 新建用户模板的时候必须给一个分组 if err := service.BindResource(form.Gid, MUserLuaTemplate.UUID); err != nil { c.JSON(common.HTTP_OK, common.Error("Group not found")) @@ -155,12 +162,13 @@ func SearchUserLuaTemplateGroup(c *gin.Context, ruleEngine typex.RuleX) { keyword, _ := c.GetQuery("keyword") for _, vv := range service.SearchUserLuaTemplate(keyword, keyword) { visuals = append(visuals, UserLuaTemplateVo{ - UUID: vv.UUID, - Label: vv.Label, - Type: vv.Type, - Apply: vv.Apply, - Detail: vv.Detail, - Gid: vv.Gid, + UUID: vv.UUID, + Label: vv.Label, + Type: vv.Type, + Apply: vv.Apply, + Detail: vv.Detail, + Gid: vv.Gid, + Variables: vv.GetVariables(), }) } c.JSON(common.HTTP_OK, common.OkWithData(visuals)) diff --git a/typex/version.go b/typex/version.go index 9306783cc..b901fd69f 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-21 14:56:01", + ReleaseTime: "2023-12-22 17:03:28", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-4d6a3c7179f8330 +** Version: v0.6.4-40b0767b39d249c ** Document: https://hootrhino.github.io ` From 1733cef8b0ce5e729901cbca42c6ee42fc012cb1 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 22 Dec 2023 20:17:28 +0800 Subject: [PATCH 132/138] fix: fix concurrent map error --- glogger/ws_logger.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/glogger/ws_logger.go b/glogger/ws_logger.go index c4d763c19..fe0a68fee 100644 --- a/glogger/ws_logger.go +++ b/glogger/ws_logger.go @@ -70,14 +70,14 @@ type RealTimeLogger struct { } func (w *RealTimeLogger) Write(p []byte) (n int, err error) { + w.lock.Lock() for _, c := range w.Clients { - w.lock.Lock() err := c.WriteMessage(websocket.TextMessage, p) - w.lock.Unlock() if err != nil { return 0, err } } + w.lock.Unlock() return 0, nil } From ac3156e99247a669c7e3c7a2d02f8d93de4c7388 Mon Sep 17 00:00:00 2001 From: wwhai Date: Wed, 27 Dec 2023 21:43:20 +0800 Subject: [PATCH 133/138] dev: enhance rule; optimize dashboard data --- component/internotify/internotify.go | 2 +- component/interqueue/yqueue.go | 4 +- component/rulex_api_server/apis/device_api.go | 7 +- component/rulex_api_server/apis/rule_api.go | 311 ++++++++++-------- component/rulex_api_server/http_api_server.go | 1 - component/rulex_api_server/model/model.go | 14 +- .../rulex_api_server/server/res_loader.go | 8 +- conf/rulex.ini | 2 +- device/generic_http_device.go | 53 ++- device/generic_http_device.md | 64 ++++ engine/engine.go | 31 +- engine/load_rule.go | 23 +- ...ows.go => rhinoh3_datetime_ctl_windows.go} | 32 +- .../rhinoh3_ubuntu18_datetime_ctl_linux.go | 5 +- test/conf/rulex.ini | 2 +- typex/rule.go | 12 +- typex/version.go | 4 +- 17 files changed, 376 insertions(+), 199 deletions(-) rename ossupport/{rhinoh3_ubuntu18_datetime_ctl_windows.go => rhinoh3_datetime_ctl_windows.go} (58%) diff --git a/component/internotify/internotify.go b/component/internotify/internotify.go index 7719aaab1..84e9dbdee 100644 --- a/component/internotify/internotify.go +++ b/component/internotify/internotify.go @@ -101,7 +101,7 @@ func GetQueue() chan BaseEvent { */ func InitInternalEventBus(r typex.RuleX, MaxQueueSize int) *InternalEventBus { __DefaultInternalEventBus = new(InternalEventBus) - __DefaultInternalEventBus.Queue = make(chan BaseEvent, MaxQueueSize) + __DefaultInternalEventBus.Queue = make(chan BaseEvent, 1024) __DefaultInternalEventBus.Rulex = r return __DefaultInternalEventBus } diff --git a/component/interqueue/yqueue.go b/component/interqueue/yqueue.go index 1ed4b888d..0a4442d25 100644 --- a/component/interqueue/yqueue.go +++ b/component/interqueue/yqueue.go @@ -48,8 +48,8 @@ type InteractQueue struct { func InitInteractQueue(rulex typex.RuleX, maxQueueSize int) *InteractQueue { __DefaultInteractQueue = InteractQueue{ - inQueue: make(chan InteractQueueData, maxQueueSize), - outQueue: make(chan InteractQueueData, maxQueueSize), + inQueue: make(chan InteractQueueData, 1), + outQueue: make(chan InteractQueueData, 1), rulex: rulex, } return &__DefaultInteractQueue diff --git a/component/rulex_api_server/apis/device_api.go b/component/rulex_api_server/apis/device_api.go index 71c44173c..7a1afff0e 100644 --- a/component/rulex_api_server/apis/device_api.go +++ b/component/rulex_api_server/apis/device_api.go @@ -107,11 +107,6 @@ func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err)) return } - // 要处理这个空字符串 "" - if Mdev.BindRules.Len() == 1 && len(Mdev.BindRules[0]) != 0 { - c.JSON(common.HTTP_OK, common.Error("Can't remove, Already have rule bind:"+Mdev.BindRules.String())) - return - } // 检查是否有规则被绑定了 for _, ruleId := range Mdev.BindRules { if ruleId != "" { @@ -120,6 +115,8 @@ func DeleteDevice(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err0)) return } + c.JSON(common.HTTP_OK, common.Error("Can't remove, Already have rule bind:"+Mdev.BindRules.String())) + return } } diff --git a/component/rulex_api_server/apis/rule_api.go b/component/rulex_api_server/apis/rule_api.go index edc9bbe07..801be9810 100644 --- a/component/rulex_api_server/apis/rule_api.go +++ b/component/rulex_api_server/apis/rule_api.go @@ -44,8 +44,8 @@ func RuleDetail(c *gin.Context, ruleEngine typex.RuleX) { Name: rule.Name, Status: 1, Description: rule.Description, - FromSource: rule.FromSource, - FromDevice: rule.FromDevice, + FromSource: []string{rule.SourceId}, + FromDevice: []string{rule.DeviceId}, Success: rule.Success, Failed: rule.Failed, Actions: rule.Actions, @@ -62,8 +62,8 @@ func Rules(c *gin.Context, ruleEngine typex.RuleX) { Name: rule.Name, Status: 1, Description: rule.Description, - FromSource: rule.FromSource, - FromDevice: rule.FromDevice, + FromSource: []string{rule.SourceId}, + FromDevice: []string{rule.DeviceId}, Success: rule.Success, Failed: rule.Failed, Actions: rule.Actions, @@ -111,7 +111,7 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { } // tmpRule 是一个一次性的临时rule,用来验证规则,这么做主要是为了防止真实Lua Vm 被污染 - tmpRule := typex.NewRule(nil, "_", "_", "_", []string{}, []string{}, + tmpRule := typex.NewRule(nil, "_", "_", "_", "", "", form.Success, form.Actions, form.Failed) if err := core.VerifyLuaSyntax(tmpRule); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) @@ -123,8 +123,18 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { utils.RuleUuid(), form.Name, form.Description, - form.FromSource, - form.FromDevice, + func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromSource), + func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromDevice), form.Success, form.Actions, form.Failed) @@ -147,11 +157,21 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { Name: form.Name, UUID: rule.UUID, Description: form.Description, - FromSource: form.FromSource, - FromDevice: form.FromDevice, - Success: form.Success, - Failed: form.Failed, - Actions: form.Actions, + SourceId: func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromSource), + DeviceId: func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromDevice), + Success: form.Success, + Failed: form.Failed, + Actions: form.Actions, } // 去重旧的 ruleMap := map[string]string{} @@ -202,11 +222,21 @@ func CreateRule(c *gin.Context, ruleEngine typex.RuleX) { Name: form.Name, UUID: rule.UUID, Description: form.Description, - FromSource: form.FromSource, - FromDevice: form.FromDevice, - Success: form.Success, - Failed: form.Failed, - Actions: form.Actions, + SourceId: func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromSource), + DeviceId: func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromDevice), + Success: form.Success, + Failed: form.Failed, + Actions: form.Actions, } // 追加新的ID ruleMap[devId] = mRule.UUID // append New Rule UUID @@ -262,7 +292,7 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { return } // tmpRule 是一个一次性的临时rule,用来验证规则,这么做主要是为了防止真实Lua Vm 被污染 - tmpRule := typex.NewRule(nil, "_", "_", "_", []string{}, []string{}, + tmpRule := typex.NewRule(nil, "_", "_", "_", "", "", form.Success, form.Actions, form.Failed) if err := core.VerifyLuaSyntax(tmpRule); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) @@ -282,21 +312,21 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { return } } - mRule, err := service.GetMRuleWithUUID(form.UUID) + OldRule, err := service.GetMRuleWithUUID(form.UUID) if err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } rule := typex.NewLuaRule( ruleEngine, - mRule.UUID, - mRule.Name, - mRule.Description, - mRule.FromSource, - mRule.FromDevice, - mRule.Success, - mRule.Actions, - mRule.Failed) + OldRule.UUID, + OldRule.Name, + OldRule.Description, + OldRule.SourceId, + OldRule.DeviceId, + OldRule.Success, + OldRule.Actions, + OldRule.Failed) ruleEngine.RemoveRule(rule.UUID) if err := ruleEngine.LoadRule(rule); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) @@ -304,14 +334,24 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { } // SaveDB // - if err := service.UpdateMRule(mRule.UUID, &model.MRule{ + if err := service.UpdateMRule(OldRule.UUID, &model.MRule{ Name: form.Name, Description: form.Description, - FromSource: form.FromSource, - FromDevice: form.FromDevice, - Success: form.Success, - Failed: form.Failed, - Actions: form.Actions, + SourceId: func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromSource), + DeviceId: func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromDevice), + Success: form.Success, + Failed: form.Failed, + Actions: form.Actions, }); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return @@ -324,73 +364,69 @@ func UpdateRule(c *gin.Context, ruleEngine typex.RuleX) { return default: } - // 更新FromSource RULE到Device表中 - for _, inId := range form.FromSource { - if inId != "" { - InEnd, _ := service.GetMInEndWithUUID(inId) - if InEnd == nil { - //c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) - return - } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range InEnd.BindRules { - ruleMap[rule] = rule - } - // 追加新的ID - ruleMap[inId] = mRule.UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } - InEnd.BindRules = BindRules - if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ - BindRules: BindRules, - }); err != nil { - //c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // LoadNewest!!! - if err := server.LoadNewestInEnd(inId, ruleEngine); err != nil { - //c.JSON(common.HTTP_OK, common.Error400(err)) - return - } + if len(form.FromSource) > 0 { + // 更新FromSource RULE到Device表中 + InEnd, _ := service.GetMInEndWithUUID(form.FromSource[0]) + if InEnd == nil { + //c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+inId)) + return + } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range InEnd.BindRules { + ruleMap[rule] = rule + } + // 追加新的ID + ruleMap[OldRule.UUID] = OldRule.UUID // append New Rule UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + InEnd.BindRules = BindRules + if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ + BindRules: BindRules, + }); err != nil { + //c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // LoadNewest!!! + if err := server.LoadNewestInEnd(InEnd.UUID, ruleEngine); err != nil { + //c.JSON(common.HTTP_OK, common.Error400(err)) + return } - } // FromDevice - for _, devId := range form.FromDevice { - if devId != "" { - Device, _ := service.GetMDeviceWithUUID(devId) - if Device == nil { - //c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) - return - } - // 去重旧的 - ruleMap := map[string]string{} - for _, rule := range Device.BindRules { - ruleMap[rule] = rule // for ["", "", "" ....] - } - // 追加新的ID - ruleMap[devId] = mRule.UUID // append New Rule UUID - // 最后ID列表 - BindRules := []string{} - for _, iid := range ruleMap { - BindRules = append(BindRules, iid) - } - Device.BindRules = BindRules - if err := service.UpdateDevice(Device.UUID, &model.MDevice{ - BindRules: BindRules, - }); err != nil { - //c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - // LoadNewest!!! - if err := server.LoadNewestDevice(devId, ruleEngine); err != nil { - //c.JSON(common.HTTP_OK, common.Error400(err)) - return - } + if len(form.FromDevice) > 0 { + + Device, _ := service.GetMDeviceWithUUID(form.FromDevice[0]) + if Device == nil { + //c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) + return + } + // 去重旧的 + ruleMap := map[string]string{} + for _, rule := range Device.BindRules { + ruleMap[rule] = rule // for ["", "", "" ....] + } + // 追加新的ID + ruleMap[OldRule.UUID] = OldRule.UUID // append New Rule UUID + // 最后ID列表 + BindRules := []string{} + for _, iid := range ruleMap { + BindRules = append(BindRules, iid) + } + Device.BindRules = BindRules + if err := service.UpdateDevice(Device.UUID, &model.MDevice{ + BindRules: BindRules, + }); err != nil { + //c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + // LoadNewest!!! + if err := server.LoadNewestDevice(Device.UUID, ruleEngine); err != nil { + //c.JSON(common.HTTP_OK, common.Error400(err)) + return } } }() @@ -405,69 +441,68 @@ func DeleteRule(c *gin.Context, ruleEngine typex.RuleX) { c.JSON(common.HTTP_OK, common.Error400(err0)) return } - // 更新FromSource RULE到Device表中 - for _, id := range mRule.FromSource { - InEnd, _ := service.GetMInEndWithUUID(id) + if len(mRule.SourceId) > 0 { + InEnd, _ := service.GetMInEndWithUUID(mRule.SourceId) if InEnd == nil { - c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+id)) + c.JSON(common.HTTP_OK, common.Error(`inend not exists: `+mRule.SourceId)) return } // 去重旧的 - BindRules := []string{} + InEndBindRules := []string{} for _, iid := range InEnd.BindRules { if iid != mRule.UUID { - BindRules = append(BindRules, iid) + InEndBindRules = append(InEndBindRules, iid) } } if err := service.UpdateMInEnd(InEnd.UUID, &model.MInEnd{ - BindRules: BindRules, + BindRules: InEndBindRules, }); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } + + if err := server.LoadNewestInEnd(mRule.SourceId, ruleEngine); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } + } + // FromDevice - for _, devId := range mRule.FromDevice { - Device, _ := service.GetMDeviceWithUUID(devId) + if len(mRule.DeviceId) > 0 { + Device, _ := service.GetMDeviceWithUUID(mRule.DeviceId) if Device == nil { - c.JSON(common.HTTP_OK, common.Error(`device not exists: `+devId)) + c.JSON(common.HTTP_OK, common.Error(`device not exists: `+mRule.DeviceId)) return } // 去重旧的 - BindRules := []string{} + DeviceBindRules := []string{} for _, iid := range Device.BindRules { if iid != mRule.UUID { - BindRules = append(BindRules, iid) + DeviceBindRules = append(DeviceBindRules, iid) } } if err := service.UpdateDevice(Device.UUID, &model.MDevice{ - BindRules: BindRules, + BindRules: DeviceBindRules, }); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } + // + // 内存里的数据刷新完了以后更新数据库,最后重启 + // + if err := server.LoadNewestDevice(mRule.DeviceId, ruleEngine); err != nil { + c.JSON(common.HTTP_OK, common.Error400(err)) + return + } } + if err := service.DeleteMRule(uuid); err != nil { c.JSON(common.HTTP_OK, common.Error400(err)) return } ruleEngine.RemoveRule(uuid) - // - // 内存里的数据刷新完了以后更新数据库,最后重启 - // - for _, devId := range mRule.FromDevice { - if err := server.LoadNewestDevice(devId, ruleEngine); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - } - for _, devId := range mRule.FromSource { - if err := server.LoadNewestInEnd(devId, ruleEngine); err != nil { - c.JSON(common.HTTP_OK, common.Error400(err)) - return - } - } c.JSON(common.HTTP_OK, common.Ok()) } @@ -494,8 +529,18 @@ func ValidateLuaSyntax(c *gin.Context, ruleEngine typex.RuleX) { "", // 不需要该字段 "", // 不需要该字段 "", // 不需要该字段 - form.FromSource, - form.FromDevice, + func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromSource), + func(s []string) string { + if len(s) > 0 { + return s[0] + } + return "" + }(form.FromDevice), form.Success, form.Actions, form.Failed) @@ -614,11 +659,11 @@ func ListByDevice(c *gin.Context, ruleEngine typex.RuleX) { mRules := service.AllMRules() // 这个效率太低了, 后期写个SQL优化一下 ruleVos := []ruleVo{} for _, rule := range mRules { - if utils.SContains(rule.FromDevice, MDevice.UUID) { + if utils.SContains([]string{rule.DeviceId}, MDevice.UUID) { ruleVos = append(ruleVos, ruleVo{ UUID: rule.UUID, - FromSource: rule.FromSource, - FromDevice: rule.FromDevice, + FromSource: []string{rule.SourceId}, + FromDevice: []string{rule.DeviceId}, Name: rule.Name, Status: 1, Description: rule.Description, @@ -648,11 +693,11 @@ func ListByInend(c *gin.Context, ruleEngine typex.RuleX) { mRules := service.AllMRules() // 这个效率太低了, 后期写个SQL优化一下 ruleVos := []ruleVo{} for _, rule := range mRules { - if utils.SContains(rule.FromSource, MInend.UUID) { + if utils.SContains([]string{rule.SourceId}, MInend.UUID) { ruleVos = append(ruleVos, ruleVo{ UUID: rule.UUID, - FromSource: rule.FromSource, - FromDevice: rule.FromDevice, + FromSource: []string{rule.SourceId}, + FromDevice: []string{rule.DeviceId}, Name: rule.Name, Status: 1, Description: rule.Description, diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index e7fbf70d7..9b973b4a9 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -312,7 +312,6 @@ func (hs *ApiServerPlugin) LoadRoute() { { osApi.GET(("/netInterfaces"), server.AddRoute(apis.GetNetInterfaces)) osApi.GET(("/osRelease"), server.AddRoute(apis.CatOsRelease)) - // osApi.GET(("/uarts"), server.AddRoute(apis.GetUartList)) osApi.GET(("/system"), server.AddRoute(apis.System)) osApi.GET(("/startedAt"), server.AddRoute(apis.StartedAt)) } diff --git a/component/rulex_api_server/model/model.go b/component/rulex_api_server/model/model.go index 05cb40d5f..22166c779 100644 --- a/component/rulex_api_server/model/model.go +++ b/component/rulex_api_server/model/model.go @@ -42,13 +42,13 @@ func (f StringList) Len() int { type MRule struct { RulexModel - UUID string `gorm:"not null"` - Name string `gorm:"not null"` - FromSource StringList `gorm:"not null type:string[]"` - FromDevice StringList `gorm:"not null type:string[]"` - Actions string `gorm:"not null"` - Success string `gorm:"not null"` - Failed string `gorm:"not null"` + UUID string `gorm:"not null"` + Name string `gorm:"not null"` + SourceId string `gorm:"not null"` + DeviceId string `gorm:"not null"` + Actions string `gorm:"not null"` + Success string `gorm:"not null"` + Failed string `gorm:"not null"` Description string } diff --git a/component/rulex_api_server/server/res_loader.go b/component/rulex_api_server/server/res_loader.go index 28cbf162d..d3513b66f 100644 --- a/component/rulex_api_server/server/res_loader.go +++ b/component/rulex_api_server/server/res_loader.go @@ -56,8 +56,8 @@ func LoadNewestInEnd(uuid string, ruleEngine typex.RuleX) error { mRule.UUID, mRule.Name, mRule.Description, - mRule.FromSource, - mRule.FromDevice, + mRule.SourceId, + mRule.DeviceId, mRule.Success, mRule.Actions, mRule.Failed) @@ -148,8 +148,8 @@ func LoadNewestDevice(uuid string, ruleEngine typex.RuleX) error { mRule.UUID, mRule.Name, mRule.Description, - mRule.FromSource, - mRule.FromDevice, + mRule.SourceId, + mRule.DeviceId, mRule.Success, mRule.Actions, mRule.Failed) diff --git a/conf/rulex.ini b/conf/rulex.ini index 2e8e6d7e9..966601cb2 100644 --- a/conf/rulex.ini +++ b/conf/rulex.ini @@ -34,7 +34,7 @@ log_path = rulexlog # # Max data cache size # -max_queue_size = 20971520 +max_queue_size = 102400 # # Max store size, default is 20MB # diff --git a/device/generic_http_device.go b/device/generic_http_device.go index 7f7b925cd..22c494049 100644 --- a/device/generic_http_device.go +++ b/device/generic_http_device.go @@ -1,7 +1,10 @@ package device import ( + "fmt" + "io" "net/http" + "net/url" "sync" "time" @@ -55,7 +58,9 @@ func (hd *GenericHttpDevice) Init(devId string, configMap map[string]interface{} glogger.GLogger.Error(err) return err } - + if _, err := isValidHTTP_URL(hd.mainConfig.HttpConfig.Url); err != nil { + return fmt.Errorf("invalid url format:%s, %s", hd.mainConfig.HttpConfig.Url, err) + } return nil } @@ -79,7 +84,7 @@ func (hd *GenericHttpDevice) Start(cctx typex.CCTX) error { { } } - body := utils.Get(hd.client, hd.mainConfig.HttpConfig.Url) + body := httpGet(hd.client, hd.mainConfig.HttpConfig.Url) if body != "" { hd.RuleEngine.WorkDevice(hd.Details(), body) } @@ -146,3 +151,47 @@ func (hd *GenericHttpDevice) OnDCACall(UUID string, Command string, Args interfa func (hd *GenericHttpDevice) OnCtrl(cmd []byte, args []byte) ([]byte, error) { return []byte{}, nil } + +/* +* +* HTTP GET +* + */ +func httpGet(client http.Client, url string) string { + var err error + client.Timeout = 2 * time.Second + request, err := http.NewRequest("GET", url, nil) + if err != nil { + glogger.GLogger.Warn(err) + return "" + } + + response, err := client.Do(request) + if err != nil { + glogger.GLogger.Warn(err) + return "" + } + defer response.Body.Close() + body, err := io.ReadAll(response.Body) + if err != nil { + glogger.GLogger.Warn(err) + return "" + } + return string(body) +} + +/* +* +* 验证URL语法 +* + */ +func isValidHTTP_URL(urlStr string) (bool, error) { + r, err := url.Parse(urlStr) + if err != nil { + return false, fmt.Errorf("error parsing URL: %w", err) + } + if r.Scheme != "http" && r.Scheme != "https" { + return false, fmt.Errorf("invalid scheme; must be http or https") + } + return true, nil +} diff --git a/device/generic_http_device.md b/device/generic_http_device.md index 7b5cd1885..f656bcc69 100644 --- a/device/generic_http_device.md +++ b/device/generic_http_device.md @@ -29,4 +29,68 @@ "description": "" } } +``` + +## 测试 +下面是一个传感器采集到的数据: +```lua +{ + "device_id": 1, // 设备的唯一标识符 + "recv_time": "2023-12-01T15:27:25+08:00", // 数据接收的时间戳 + "bat_voltage": 0, // 电池电压,单位通常为伏特 + "longitude": 0, // 经度,表示设备所在位置的东经或西经度数 + "latitude": 0, // 纬度,表示设备所在位置的北纬或南纬度数 + "air_height": 0, // 距离海平面的空气高度,单位通常为米 + "water_temp": 18.91, // 水温,单位通常为摄氏度 + "salinity": 627.317, // 盐度,表示水中溶解盐的含量 + "dissolved_oxygen": 0, // 溶解氧含量,单位通常为毫克/升 + "ph_value": 5.95799, // pH值,表示水质的酸碱程度 + "wind_speed": 4.48, // 风速,单位通常为米/秒 + "wind_direction": 37, // 风向,通常以北为0度,顺时针增加 + "air_temp": 13.9, // 空气温度,单位通常为摄氏度 + "air_pressure": 102.6, // 空气压力,单位通常为百帕 + "air_humidity": 63.9, // 空气湿度,通常以百分比表示 + "noise": 42, // 噪音水平,单位通常为分贝 + "wave_height": 0, // 波高,单位通常为米 + "mean_wave_period": 0, // 平均波周期,单位通常为秒 + "peak_wave_period": 0, // 最大波周期,单位通常为秒 + "mean_wave_direction": 0 // 平均波向,通常以北为0度,顺时针增加 +} + +``` + +使用LUA脚本解析并且打印出来: + +```lua +Actions = { + function(args) + local jsonTable = { + device_id = "设备唯一标识符", + recv_time = "数据接收时间戳", + bat_voltage = "电池电压", + longitude = "经度", + latitude = "纬度", + air_height = "空气高度", + water_temp = "水温", + salinity = "盐度", + dissolved_oxygen = "溶解氧含量", + ph_value = "pH值", + wind_speed = "风速", + wind_direction = "风向", + air_temp = "空气温度", + air_pressure = "空气压力", + air_humidity = "空气湿度", + noise = "噪音水平", + wave_height = "波高", + mean_wave_period = "平均波周期", + peak_wave_period = "最大波周期", + mean_wave_direction = "平均波向" + } + local dataT = json:J2T(args) + for k, v in pairs(dataT) do + stdlib:Debug(jsonTable[k] .. ": " .. v) + end + return true, args + end +} ``` \ No newline at end of file diff --git a/engine/engine.go b/engine/engine.go index ce4bdacd5..61f99d509 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -43,6 +43,7 @@ import ( "github.com/hootrhino/rulex/typex" "github.com/hootrhino/rulex/utils" "github.com/shirou/gopsutil/v3/disk" + "github.com/sirupsen/logrus" ) /* @@ -259,20 +260,22 @@ func (e *RuleEngine) RunSourceCallbacks(in *typex.InEnd, callbackArgs string) { */ func (e *RuleEngine) RunDeviceCallbacks(Device *typex.Device, callbackArgs string) { for _, rule := range Device.BindRules { - if rule.Status == typex.RULE_RUNNING { - _, errA := core.ExecuteActions(&rule, lua.LString(callbackArgs)) - if errA != nil { - glogger.GLogger.Error("RunLuaCallbacks error:", errA) - _, err1 := core.ExecuteFailed(rule.LuaVM, lua.LString(errA.Error())) - if err1 != nil { - glogger.GLogger.Error(err1) - } - } else { - _, err2 := core.ExecuteSuccess(rule.LuaVM) - if err2 != nil { - glogger.GLogger.Error(err2) - return - } + _, errA := core.ExecuteActions(&rule, lua.LString(callbackArgs)) + if errA != nil { + glogger.GLogger.WithFields(logrus.Fields{ + "topic": "rule/log/" + rule.UUID, + }).Info("RunLuaCallbacks error:", errA) + _, err1 := core.ExecuteFailed(rule.LuaVM, lua.LString(errA.Error())) + if err1 != nil { + glogger.GLogger.Error(err1) + } + } else { + _, err2 := core.ExecuteSuccess(rule.LuaVM) + if err2 != nil { + glogger.GLogger.WithFields(logrus.Fields{ + "topic": "rule/log/" + rule.UUID, + }).Info("RunLuaCallbacks error:", err2) + return } } } diff --git a/engine/load_rule.go b/engine/load_rule.go index ced720a4b..da932da43 100644 --- a/engine/load_rule.go +++ b/engine/load_rule.go @@ -39,23 +39,16 @@ func (e *RuleEngine) LoadRule(r *typex.Rule) error { // Load LoadBuildInLuaLib //-------------------------------------------------------------- LoadBuildInLuaLib(e, r) - glogger.GLogger.Infof("Rule [%v, %v] load successfully", r.Name, r.UUID) - // 绑定输入资源 - for _, inUUId := range r.FromSource { - // 查找输入定义的资源是否存在 - if in := e.GetInEnd(inUUId); in != nil { - (in.BindRules)[r.UUID] = *r - return nil - } + // 查找输入定义的资源是否存在 + if in := e.GetInEnd(r.FromSource); in != nil { + (in.BindRules)[r.UUID] = *r + return nil } - // 绑定设备 - for _, devUUId := range r.FromDevice { - // 查找输入定义的资源是否存在 - if Device := e.GetDevice(devUUId); Device != nil { - // 绑定资源和规则,建立关联关系 - (Device.BindRules)[r.UUID] = *r - } + // 查找输入定义的资源是否存在 + if Device := e.GetDevice(r.FromDevice); Device != nil { + // 绑定资源和规则,建立关联关系 + (Device.BindRules)[r.UUID] = *r } return nil diff --git a/ossupport/rhinoh3_ubuntu18_datetime_ctl_windows.go b/ossupport/rhinoh3_datetime_ctl_windows.go similarity index 58% rename from ossupport/rhinoh3_ubuntu18_datetime_ctl_windows.go rename to ossupport/rhinoh3_datetime_ctl_windows.go index 6197c682c..6a49d8153 100644 --- a/ossupport/rhinoh3_ubuntu18_datetime_ctl_windows.go +++ b/ossupport/rhinoh3_datetime_ctl_windows.go @@ -17,6 +17,9 @@ package ossupport import ( "fmt" + "strings" + "time" + "github.com/hootrhino/wmi" ) @@ -39,8 +42,33 @@ func GetUptime() (string, error) { } if len(result) > 0 { - return result[0].LastBootUpTime, nil + // 20231226170151.500000+480 + wmicTime := parseWinWmicTime(result[0].LastBootUpTime) + Seconds := wmicTime.Abs().Seconds() + hour := int(Seconds / 3600) + minute := int(Seconds/60) % 60 + second := int(Seconds) % 60 + return fmt.Sprintf("%d Hours %02d Minutes %02d Seconds", hour, minute, second), nil } - return "0:0:0", fmt.Errorf("Failed to retrieve system uptime") + return "0 Year 0 Month 0 Days 0 Hours 0 Minutes 0 Seconds", + fmt.Errorf("failed to retrieve system uptime") +} + +/* +* +* 解析ISO时间戳 +* + */ +func parseWinWmicTime(timestamp string) time.Duration { + parts1 := strings.Split(timestamp, "+") + if len(parts1) != 2 { + return 0 + } + //2023 12 26 17 01 51.500000+480 + mainTimestamp, err := time.Parse("20060102150405", parts1[0]) + if err != nil { + return 0 + } + return time.Until(mainTimestamp) } diff --git a/ossupport/rhinoh3_ubuntu18_datetime_ctl_linux.go b/ossupport/rhinoh3_ubuntu18_datetime_ctl_linux.go index ef841ba44..14e8ddc9f 100644 --- a/ossupport/rhinoh3_ubuntu18_datetime_ctl_linux.go +++ b/ossupport/rhinoh3_ubuntu18_datetime_ctl_linux.go @@ -167,7 +167,7 @@ func GetUptime() (string, error) { var info unix.Sysinfo_t if err := unix.Sysinfo(&info); err != nil { - return "0:0:0", err + return "0 Year 0 Month 0 Days 0 Hours 0 Minutes 0 Seconds", err } return formatUptime(int64(info.Uptime)), nil @@ -178,6 +178,5 @@ func formatUptime(uptime int64) string { hours := (uptime % 86400) / 3600 minutes := (uptime % 3600) / 60 seconds := uptime % 60 - - return fmt.Sprintf("%d days, %02d:%02d:%02d", days, hours, minutes, seconds) + return fmt.Sprintf("%d days %d Hours %02d Minutes %02d Seconds", days, hours, minutes, seconds) } diff --git a/test/conf/rulex.ini b/test/conf/rulex.ini index d51ee592b..a22d819a1 100644 --- a/test/conf/rulex.ini +++ b/test/conf/rulex.ini @@ -38,7 +38,7 @@ lua_log_path = rulex-lua-log.txt # # Max data cache size # -max_queue_size = 20971520 +max_queue_size = 102400 # # Max store size, default is 20MB # diff --git a/typex/rule.go b/typex/rule.go index cc64579d0..d3517537f 100644 --- a/typex/rule.go +++ b/typex/rule.go @@ -23,8 +23,8 @@ type Rule struct { Type string `json:"type"` // 脚本类型,目前支持"lua" Status RuleStatus `json:"status"` Name string `json:"name"` - FromSource []string `json:"fromSource"` // 来自数据源 - FromDevice []string `json:"fromDevice"` // 来自设备 + FromSource string `json:"fromSource"` // 来自数据源 + FromDevice string `json:"fromDevice"` // 来自设备 Actions string `json:"actions"` Success string `json:"success"` Failed string `json:"failed"` @@ -36,8 +36,8 @@ func NewLuaRule(e RuleX, uuid string, name string, description string, - fromSource []string, - fromDevice []string, + fromSource string, + fromDevice string, success string, actions string, failed string) *Rule { @@ -58,8 +58,8 @@ func NewRule(e RuleX, uuid string, name string, description string, - fromSource []string, - fromDevice []string, + fromSource string, + fromDevice string, success string, actions string, failed string) *Rule { diff --git a/typex/version.go b/typex/version.go index b901fd69f..baedf85f8 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-22 17:03:28", + ReleaseTime: "2023-12-27 21:27:46", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-40b0767b39d249c +** Version: v0.6.4-1733cef8b0ce5e7 ** Document: https://hootrhino.github.io ` From 2f0c02c617817e5c4b5827ab06e64d1b865d665d Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 29 Dec 2023 10:32:42 +0800 Subject: [PATCH 134/138] dev: add Port to StartRulexApiServer --- component/rulex_api_server/http_api_server.go | 2 +- component/rulex_api_server/server/apiserver.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 9b973b4a9..1097fd2f4 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -188,7 +188,7 @@ func (hs *ApiServerPlugin) Init(config *ini.Section) error { if err := utils.InIMapToStruct(config, &hs.mainConfig); err != nil { return err } - server.StartRulexApiServer(hs.ruleEngine) + server.StartRulexApiServer(hs.ruleEngine, hs.mainConfig.Port) interdb.DB().Exec("VACUUM;") interdb.RegisterModel( diff --git a/component/rulex_api_server/server/apiserver.go b/component/rulex_api_server/server/apiserver.go index 09b756702..67caba4b5 100644 --- a/component/rulex_api_server/server/apiserver.go +++ b/component/rulex_api_server/server/apiserver.go @@ -58,12 +58,12 @@ var err1crash = errors.New("http server crash, try to recovery") * 开启Server * */ -func StartRulexApiServer(ruleEngine typex.RuleX) { +func StartRulexApiServer(ruleEngine typex.RuleX, port int) { gin.SetMode(gin.ReleaseMode) server := RulexApiServer{ ginEngine: gin.New(), ruleEngine: ruleEngine, - config: serverConfig{Port: 2580}, + config: serverConfig{Port: port}, } server.ginEngine.Use(static.Serve("/", WWWRoot(""))) server.ginEngine.Use(Authorize()) From 051034c476c2fc8e620712f4f6118a42637966aa Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 29 Dec 2023 12:45:41 +0800 Subject: [PATCH 135/138] dev: change plugin path to 'plugware' --- component/rulex_api_server/http_api_server.go | 9 +++------ typex/version.go | 4 ++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 1097fd2f4..999c8e101 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -372,14 +372,11 @@ func (hs *ApiServerPlugin) LoadRoute() { // ---------------------------------------------------------------------------------------------- // Plugin // ---------------------------------------------------------------------------------------------- - pluginsApi := server.RouteGroup(server.ContextUrl("/plugins")) + pluginsApi := server.RouteGroup(server.ContextUrl("/plugware")) { pluginsApi.GET(("/"), server.AddRoute(apis.Plugins)) - } - pluginApi := server.RouteGroup(server.ContextUrl("/plugin")) - { - pluginApi.POST(("/service"), server.AddRoute(apis.PluginService)) - pluginApi.GET(("/detail"), server.AddRoute(apis.PluginDetail)) + pluginsApi.POST(("/service"), server.AddRoute(apis.PluginService)) + pluginsApi.GET(("/detail"), server.AddRoute(apis.PluginDetail)) } // diff --git a/typex/version.go b/typex/version.go index baedf85f8..13b3829fe 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-27 21:27:46", + ReleaseTime: "2023-12-29 12:43:21", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-1733cef8b0ce5e7 +** Version: v0.6.4-2f0c02c617817e5 ** Document: https://hootrhino.github.io ` From 49970fe540c38a67ffec8b091ee4fceae1e58bf8 Mon Sep 17 00:00:00 2001 From: wwhai Date: Fri, 29 Dec 2023 13:20:02 +0800 Subject: [PATCH 136/138] dev: change plugin list path --- component/rulex_api_server/http_api_server.go | 2 +- typex/version.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/component/rulex_api_server/http_api_server.go b/component/rulex_api_server/http_api_server.go index 999c8e101..4006bd2ba 100644 --- a/component/rulex_api_server/http_api_server.go +++ b/component/rulex_api_server/http_api_server.go @@ -374,7 +374,7 @@ func (hs *ApiServerPlugin) LoadRoute() { // ---------------------------------------------------------------------------------------------- pluginsApi := server.RouteGroup(server.ContextUrl("/plugware")) { - pluginsApi.GET(("/"), server.AddRoute(apis.Plugins)) + pluginsApi.GET(("/list"), server.AddRoute(apis.Plugins)) pluginsApi.POST(("/service"), server.AddRoute(apis.PluginService)) pluginsApi.GET(("/detail"), server.AddRoute(apis.PluginDetail)) } diff --git a/typex/version.go b/typex/version.go index 13b3829fe..713b9f4a9 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-29 12:43:21", + ReleaseTime: "2023-12-29 13:19:02", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-2f0c02c617817e5 +** Version: v0.6.4-051034c476c2fc8 ** Document: https://hootrhino.github.io ` From cb68b5b9df7ae045db03e5cef711098c9847a578 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 30 Dec 2023 21:04:29 +0800 Subject: [PATCH 137/138] dev: optimize code --- component/rulex_api_server/server/apiserver.go | 4 +++- plugin/icmp_sender/icmp_sender.go | 11 +++++------ typex/version.go | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/component/rulex_api_server/server/apiserver.go b/component/rulex_api_server/server/apiserver.go index 67caba4b5..41582b446 100644 --- a/component/rulex_api_server/server/apiserver.go +++ b/component/rulex_api_server/server/apiserver.go @@ -156,14 +156,16 @@ func (s *RulexApiServer) InitializeGenericOSData() { initStaticModel() } func (s *RulexApiServer) InitializeUnixData() { + glogger.GLogger.Info("Initialize Unix Default Data") } func (s *RulexApiServer) InitializeWindowsData() { + glogger.GLogger.Info("Initialize Windows Default Data") } func (s *RulexApiServer) InitializeEEKITData() { env := os.Getenv("ARCHSUPPORT") if env == "EEKITH3" { - + glogger.GLogger.Info("Initialize Rhino EEKIT Pi Default Data") } } diff --git a/plugin/icmp_sender/icmp_sender.go b/plugin/icmp_sender/icmp_sender.go index 5a8628450..0947eb0b2 100644 --- a/plugin/icmp_sender/icmp_sender.go +++ b/plugin/icmp_sender/icmp_sender.go @@ -84,16 +84,15 @@ func (icmp *ICMPSender) Service(arg typex.ServiceArg) typex.ServiceResult { for i := 0; i < 5; i++ { switch ip := tt[0].(type) { case string: - if Duration, err := pingQ(ip, 2000*time.Millisecond); err != nil { + if Duration, err := pingQ(ip, 1000*time.Millisecond); err != nil { glogger.GLogger.WithFields(Fields).Info(fmt.Sprintf( - "[Count:%d] Ping Error:%s", i, - err.Error())) + "[Count:%d] Ping Error:%s", i, err.Error())) } else { glogger.GLogger.WithFields(Fields).Info(fmt.Sprintf( - "[Count:%d] Ping Reply From %s: time=%v ms TTL=128", i, - tt, Duration)) + "[Count:%d] Ping Reply From %s: time=%v ms TTL=128", i, tt, Duration)) } - time.Sleep(1 * time.Second) + // 300毫秒 + time.Sleep(100 * time.Millisecond) } } diff --git a/typex/version.go b/typex/version.go index 713b9f4a9..db279a540 100644 --- a/typex/version.go +++ b/typex/version.go @@ -14,10 +14,10 @@ type Version struct { var DefaultVersion = Version{ Product: "COMMON", Version: `v0.6.4`, - ReleaseTime: "2023-12-29 13:19:02", + ReleaseTime: "2023-12-30 19:09:35", } var Banner = ` ** Welcome to RULEX framework world <'_'> -** Version: v0.6.4-051034c476c2fc8 +** Version: v0.6.4-49970fe540c38a6 ** Document: https://hootrhino.github.io ` From f5d6732214935c3a5c9ae36b9107296741e63652 Mon Sep 17 00:00:00 2001 From: wwhai Date: Sat, 30 Dec 2023 22:39:58 +0800 Subject: [PATCH 138/138] dev: enhance version format --- Makefile | 21 ++++++++++--------- component/rulex_api_server/apis/system_api.go | 4 ++-- .../service/hw_intrerface_service.go | 4 ++-- engine/engine.go | 6 +++--- gen_info.sh | 8 +++---- main.go | 16 +++++++------- plugin/net_discover/net_boardcast.go | 2 +- typex/rulex.go | 2 +- typex/version.go | 12 +++++------ 9 files changed, 38 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index cd30cc159..2103bd47c 100644 --- a/Makefile +++ b/Makefile @@ -8,11 +8,12 @@ ip=$(shell hostname -I) memory=$(shell free -m | awk 'NR==2{printf "%.2fGB\n", $$2/1000}') disk=$(shell df -h | awk '$$NF=="/"{printf "%s\n", $$2}') arch=$(uname -m) - +version=$(shell git describe --tags $(git rev-list --tags --max-count=1)) +shortVersion=-X 'github.com/hootrhino/rulex/typex.MainVersion=$(version)' .PHONY: all all: @echo "\e[41m[*] Distro \e[0m: \e[36m ${distro} \e[0m" - @echo "\e[41m[*] Arch \e[0m: \e[36m ${arch} \e[0m" + @echo "\e[41m[*] Arch \e[0m: \e[36m ${arch} \e[0m" @echo "\e[41m[*] Kernel \e[0m: \e[36m ${kernel} \e[0m" @echo "\e[41m[*] Cpu \e[0m: \e[36m ${cpu} \e[0m" @echo "\e[41m[*] Memory \e[0m: \e[36m ${memory} \e[0m" @@ -26,51 +27,51 @@ all: build: CGO_ENABLED=1 GOOS=linux go generate - go build -v -ldflags "-s -w" -o ${APP} + go build -ldflags "$(shortVersion) -s -w" -v -o ${APP} .PHONY: x64linux x64linux: go generate CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=gcc\ - go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-x64linux + go build -ldflags "$(shortVersion) -s -w" -v -o ${APP}-x64linux .PHONY: windows windows: GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc\ - go build -ldflags "-s -w" -o ${APP}-windows.exe + go build -ldflags "$(shortVersion) -s -w" -o ${APP}-windows.exe .PHONY: arm32 arm32: go generate CGO_ENABLED=1 GOOS=linux GOARCH=arm CC=arm-linux-gnueabi-gcc\ - go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-arm32linux + go build -ldflags "$(shortVersion) -s -w -linkmode external -extldflags -static" -o ${APP}-arm32linux .PHONY: arm64 arm64: go generate CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=aarch64-linux-gnu-gcc\ - go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-arm64linux + go build -ldflags "$(shortVersion) -s -w -linkmode external -extldflags -static" -o ${APP}-arm64linux .PHONY: mips32 mips32: go generate # sudo apt-get install gcc-mips-linux-gnu GOOS=linux GOARCH=mips CGO_ENABLED=1 CC=mips-linux-gnu-gcc\ - go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-mips32linux + go build -ldflags "$(shortVersion) -s -w -linkmode external -extldflags -static" -o ${APP}-mips32linux .PHONY: mips64 mips64: go generate # sudo apt-get install gcc-mips-linux-gnu GOOS=linux GOARCH=mips64 CGO_ENABLED=1 CC=mips-linux-gnu-gcc\ - go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-mips64linux + go build -ldflags "$(shortVersion) -s -w -linkmode external -extldflags -static" -o ${APP}-mips64linux .PHONY: mipsel mipsle: go generate # sudo apt-get install gcc-mipsel-linux-gnu GOOS=linux GOARCH=mipsle CGO_ENABLED=1 GOMIPS=softfloat CC=mipsel-linux-gnu-gcc\ - go build -ldflags "-s -w -linkmode external -extldflags -static" -o ${APP}-mipslelinux + go build -ldflags "$(shortVersion) -s -w -linkmode external -extldflags -static" -o ${APP}-mipslelinux .PHONY: release release: diff --git a/component/rulex_api_server/apis/system_api.go b/component/rulex_api_server/apis/system_api.go index f3804fc8c..0549ff10c 100644 --- a/component/rulex_api_server/apis/system_api.go +++ b/component/rulex_api_server/apis/system_api.go @@ -110,13 +110,13 @@ func System(c *gin.Context, ruleEngine typex.RuleX) { // ip, err0 := utils.HostNameI() memPercent, _ := service.GetMemPercent() hardWareInfo := map[string]interface{}{ - "version": ruleEngine.Version().Version, + "version": typex.MainVersion, "diskInfo": calculateDiskInfo(diskInfo), "memPercent": memPercent, "cpuPercent": calculateCpuPercent(cpuPercent), "osArch": ruleEngine.Version().Arch, "osDist": ruleEngine.Version().Dist, - "product": typex.DefaultVersion.Product, + "product": typex.DefaultVersionInfo.Product, "startedAt": __StartedAt, "osUpTime": func() string { result, err := ossupport.GetUptime() diff --git a/component/rulex_api_server/service/hw_intrerface_service.go b/component/rulex_api_server/service/hw_intrerface_service.go index 6ca3e318f..ebe8a456f 100644 --- a/component/rulex_api_server/service/hw_intrerface_service.go +++ b/component/rulex_api_server/service/hw_intrerface_service.go @@ -109,7 +109,7 @@ func InitHwPortConfig() error { Description: portName, } // 兼容代码,识别H3网关的参数 - if typex.DefaultVersion.Product == "EEKIIH3" { + if typex.DefaultVersionInfo.Product == "EEKIIH3" { if portName == "/dev/ttyS1" { Port.Alias = "RS485接口1(A1B1)" Port.Name = "RS4851(A1B1)" @@ -153,7 +153,7 @@ func GetOsPort() []string { } List := []string{} for _, port := range ports { - if typex.DefaultVersion.Product == "EEKIIH3" { + if typex.DefaultVersionInfo.Product == "EEKIIH3" { // H3的下列串口被系统占用 if utils.SContains([]string{ "/dev/ttyS0", diff --git a/engine/engine.go b/engine/engine.go index 61f99d509..a1a313a8c 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -143,8 +143,8 @@ func (e *RuleEngine) AllPlugins() *sync.Map { return e.Plugins } -func (e *RuleEngine) Version() typex.Version { - return typex.DefaultVersion +func (e *RuleEngine) Version() typex.VersionInfo { + return typex.DefaultVersionInfo } func (e *RuleEngine) GetConfig() *typex.RulexConfig { @@ -401,7 +401,7 @@ func (e *RuleEngine) SnapshotDump() string { runtime.ReadMemStats(&m) system := map[string]interface{}{ - "version": e.Version().Version, + "version": typex.MainVersion, "diskInfo": int(diskInfo.UsedPercent), "system": utils.BToMb(m.Sys), "alloc": utils.BToMb(m.Alloc), diff --git a/gen_info.sh b/gen_info.sh index f9e26797e..5868b0abb 100644 --- a/gen_info.sh +++ b/gen_info.sh @@ -11,17 +11,17 @@ cat >./typex/version.go < -** Version: v0.6.4-49970fe540c38a6 +** Version: v0.6.5-cb68b5b9df7ae04 ** Document: https://hootrhino.github.io `