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
|
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
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
"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()
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
# 保存配置
|
2025-06-12 17:29:35 +08:00
|
|
|
|
return self.save_config()
|
|
|
|
|
|
|
|
|
|
|
|
def get_config(self, key):
|
|
|
|
|
|
"""
|
|
|
|
|
|
获取serial配置下的指定配置
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
key: 配置键,例如'mdz', 'cz'等
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
dict: 配置值,未找到则返回None
|
|
|
|
|
|
"""
|
|
|
|
|
|
if 'serial' not in self.config:
|
|
|
|
|
|
self.config['serial'] = {}
|
|
|
|
|
|
|
|
|
|
|
|
if key not in self.config['serial']:
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
return self.config['serial'][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'] = {}
|
|
|
|
|
|
|
|
|
|
|
|
self.config['serial'][key] = config_data
|
|
|
|
|
|
# 这里不保存配置,等待调用save_config方法时一并保存
|
2025-06-13 17:14:03 +08:00
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
def get_database_config(self, db_type=None):
|
|
|
|
|
|
"""
|
|
|
|
|
|
获取指定类型的数据库配置
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
db_type: 数据库类型,如'sqlite', 'postgresql', 'mysql'等,不指定则使用默认配置
|
|
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
|
dict: 数据库配置
|
|
|
|
|
|
"""
|
|
|
|
|
|
# 如果未指定数据库类型,使用当前设置的类型
|
|
|
|
|
|
if db_type is None:
|
|
|
|
|
|
db_type = self.get_value('database.default', 'sqlite')
|
|
|
|
|
|
|
|
|
|
|
|
# 处理pgsql和postgresql兼容
|
|
|
|
|
|
if db_type == 'pgsql':
|
|
|
|
|
|
db_type = 'postgresql'
|
|
|
|
|
|
|
|
|
|
|
|
# 获取数据库配置
|
|
|
|
|
|
return self.get_value(f'database.sources.{db_type}', {})
|