mirror of
https://github.com/dptech-corp/Uni-Lab-OS.git
synced 2025-12-17 21:11:12 +00:00
Dev Sync (#18)
* Update README and MQTTClient for installation instructions and code improvements * feat: 支持local_config启动 add: 增加对crt path的说明,为传入config.py的相对路径 move: web component * add: registry description * feat: node_info_update srv fix: OTDeck cant create * close #12 feat: slave node registry * feat: show machine name fix: host node registry not uploaded * feat: add hplc registry * feat: add hplc registry * fix: hplc status typo * fix: devices/ * fix: device.class possible null * fix: HPLC additions with online service * fix: slave mode spin not working * fix: slave mode spin not working * feat: 多ProtocolNode 允许子设备ID相同 feat: 上报发现的ActionClient feat: Host重启动,通过discover机制要求slaveNode重新注册,实现信息及时上报 * feat: 支持env设置config --------- Co-authored-by: Harvey Que <Q-Query@outlook.com>
This commit is contained in:
@@ -12,7 +12,7 @@ ilabos_dir = os.path.dirname(os.path.dirname(current_dir))
|
|||||||
if ilabos_dir not in sys.path:
|
if ilabos_dir not in sys.path:
|
||||||
sys.path.append(ilabos_dir)
|
sys.path.append(ilabos_dir)
|
||||||
|
|
||||||
from unilabos.config.config import load_config, BasicConfig
|
from unilabos.config.config import load_config, BasicConfig, _update_config_from_env
|
||||||
from unilabos.utils.banner_print import print_status, print_unilab_banner
|
from unilabos.utils.banner_print import print_status, print_unilab_banner
|
||||||
|
|
||||||
|
|
||||||
@@ -80,8 +80,10 @@ def main():
|
|||||||
args = parse_args()
|
args = parse_args()
|
||||||
args_dict = vars(args)
|
args_dict = vars(args)
|
||||||
|
|
||||||
# 加载配置文件 - 这里保持最先加载配置的逻辑
|
# 加载配置文件,优先加载config,然后从env读取
|
||||||
config_path = args_dict.get("config")
|
config_path = args_dict.get("config")
|
||||||
|
if config_path is None:
|
||||||
|
config_path = os.environ.get("UNILABOS.BASICCONFIG.CONFIG_PATH", None)
|
||||||
if config_path:
|
if config_path:
|
||||||
if not os.path.exists(config_path):
|
if not os.path.exists(config_path):
|
||||||
print_status(f"配置文件 {config_path} 不存在", "error")
|
print_status(f"配置文件 {config_path} 不存在", "error")
|
||||||
|
|||||||
@@ -101,26 +101,79 @@ def _update_config_from_module(module):
|
|||||||
logger.warning("Skipping key file loading, key_file is empty")
|
logger.warning("Skipping key file loading, key_file is empty")
|
||||||
|
|
||||||
|
|
||||||
|
def _update_config_from_env():
|
||||||
|
prefix = "UNILABOS."
|
||||||
|
for env_key, env_value in os.environ.items():
|
||||||
|
if not env_key.startswith(prefix):
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
key_path = env_key[len(prefix):] # Remove UNILAB_ prefix
|
||||||
|
class_field = key_path.upper().split(".", 1)
|
||||||
|
if len(class_field) != 2:
|
||||||
|
logger.warning(f"[ENV] 环境变量格式不正确:{env_key}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
class_key, field_key = class_field
|
||||||
|
# 遍历 globals 找匹配类(不区分大小写)
|
||||||
|
matched_cls = None
|
||||||
|
for name, obj in globals().items():
|
||||||
|
if name.upper() == class_key and isinstance(obj, type):
|
||||||
|
matched_cls = obj
|
||||||
|
break
|
||||||
|
|
||||||
|
if matched_cls is None:
|
||||||
|
logger.warning(f"[ENV] 未找到类:{class_key}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 查找类属性(不区分大小写)
|
||||||
|
matched_field = None
|
||||||
|
for attr in dir(matched_cls):
|
||||||
|
if attr.upper() == field_key:
|
||||||
|
matched_field = attr
|
||||||
|
break
|
||||||
|
|
||||||
|
if matched_field is None:
|
||||||
|
logger.warning(f"[ENV] 类 {matched_cls.__name__} 中未找到字段:{field_key}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
current_value = getattr(matched_cls, matched_field)
|
||||||
|
attr_type = type(current_value)
|
||||||
|
if attr_type == bool:
|
||||||
|
value = env_value.lower() in ("true", "1", "yes")
|
||||||
|
elif attr_type == int:
|
||||||
|
value = int(env_value)
|
||||||
|
elif attr_type == float:
|
||||||
|
value = float(env_value)
|
||||||
|
else:
|
||||||
|
value = env_value
|
||||||
|
setattr(matched_cls, matched_field, value)
|
||||||
|
logger.info(f"[ENV] 设置 {matched_cls.__name__}.{matched_field} = {value}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"[ENV] 解析环境变量 {env_key} 失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def load_config(config_path=None):
|
def load_config(config_path=None):
|
||||||
# 如果提供了配置文件路径,从该文件导入配置
|
# 如果提供了配置文件路径,从该文件导入配置
|
||||||
if config_path:
|
if config_path:
|
||||||
|
_update_config_from_env() # 允许config_path被env设定后读取
|
||||||
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"配置文件 {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)
|
||||||
if spec is None:
|
if spec is None:
|
||||||
logger.error(f"配置文件 {config_path} 错误")
|
logger.error(f"[ENV] 配置文件 {config_path} 错误")
|
||||||
return
|
return
|
||||||
module = importlib.util.module_from_spec(spec)
|
module = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(module) # type: ignore
|
spec.loader.exec_module(module) # type: ignore
|
||||||
_update_config_from_module(module)
|
_update_config_from_module(module)
|
||||||
logger.info(f"配置文件 {config_path} 加载成功")
|
logger.info(f"[ENV] 配置文件 {config_path} 加载成功")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"加载配置文件 {config_path} 失败: {e}")
|
logger.error(f"[ENV] 加载配置文件 {config_path} 失败")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user