Compare commits

...

3 Commits

Author SHA1 Message Date
Xuwznln
4529af1fcd 使用rattler-build进行构建测试 2025-08-01 15:06:44 +08:00
Xuwznln
b6a23ef120 更新环境变量级别 2025-08-01 12:41:36 +08:00
Xuwznln
fab90f0b46 更新启动逻辑 2025-08-01 12:12:30 +08:00
11 changed files with 291 additions and 189 deletions

View File

@@ -2,16 +2,21 @@ name: Multi-Platform Conda Build
on: on:
push: push:
branches: [ main, dev ] branches: [main, dev]
tags: [ 'v*' ] tags: ['v*']
pull_request: pull_request:
branches: [ main, dev ] branches: [main, dev]
workflow_dispatch: workflow_dispatch:
inputs: inputs:
platforms: platforms:
description: '选择构建平台 (逗号分隔): linux-64, osx-64, osx-arm64, win-64' description: '选择构建平台 (逗号分隔): linux-64, osx-64, osx-arm64, win-64'
required: false required: false
default: 'osx-arm64' default: 'osx-arm64'
upload_to_anaconda:
description: '是否上传到Anaconda.org'
required: false
default: false
type: boolean
jobs: jobs:
build: build:
@@ -19,18 +24,18 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: ubuntu-latest - os: ubuntu-latest
platform: linux-64 platform: linux-64
env_file: unilabos-linux-64.yaml env_file: unilabos-linux-64.yaml
- os: macos-13 # Intel - os: macos-13 # Intel
platform: osx-64 platform: osx-64
env_file: unilabos-osx-64.yaml env_file: unilabos-osx-64.yaml
- os: macos-latest # ARM64 - os: macos-latest # ARM64
platform: osx-arm64 platform: osx-arm64
env_file: unilabos-osx-arm64.yaml env_file: unilabos-osx-arm64.yaml
- os: windows-latest - os: windows-latest
platform: win-64 platform: win-64
env_file: unilabos-win64.yaml env_file: unilabos-win64.yaml
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
@@ -39,94 +44,112 @@ jobs:
shell: bash -l {0} shell: bash -l {0}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Check if platform should be built - name: Check if platform should be built
id: should_build id: should_build
run: | run: |
if [[ "${{ github.event_name }}" != "workflow_dispatch" ]]; then if [[ "${{ github.event_name }}" != "workflow_dispatch" ]]; then
echo "should_build=true" >> $GITHUB_OUTPUT echo "should_build=true" >> $GITHUB_OUTPUT
elif [[ -z "${{ github.event.inputs.platforms }}" ]]; then elif [[ -z "${{ github.event.inputs.platforms }}" ]]; then
echo "should_build=true" >> $GITHUB_OUTPUT echo "should_build=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.event.inputs.platforms }}" == *"${{ matrix.platform }}"* ]]; then elif [[ "${{ github.event.inputs.platforms }}" == *"${{ matrix.platform }}"* ]]; then
echo "should_build=true" >> $GITHUB_OUTPUT echo "should_build=true" >> $GITHUB_OUTPUT
else else
echo "should_build=false" >> $GITHUB_OUTPUT echo "should_build=false" >> $GITHUB_OUTPUT
fi fi
- name: Setup Miniconda - name: Setup Miniconda
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
uses: conda-incubator/setup-miniconda@v3 uses: conda-incubator/setup-miniconda@v3
with: with:
miniconda-version: "latest" miniconda-version: 'latest'
channels: conda-forge,robostack-staging,defaults channels: conda-forge,robostack-staging,defaults
channel-priority: strict channel-priority: strict
activate-environment: build-env activate-environment: build-env
auto-activate-base: false auto-activate-base: false
auto-update-conda: false auto-update-conda: false
show-channel-urls: true show-channel-urls: true
- name: Install boa and build tools - name: Install rattler-build and anaconda-client
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
run: | run: |
conda install -c conda-forge boa conda-build conda install -c conda-forge rattler-build anaconda-client
- name: Show environment info - name: Show environment info
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
run: | run: |
conda info conda info
conda list | grep -E "(boa|conda-build)" conda list | grep -E "(rattler-build|anaconda-client)"
echo "Platform: ${{ matrix.platform }}" echo "Platform: ${{ matrix.platform }}"
echo "OS: ${{ matrix.os }}" echo "OS: ${{ matrix.os }}"
- name: Build conda package - name: Build conda package
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
run: | run: |
if [[ "${{ matrix.platform }}" == "osx-arm64" ]]; then if [[ "${{ matrix.platform }}" == "osx-arm64" ]]; then
boa build -m ./recipes/conda_build_config.yaml -m ./recipes/macos_sdk_config.yaml ./recipes/ros-humble-unilabos-msgs rattler-build build -m ./recipes/conda_build_config.yaml -m ./recipes/macos_sdk_config.yaml ./recipes/msgs
else else
boa build -m ./recipes/conda_build_config.yaml ./recipes/ros-humble-unilabos-msgs rattler-build build -m ./recipes/conda_build_config.yaml ./recipes/msgs
fi fi
- name: List built packages - name: List built packages
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
run: | run: |
echo "Built packages in conda-bld:" echo "Built packages in output directory:"
find $CONDA_PREFIX/conda-bld -name "*.tar.bz2" | head -10 find ./recipes/msgs/output -name "*.conda" | head -10
ls -la $CONDA_PREFIX/conda-bld/${{ matrix.platform }}/ || echo "${{ matrix.platform }} directory not found" ls -la ./recipes/msgs/output/${{ matrix.platform }}/ || echo "${{ matrix.platform }} directory not found"
ls -la $CONDA_PREFIX/conda-bld/noarch/ || echo "noarch directory not found" ls -la ./recipes/msgs/output/noarch/ || echo "noarch directory not found"
echo "CONDA_PREFIX: $CONDA_PREFIX" echo "Output directory structure:"
echo "Full path would be: $CONDA_PREFIX/conda-bld/**/*.tar.bz2" find ./recipes/msgs/output -type f -name "*.conda"
- name: Prepare artifacts for upload - name: Prepare artifacts for upload
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
run: | run: |
mkdir -p ${{ runner.temp }}/conda-packages mkdir -p ${{ runner.temp }}/conda-packages
find $CONDA_PREFIX/conda-bld -name "*.tar.bz2" -exec cp {} ${{ runner.temp }}/conda-packages/ \; find ./recipes/msgs/output -name "*.conda" -exec cp {} ${{ runner.temp }}/conda-packages/ \;
echo "Copied files to temp directory:" echo "Copied files to temp directory:"
ls -la ${{ runner.temp }}/conda-packages/ ls -la ${{ runner.temp }}/conda-packages/
- name: Upload conda package artifacts - name: Upload conda package artifacts
if: steps.should_build.outputs.should_build == 'true' if: steps.should_build.outputs.should_build == 'true'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: conda-package-${{ matrix.platform }} name: conda-package-${{ matrix.platform }}
path: ${{ runner.temp }}/conda-packages path: ${{ runner.temp }}/conda-packages
if-no-files-found: warn if-no-files-found: warn
retention-days: 30 retention-days: 30
- name: Create release assets (on tags) - name: Login to Anaconda
if: steps.should_build.outputs.should_build == 'true' && startsWith(github.ref, 'refs/tags/') if: steps.should_build.outputs.should_build == 'true' && (github.event.inputs.upload_to_anaconda == 'true' || startsWith(github.ref, 'refs/tags/'))
run: | run: |
mkdir -p release-assets anaconda login --username ${{ secrets.ANACONDA_USERNAME }} --password ${{ secrets.ANACONDA_PASSWORD }}
find $CONDA_PREFIX/conda-bld -name "*.tar.bz2" -exec cp {} release-assets/ \;
- name: Upload to release - name: Upload to Anaconda.org
if: steps.should_build.outputs.should_build == 'true' && startsWith(github.ref, 'refs/tags/') if: steps.should_build.outputs.should_build == 'true' && (github.event.inputs.upload_to_anaconda == 'true' || startsWith(github.ref, 'refs/tags/'))
uses: softprops/action-gh-release@v1 run: |
with: for package in $(find ./recipes/msgs/output -name "*.conda"); do
files: release-assets/* echo "Uploading $package to Anaconda.org..."
draft: false anaconda upload --user ${{ secrets.ANACONDA_ORG }} --force "$package"
prerelease: false done
- name: Logout from Anaconda
if: always() && steps.should_build.outputs.should_build == 'true' && (github.event.inputs.upload_to_anaconda == 'true' || startsWith(github.ref, 'refs/tags/'))
run: |
anaconda logout || true
- name: Create release assets (on tags)
if: steps.should_build.outputs.should_build == 'true' && startsWith(github.ref, 'refs/tags/')
run: |
mkdir -p release-assets
find ./recipes/msgs/output -name "*.conda" -exec cp {} release-assets/ \;
- name: Upload to release
if: steps.should_build.outputs.should_build == 'true' && startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v1
with:
files: release-assets/*
draft: false
prerelease: false

View File

@@ -34,8 +34,32 @@ cmake ^
-DCMAKE_OBJECT_PATH_MAX=255 ^ -DCMAKE_OBJECT_PATH_MAX=255 ^
-DPYTHON_INSTALL_DIR=%SP_DIR_FORWARDSLASHES% ^ -DPYTHON_INSTALL_DIR=%SP_DIR_FORWARDSLASHES% ^
--compile-no-warning-as-error ^ --compile-no-warning-as-error ^
%SRC_DIR%\%PKG_NAME%\src\work %SRC_DIR%\src
if errorlevel 1 exit 1 if errorlevel 1 exit 1
set "infile=%SRC_DIR%\build\cmake_install.cmake"
set "tmpfile=%infile%.tmp"
rem 模式串
set "pattern=echo %PYTHON%"
> "%tmpfile%" (
for /f "usebackq delims=" %%L in ("%infile%") do (
set "line=%%L"
rem 把 pattern 从 line 里“删除”,看看结果是否变化
set "test=!line:%pattern%=!"
if "!test!" neq "!line!" (
rem 含有 echo %PYTHON%,对整行做 \→\\ 全局替换
echo !line:\=\\!
) else (
rem 不含,原样输出
echo !line!
)
)
)
rem 用 tmp 覆盖原文件
move /Y "%tmpfile%" "%infile%" > nul
cmake --build . --config Release --target install cmake --build . --config Release --target install
if errorlevel 1 exit 1 if errorlevel 1 exit 1

View File

@@ -66,6 +66,6 @@ cmake \
-DBUILD_TESTING=OFF \ -DBUILD_TESTING=OFF \
-DCMAKE_OSX_DEPLOYMENT_TARGET=$OSX_DEPLOYMENT_TARGET \ -DCMAKE_OSX_DEPLOYMENT_TARGET=$OSX_DEPLOYMENT_TARGET \
--compile-no-warning-as-error \ --compile-no-warning-as-error \
$SRC_DIR/$PKG_NAME/src/work $SRC_DIR/src
cmake --build . --config Release --target install cmake --build . --config Release --target install

76
recipes/msgs/recipe.yaml Normal file
View File

@@ -0,0 +1,76 @@
package:
name: ros-humble-unilabos-msgs
version: 0.10.1
source:
path: ../../unilabos_msgs
target_directory: src
build:
script:
- if: win
then:
- copy %RECIPE_DIR%\bld_ament_cmake.bat %SRC_DIR%
- call %SRC_DIR%\bld_ament_cmake.bat
- if: unix
then:
- cp $RECIPE_DIR/build_ament_cmake.sh $SRC_DIR
- bash $SRC_DIR/build_ament_cmake.sh
about:
repository: https://github.com/dptech-corp/Uni-Lab-OS
license: BSD-3-Clause
description: "ros-humble-unilabos-msgs is a package that provides message definitions for Uni-Lab-OS."
requirements:
build:
- if: build_platform != target_platform
then:
- pkg-config
- python =3.11.11
- cross-python_${{ target_platform }}
- numpy
- ${{ compiler('cxx') }}
- ${{ compiler('c') }}
- if: linux and x86_64
then:
- sysroot_linux-64 2.17
- ninja
- setuptools
- cython
- cmake
- if: unix
then:
- make
- coreutils
- if: osx
then:
- tapi
- if: win
then:
- vs2022_win-64
host:
- numpy
- pip
- if: build_platform == target_platform
then:
- pkg-config
- robostack-staging::ros-humble-action-msgs
- robostack-staging::ros-humble-ament-cmake
- robostack-staging::ros-humble-ament-lint-auto
- robostack-staging::ros-humble-ament-lint-common
- robostack-staging::ros-humble-ros-environment
- robostack-staging::ros-humble-ros-workspace
- robostack-staging::ros-humble-rosidl-default-generators
- robostack-staging::ros-humble-std-msgs
- robostack-staging::ros-humble-geometry-msgs
- robostack-staging::ros2-distro-mutex=0.6
run:
- robostack-staging::ros-humble-action-msgs
- robostack-staging::ros-humble-ros-workspace
- robostack-staging::ros-humble-rosidl-default-runtime
- robostack-staging::ros-humble-std-msgs
- robostack-staging::ros-humble-geometry-msgs
- robostack-staging::ros2-distro-mutex=0.6
- if: osx and x86_64
then:
- __osx >= {{ MACOSX_DEPLOYMENT_TARGET|default('10.14') }}

View File

@@ -1,61 +0,0 @@
package:
name: ros-humble-unilabos-msgs
version: 0.10.1
source:
path: ../../unilabos_msgs
folder: ros-humble-unilabos-msgs/src/work
build:
script:
sel(win): bld_ament_cmake.bat
sel(unix): build_ament_cmake.sh
number: 5
about:
home: https://www.ros.org/
license: BSD-3-Clause
summary: |
Robot Operating System
extra:
recipe-maintainers:
- ros-forge
requirements:
build:
- "{{ compiler('cxx') }}"
- "{{ compiler('c') }}"
- sel(linux64): sysroot_linux-64 2.17
- ninja
- setuptools
- sel(unix): make
- sel(unix): coreutils
- sel(osx): tapi
- sel(build_platform != target_platform): pkg-config
- cmake
- cython
- sel(win): vs2022_win-64
- sel(build_platform != target_platform): python
- sel(build_platform != target_platform): cross-python_{{ target_platform }}
- sel(build_platform != target_platform): numpy
host:
- numpy
- pip
- sel(build_platform == target_platform): pkg-config
- robostack-staging::ros-humble-action-msgs
- robostack-staging::ros-humble-ament-cmake
- robostack-staging::ros-humble-ament-lint-auto
- robostack-staging::ros-humble-ament-lint-common
- robostack-staging::ros-humble-ros-environment
- robostack-staging::ros-humble-ros-workspace
- robostack-staging::ros-humble-rosidl-default-generators
- robostack-staging::ros-humble-std-msgs
- robostack-staging::ros-humble-geometry-msgs
- robostack-staging::ros2-distro-mutex=0.6.*
run:
- robostack-staging::ros-humble-action-msgs
- robostack-staging::ros-humble-ros-workspace
- robostack-staging::ros-humble-rosidl-default-runtime
- robostack-staging::ros-humble-std-msgs
- robostack-staging::ros-humble-geometry-msgs
# - robostack-staging::ros2-distro-mutex=0.6.*
- sel(osx and x86_64): __osx >={{ MACOSX_DEPLOYMENT_TARGET|default('10.14') }}

View File

@@ -43,10 +43,11 @@ def convert_argv_dashes_to_underscores(args: argparse.ArgumentParser):
for i, arg in enumerate(sys.argv): for i, arg in enumerate(sys.argv):
for option_string in option_strings: for option_string in option_strings:
if arg.startswith(option_string): if arg.startswith(option_string):
new_arg = arg[:2] + arg[2:len(option_string)].replace("-", "_") + arg[len(option_string):] new_arg = arg[:2] + arg[2 : len(option_string)].replace("-", "_") + arg[len(option_string) :]
sys.argv[i] = new_arg sys.argv[i] = new_arg
break break
def parse_args(): def parse_args():
"""解析命令行参数""" """解析命令行参数"""
parser = argparse.ArgumentParser(description="Start Uni-Lab Edge server.") parser = argparse.ArgumentParser(description="Start Uni-Lab Edge server.")
@@ -128,6 +129,13 @@ def parse_args():
default="", default="",
help="实验室唯一ID也可通过环境变量 UNILABOS.MQCONFIG.LABID 设置或传入--config设置", help="实验室唯一ID也可通过环境变量 UNILABOS.MQCONFIG.LABID 设置或传入--config设置",
) )
parser.add_argument(
"--loglevel",
type=str,
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
default="INFO",
help="设置日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL),默认为 INFO",
)
return parser return parser
@@ -140,29 +148,40 @@ def main():
# 加载配置文件优先加载config然后从env读取 # 加载配置文件优先加载config然后从env读取
config_path = args_dict.get("config") config_path = args_dict.get("config")
working_dir = os.path.abspath(os.path.join(os.getcwd(), "unilabos_data")) if os.getcwd().endswith("unilabos_data"):
if not config_path and (not os.path.exists(working_dir) or not os.path.exists(os.path.join(working_dir, "local_config.py"))): working_dir = os.path.abspath(os.getcwd())
print_status(f"当前未指定config路径非第一次使用请通过 --config 传入 local_config.py 文件路径", "info") else:
print_status(f"您是否为第一次使用?并将当前文件路径 {working_dir} 作为工作目录? (Y/n)", "info") working_dir = os.path.abspath(os.path.join(os.getcwd(), "unilabos_data"))
if args_dict.get("working_dir"):
working_dir = args_dict.get("working_dir")
if config_path and not os.path.exists(config_path):
config_path = os.path.join(working_dir, "local_config.py")
if not os.path.exists(config_path):
print_status(
f"当前工作目录 {working_dir} 未找到local_config.py请通过 --config 传入 local_config.py 文件路径",
"error",
)
os._exit(1)
elif os.path.exists(working_dir) and os.path.exists(os.path.join(working_dir, "local_config.py")):
config_path = os.path.join(working_dir, "local_config.py")
elif not config_path and (
not os.path.exists(working_dir) or not os.path.exists(os.path.join(working_dir, "local_config.py"))
):
print_status(f"未指定config路径可通过 --config 传入 local_config.py 文件路径", "info")
print_status(f"您是否为第一次使用?并将当前路径 {working_dir} 作为工作目录? (Y/n)", "info")
if input() != "n": if input() != "n":
os.makedirs(working_dir, exist_ok=True) os.makedirs(working_dir, exist_ok=True)
config_path = os.path.join(working_dir, "local_config.py") config_path = os.path.join(working_dir, "local_config.py")
shutil.copy(os.path.join(os.path.dirname(os.path.dirname(__file__)), "config", "example_config.py"), config_path) shutil.copy(
os.path.join(os.path.dirname(os.path.dirname(__file__)), "config", "example_config.py"), config_path
)
print_status(f"已创建 local_config.py 路径: {config_path}", "info") print_status(f"已创建 local_config.py 路径: {config_path}", "info")
print_status(f"请在文件夹中配置lab_id放入下载的CA.crt、lab.crt、lab.key重新启动本程序", "info") print_status(f"请在文件夹中配置lab_id放入下载的CA.crt、lab.crt、lab.key重新启动本程序", "info")
os._exit(1) os._exit(1)
else: else:
os._exit(1) os._exit(1)
else:
working_dir = args_dict.get("working_dir") or os.path.abspath(os.path.join(os.getcwd(), "unilabos_data"))
if working_dir:
if config_path and not os.path.exists(config_path):
config_path = os.path.join(working_dir, "local_config.py")
if not os.path.exists(config_path):
print_status(f"当前工作目录 {working_dir} 未找到local_config.py请通过 --config 传入 local_config.py 文件路径", "error")
os._exit(1)
print_status(f"当前工作目录为 {working_dir}", "info")
# 加载配置文件 # 加载配置文件
print_status(f"当前工作目录为 {working_dir}", "info")
load_config_from_file(config_path, args_dict["labid"]) load_config_from_file(config_path, args_dict["labid"])
# 设置BasicConfig参数 # 设置BasicConfig参数
@@ -204,10 +223,11 @@ def main():
print_status("联网获取设备加载文件成功", "info") print_status("联网获取设备加载文件成功", "info")
graph, data = read_node_link_json(request_startup_json) graph, data = read_node_link_json(request_startup_json)
else: else:
if args_dict["graph"].endswith(".json"): file_path = args_dict["graph"]
graph, data = read_node_link_json(args_dict["graph"]) if file_path.endswith(".json"):
graph, data = read_node_link_json(file_path)
else: else:
graph, data = read_graphml(args_dict["graph"]) graph, data = read_graphml(file_path)
import unilabos.resources.graphio as graph_res import unilabos.resources.graphio as graph_res
graph_res.physical_setup_graph = graph graph_res.physical_setup_graph = graph

View File

@@ -4,11 +4,12 @@ HTTP客户端模块
提供与远程服务器通信的客户端功能只有host需要用 提供与远程服务器通信的客户端功能只有host需要用
""" """
import json import json
import os
from typing import List, Dict, Any, Optional from typing import List, Dict, Any, Optional
import requests import requests
from unilabos.utils.log import info from unilabos.utils.log import info
from unilabos.config.config import MQConfig, HTTPConfig from unilabos.config.config import MQConfig, HTTPConfig, BasicConfig
from unilabos.utils import logger from unilabos.utils import logger
@@ -189,7 +190,7 @@ class HTTPClient:
logger.error(f"请求启动配置失败: {response.status_code}, {response.text}") logger.error(f"请求启动配置失败: {response.status_code}, {response.text}")
else: else:
try: try:
with open("startup_config.json", "w", encoding="utf-8") as f: with open(os.path.join(BasicConfig.working_dir, "startup_config.json"), "w", encoding="utf-8") as f:
f.write(response.text) f.write(response.text)
target_dict = json.loads(response.text) target_dict = json.loads(response.text)
if "data" in target_dict: if "data" in target_dict:

View File

@@ -163,12 +163,12 @@ def _update_config_from_env():
def load_config(config_path=None, override_labid=None): def load_config(config_path=None, override_labid=None):
# 如果提供了配置文件路径,从该文件导入配置 # 如果提供了配置文件路径,从该文件导入配置
if config_path: if config_path:
_update_config_from_env() # 允许config_path被env设定后读取 env_config_path = os.environ.get("UNILABOS.BASICCONFIG.CONFIG_PATH")
config_path = env_config_path if env_config_path else config_path
BasicConfig.config_path = os.path.abspath(os.path.dirname(config_path)) BasicConfig.config_path = os.path.abspath(os.path.dirname(config_path))
if not os.path.exists(config_path): if not os.path.exists(config_path):
logger.error(f"[ENV] 配置文件 {config_path} 不存在") logger.error(f"[ENV] 配置文件 {config_path} 不存在")
exit(1) exit(1)
try: try:
module_name = "lab_" + os.path.basename(config_path).replace(".py", "") module_name = "lab_" + os.path.basename(config_path).replace(".py", "")
spec = importlib.util.spec_from_file_location(module_name, config_path) spec = importlib.util.spec_from_file_location(module_name, config_path)
@@ -179,6 +179,7 @@ def load_config(config_path=None, override_labid=None):
spec.loader.exec_module(module) # type: ignore spec.loader.exec_module(module) # type: ignore
_update_config_from_module(module, override_labid) _update_config_from_module(module, override_labid)
logger.info(f"[ENV] 配置文件 {config_path} 加载成功") logger.info(f"[ENV] 配置文件 {config_path} 加载成功")
_update_config_from_env()
except Exception as e: except Exception as e:
logger.error(f"[ENV] 加载配置文件 {config_path} 失败") logger.error(f"[ENV] 加载配置文件 {config_path} 失败")
traceback.print_exc() traceback.print_exc()

View File

@@ -8,9 +8,9 @@ class MQConfig:
broker_url = "" broker_url = ""
port = 1883 port = 1883
ca_file = "CA.crt" ca_file = "./CA.crt"
cert_file = "lab.crt" cert_file = "./lab.crt"
key_file = "lab.key" key_file = "./lab.key"
# HTTP配置 # HTTP配置
class HTTPConfig: class HTTPConfig:

View File

@@ -144,11 +144,29 @@ class ColoredFormatter(logging.Formatter):
# 配置日志处理器 # 配置日志处理器
def configure_logger(): def configure_logger(loglevel=None):
"""配置日志记录器""" """配置日志记录器
Args:
loglevel: 日志级别,可以是字符串('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
或logging模块的常量如logging.DEBUG
"""
# 获取根日志记录器 # 获取根日志记录器
root_logger = logging.getLogger() root_logger = logging.getLogger()
root_logger.setLevel(logging.DEBUG) # 修改为DEBUG以显示所有级别
# 设置日志级别
if loglevel is not None:
if isinstance(loglevel, str):
# 将字符串转换为logging级别
numeric_level = getattr(logging, loglevel.upper(), None)
if not isinstance(numeric_level, int):
print(f"警告: 无效的日志级别 '{loglevel}',使用默认级别 DEBUG")
numeric_level = logging.DEBUG
else:
numeric_level = loglevel
root_logger.setLevel(numeric_level)
else:
root_logger.setLevel(logging.DEBUG) # 默认级别
# 移除已存在的处理器 # 移除已存在的处理器
for handler in root_logger.handlers[:]: for handler in root_logger.handlers[:]:
@@ -156,7 +174,7 @@ def configure_logger():
# 创建控制台处理器 # 创建控制台处理器
console_handler = logging.StreamHandler() console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG) # 修改为DEBUG以显示所有级别 console_handler.setLevel(root_logger.level) # 使用与根记录器相同的级别
# 使用自定义的颜色格式化器 # 使用自定义的颜色格式化器
color_formatter = ColoredFormatter() color_formatter = ColoredFormatter()

View File

@@ -2,7 +2,7 @@
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3"> <package format="3">
<name>unilabos_msgs</name> <name>unilabos_msgs</name>
<version>0.0.5</version> <version>0.10.1</version>
<description>ROS2 Messages package for unilabos devices</description> <description>ROS2 Messages package for unilabos devices</description>
<maintainer email="changjh@pku.edu.cn">Junhan Chang</maintainer> <maintainer email="changjh@pku.edu.cn">Junhan Chang</maintainer>
<license>MIT</license> <license>MIT</license>