jiateng_ws/utils/config_loader.py

343 lines
12 KiB
Python
Raw Permalink Normal View History

2025-06-07 10:45:09 +08:00
import os
import json
import logging
class ConfigLoader:
"""配置加载器,用于加载和管理应用配置"""
_instance = None
@classmethod
def get_instance(cls):
"""获取单例实例"""
if cls._instance is None:
cls._instance = ConfigLoader()
return cls._instance
def __init__(self):
"""初始化配置加载器"""
self.config = {}
self.config_file = os.path.join('config', 'app_config.json')
# 创建配置目录(如果不存在)
os.makedirs('config', exist_ok=True)
# 加载配置
self.load_config()
def load_config(self):
"""加载配置文件"""
try:
if os.path.exists(self.config_file):
with open(self.config_file, 'r', encoding='utf-8') as f:
self.config = json.load(f)
logging.info(f"已加载配置文件: {self.config_file}")
2025-06-13 17:14:03 +08:00
# 检查并升级配置文件结构(兼容旧版本的配置)
self._upgrade_config_if_needed()
2025-06-07 10:45:09 +08:00
else:
# 创建默认配置
self.config = {
"app": {
"name": "腾智微丝产线包装系统",
"version": "1.0.0",
"features": {
"enable_serial_ports": False,
2025-06-13 17:14:03 +08:00
"enable_keyboard_listener": False,
"enable_camera": False
},
"mode": "standalone" # 默认为单机模式
2025-06-07 10:45:09 +08:00
},
"database": {
2025-06-13 17:14:03 +08:00
"current": "sqlite",
"sources": {
"sqlite": {
"path": "db/jtDB.db",
"description": "默认SQLite数据库"
},
"postgresql": {
"host": "localhost",
"port": "5432",
"user": "postgres",
"password": "",
"name": "jtDB",
"description": ""
},
"mysql": {
"host": "localhost",
"port": "3306",
"user": "root",
"password": "",
"name": "jtDB",
"description": ""
}
}
},
"camera": {
"enabled": False,
"default_exposure": 20000,
"default_gain": 10,
"default_framerate": 30
},
"modbus": {
"host": "localhost",
"port": "5020"
},
"serial": {
"keyboard": {
"trigger_key": "Key.page_up",
"enabled": False
}
2025-06-07 10:45:09 +08:00
}
}
# 保存默认配置
self.save_config()
logging.info(f"已创建默认配置文件: {self.config_file}")
except Exception as e:
logging.error(f"加载配置文件失败: {e}")
# 使用默认配置
self.config = {
"app": {
"name": "腾智微丝产线包装系统",
"version": "1.0.0",
"features": {
"enable_serial_ports": False,
2025-06-13 17:14:03 +08:00
"enable_keyboard_listener": False,
"enable_camera": False
},
"mode": "standalone" # 默认为单机模式
2025-06-13 17:14:03 +08:00
},
"database": {
"current": "sqlite",
"sources": {
"sqlite": {
"path": "db/jtDB.db",
"description": "默认SQLite数据库"
}
2025-06-07 10:45:09 +08:00
}
}
}
2025-06-13 17:14:03 +08:00
def _upgrade_config_if_needed(self):
"""升级配置文件结构(兼容旧版本的配置)"""
try:
# 检查数据库配置是否需要升级
if 'database' in self.config:
db_config = self.config['database']
# 旧版本配置结构检查
if 'type' in db_config and 'sources' not in db_config:
logging.info("检测到旧版本的数据库配置,正在升级...")
# 获取旧配置
db_type = db_config.get('type', 'sqlite')
# 创建新的配置结构
new_db_config = {
"default": db_type,
"sources": {}
}
# 转移旧配置到新结构
if db_type == 'sqlite':
new_db_config['sources']['sqlite'] = {
"path": db_config.get('path', 'db/jtDB.db'),
"description": "从旧版本升级的SQLite数据库"
}
else:
new_db_config['sources'][db_type] = {
"host": db_config.get('host', 'localhost'),
"port": db_config.get('port', '5432' if db_type == 'postgresql' else '3306'),
"user": db_config.get('user', ''),
"password": db_config.get('password', ''),
"name": db_config.get('name', 'jtDB'),
"description": f"从旧版本升级的{db_type}数据库"
}
# 确保至少有一个sqlite配置
if 'sqlite' not in new_db_config['sources']:
new_db_config['sources']['sqlite'] = {
"path": "db/jtDB.db",
"description": "默认SQLite数据库"
}
# 更新配置
self.config['database'] = new_db_config
self.save_config()
logging.info("数据库配置已成功升级")
# 将current改为default
if 'current' in db_config and 'default' not in db_config:
logging.info("将数据库配置中的'current'改为'default'...")
db_config['default'] = db_config.pop('current')
self.save_config()
# 将pgsql改为postgresql
if 'sources' in db_config and 'pgsql' in db_config['sources'] and 'postgresql' not in db_config['sources']:
logging.info("将数据库配置中的'pgsql'改为'postgresql'...")
db_config['sources']['postgresql'] = db_config['sources'].pop('pgsql')
# 如果默认值是pgsql也更新
if db_config.get('default') == 'pgsql':
db_config['default'] = 'postgresql'
self.save_config()
# 检查并添加运行模式配置
if 'app' in self.config and 'mode' not in self.config['app']:
logging.info("添加运行模式配置...")
self.config['app']['mode'] = 'standalone'
self.save_config()
2025-06-13 17:14:03 +08:00
except Exception as e:
logging.error(f"升级配置文件结构失败: {e}")
2025-06-07 10:45:09 +08:00
def save_config(self):
"""保存配置到文件"""
try:
with open(self.config_file, 'w', encoding='utf-8') as f:
json.dump(self.config, f, indent=4, ensure_ascii=False)
logging.info(f"已保存配置文件: {self.config_file}")
return True
except Exception as e:
logging.error(f"保存配置文件失败: {e}")
return False
def get_value(self, key_path, default=None):
"""
获取配置值
Args:
key_path: 配置键路径例如 "app.features.enable_serial_ports"
default: 默认值如果配置项不存在则返回此值
Returns:
配置值或默认值
"""
keys = key_path.split('.')
value = self.config
try:
for key in keys:
value = value[key]
return value
except (KeyError, TypeError):
return default
def set_value(self, key_path, value):
"""
设置配置值
Args:
key_path: 配置键路径例如 "app.features.enable_serial_ports"
value: 要设置的值
Returns:
bool: 是否设置成功
"""
keys = key_path.split('.')
config = self.config
# 遍历路径中的所有键,除了最后一个
for key in keys[:-1]:
if key not in config:
config[key] = {}
config = config[key]
# 设置最后一个键的值
config[keys[-1]] = value
# 保存配置
return self.save_config()
def get_app_mode(self):
"""
获取应用运行模式
Returns:
str: 'standalone'(单机模式) 'api'(接口模式)
"""
return self.get_value('app.mode', 'standalone')
def set_app_mode(self, mode):
"""
设置应用运行模式
Args:
mode: 'standalone'(单机模式) 'api'(接口模式)
Returns:
bool: 是否设置成功
"""
if mode not in ['standalone', 'api']:
logging.error(f"无效的运行模式: {mode},必须是 'standalone''api'")
return False
return self.set_value('app.mode', mode)
def is_standalone_mode(self):
"""
检查是否为单机模式
Returns:
bool: True表示单机模式False表示接口模式
"""
return self.get_app_mode() == 'standalone'
def is_api_mode(self):
"""
检查是否为接口模式
Returns:
bool: True表示接口模式False表示单机模式
"""
return self.get_app_mode() == 'api'
def get_config(self, key):
"""
获取serial配置下的指定配置
Args:
key: 配置键例如'mdz', 'cz'
Returns:
dict: 配置数据
"""
serial_config = self.config.get('serial', {})
return serial_config.get(key, {})
def set_config(self, key, config_data):
"""
设置serial配置下的指定配置
Args:
key: 配置键例如'mdz', 'cz'
config_data: 配置数据
Returns:
bool: 是否设置成功
"""
if 'serial' not in self.config:
self.config['serial'] = {}
2025-06-13 17:14:03 +08:00
self.config['serial'][key] = config_data
return self.save_config()
2025-06-13 17:14:03 +08:00
def get_database_config(self, db_type=None):
"""
获取数据库配置
2025-06-13 17:14:03 +08:00
Args:
db_type: 数据库类型如果为None则返回当前使用的数据库配置
2025-06-13 17:14:03 +08:00
Returns:
dict: 数据库配置
"""
db_config = self.config.get('database', {})
db_sources = db_config.get('sources', {})
2025-06-13 17:14:03 +08:00
# 如果未指定数据库类型,则使用当前配置的数据库类型
if db_type is None:
db_type = db_config.get('current', 'sqlite')
2025-06-13 17:14:03 +08:00
# 返回指定类型的数据库配置
return db_sources.get(db_type, {})