Browse Source

111111

master
dongchangxi 2 weeks ago
parent
commit
b7843917ff
  1. 51
      factory_sliceing/README_BUILD.md
  2. 12
      factory_sliceing/auto_sliceing_operate/main_begin_sliceing.py
  3. 10
      factory_sliceing/auto_sliceing_operate/utils/click_soft_button.py
  4. 18
      factory_sliceing/auto_sliceing_operate/utils/exe_operate.py
  5. 31
      factory_sliceing/build_exe.py
  6. 40
      factory_sliceing/config.example.toml
  7. 44
      factory_sliceing/config.toml
  8. 4
      factory_sliceing/download_batch_data/main_download_batch_data_and_trans.py
  9. 22
      factory_sliceing/main.py
  10. 2
      factory_sliceing/utils/__init__.py
  11. 155
      factory_sliceing/utils/config.py

51
factory_sliceing/README_BUILD.md

@ -38,19 +38,58 @@ pyinstaller --name=factory_sliceing --onefile --console --clean main.py
打包完成后,exe 文件位于 `dist/factory_sliceing.exe` 打包完成后,exe 文件位于 `dist/factory_sliceing.exe`
使用方法: ### 配置文件
**重要**: 打包后的 exe 需要配置文件 `config.toml` 才能正常运行。
- **配置文件位置**: 必须放在 **exe 同级目录**(与 `factory_sliceing.exe` 同一目录)
- **自动复制**: 打包脚本会自动将 `config.toml` 复制到 `dist/` 目录
- **如果配置文件不存在**: 打包脚本会尝试复制 `config.example.toml` 作为模板,你需要根据实际情况修改
配置文件示例:
```toml
[redis]
host = "your-redis-host"
password = "your-redis-password"
port = 6379
db = 6
[oss]
access_key_id = "your-access-key-id"
access_key_secret = "your-access-key-secret"
endpoint = "oss-cn-shanghai.aliyuncs.com"
bucket = "your-bucket-name"
[api]
base_url = "https://mp.api.suwa3d.com"
env = "prod"
[work]
default_dir = "C:\\work" # 默认工作目录
```
### 使用方法
```bash ```bash
factory_sliceing.exe <command> <work_dir> factory_sliceing.exe <command> [work_dir]
``` ```
可用命令: 可用命令:
- `batch_dwonload` - 批量下载 - `batch_download` - 批量下载
- `begin_sliceing` - 开始切片 - `begin_sliceing` - 开始切片
- `download_zip` - 下载压缩包 - `download_zip` - 下载压缩包
参数说明:
- `command`: 必需,要执行的命令
- `work_dir`: 可选,工作目录。如果未提供,将从配置文件读取 `work.default_dir`,如果配置文件中也没有,则使用 exe 所在目录
示例: 示例:
```bash ```bash
# 使用命令行参数指定工作目录
factory_sliceing.exe begin_sliceing C:\work\data factory_sliceing.exe begin_sliceing C:\work\data
# 使用配置文件中的默认工作目录
factory_sliceing.exe begin_sliceing
``` ```
## 注意事项 ## 注意事项
@ -92,3 +131,9 @@ factory_sliceing.exe begin_sliceing C:\work\data
- 如果仍然提示文件不存在,检查 `build_exe.py` 中的 `--add-data` 参数是否正确 - 如果仍然提示文件不存在,检查 `build_exe.py` 中的 `--add-data` 参数是否正确
- 文件会被放在 `_MEIPASS/utils/``_MEIPASS/download_batch_data/utils/` 目录下 - 文件会被放在 `_MEIPASS/utils/``_MEIPASS/download_batch_data/utils/` 目录下
### 问题:配置文件不存在或读取失败
- **配置文件位置**: 必须放在 exe 同级目录(与 `factory_sliceing.exe` 同一目录)
- 打包脚本会自动复制 `config.toml``dist/` 目录
- 如果配置文件不存在,程序会使用默认值或提示错误
- 可以复制 `config.example.toml` 并重命名为 `config.toml`,然后根据实际情况修改

12
factory_sliceing/auto_sliceing_operate/main_begin_sliceing.py

@ -8,12 +8,12 @@ import os
from .utils.request import requestApiToUpdateSliceStatusComplate from .utils.request import requestApiToUpdateSliceStatusComplate
#"C:/test/10192_small_No4/data" #"C:/test/10192_small_No4/data"
def BeginSliceing(batchId,machineId, folderPath): def BeginSliceing(batchId,machineId, folderPath,data):
# 打开3d切片软件 # 打开3d切片软件
start_exe() start_exe(data)
time.sleep(1) time.sleep(5)
#点击确认按钮 #点击确认按钮
click_confirm() # click_confirm()
#先打开导入文件的弹框 #先打开导入文件的弹框
clickFileIMportShow() clickFileIMportShow()
time.sleep(1) time.sleep(1)
@ -29,7 +29,7 @@ def BeginSliceing(batchId,machineId, folderPath):
log("切片结束") log("切片结束")
time.sleep(5) time.sleep(5)
#切片完成之后,将切片文件打包成zip文件,上传到OSS,并且请求api 更新批次状态为切片完成 #切片完成之后,将切片文件打包成zip文件,上传到OSS,并且请求api 更新批次状态为切片完成
requestApiToUpdateSliceStatusComplate(batchId, 0) # requestApiToUpdateSliceStatusComplate(batchId, 0)
# sadd 插入对应的队列 # sadd 插入对应的队列
r = redisClient() r = redisClient()
r.sadd('pb:begin_print_machine_'+machineId, batchId) r.sadd('pb:begin_print_machine_'+machineId, batchId)
@ -62,6 +62,6 @@ def main(work_dir=None):
batchId = data.split('_')[0] #批次ID batchId = data.split('_')[0] #批次ID
# machineType = data.split('_')[1] #机型类型 # machineType = data.split('_')[1] #机型类型
machineId = data.split('_')[2].replace('No', '') #机器ID machineId = data.split('_')[2].replace('No', '') #机器ID
BeginSliceing(batchId,machineId,folderPath) BeginSliceing(batchId,machineId,folderPath,data)
time.sleep(10) time.sleep(10)

10
factory_sliceing/auto_sliceing_operate/utils/click_soft_button.py

@ -1,7 +1,7 @@
import uiautomation as auto import uiautomation as auto
from utils.config import cfg
softName = cfg('exe.soft_name', None)
softName = "赛纳3D打印控制系统 V1.4.3.2"
# 遍历所有控件 找到 # 遍历所有控件 找到
def findAndClick(control, depth=0,index=1): def findAndClick(control, depth=0,index=1):
@ -71,12 +71,18 @@ def findAndClick(control, depth=0,index=1):
# 点击导入文件按钮 # 点击导入文件按钮
def clickFileIMportShow(): def clickFileIMportShow():
if softName is None:
print(f"错误:软件名称未配置")
exit(1)
control = auto.WindowControl(searchDepth=1, Name=softName) control = auto.WindowControl(searchDepth=1, Name=softName)
clickRes = findAndClick(control,index=1) clickRes = findAndClick(control,index=1)
return clickRes return clickRes
# 点击开始切片按钮 # 点击开始切片按钮
def clickBegingSlice(): def clickBegingSlice():
if softName is None:
print(f"错误:软件名称未配置")
exit(1)
control = auto.WindowControl(searchDepth=1, Name=softName) control = auto.WindowControl(searchDepth=1, Name=softName)
clickRes = findAndClick(control,index=2) clickRes = findAndClick(control,index=2)
return clickRes return clickRes

18
factory_sliceing/auto_sliceing_operate/utils/exe_operate.py

@ -3,9 +3,21 @@ import os
import subprocess import subprocess
import time import time
import uiautomation as auto import uiautomation as auto
exe_path = r"C:\Users\Administrator\Desktop\排版软件\NormalTek.ThreeDPrinter.UI.exe" from utils.config import cfg
# exe_path = cfg('exe.small_exe', None)
def start_exe(): # if exe_path is None:
# print(f"错误:exe_path 未配置")
# exit(1)
def start_exe(data):
exe_path = None
if "small" in data:
exe_path = cfg('exe.small_exe', None)
elif "big" in data:
exe_path = cfg('exe.big_exe', None)
else:
print(f"错误:机型类型未配置")
exit(1)
try: try:
# 检查文件是否存在 # 检查文件是否存在
if not os.path.exists(exe_path): if not os.path.exists(exe_path):

31
factory_sliceing/build_exe.py

@ -134,9 +134,36 @@ def build_exe():
print(f"生成的 exe 文件: {exe_path}") print(f"生成的 exe 文件: {exe_path}")
print(f"文件大小: {file_size:.2f} MB") print(f"文件大小: {file_size:.2f} MB")
print() print()
# 复制配置文件到 dist 目录(如果存在)
config_file = os.path.join(current_dir, 'config.toml')
dist_config = os.path.join(current_dir, 'dist', 'config.toml')
if os.path.exists(config_file):
try:
shutil.copy2(config_file, dist_config)
print(f"配置文件已复制到: {dist_config}")
except Exception as e:
print(f"警告: 复制配置文件失败: {e}")
print(f"请手动将 config.toml 复制到 exe 同级目录: {os.path.dirname(exe_path)}")
else:
# 如果 config.toml 不存在,尝试复制示例文件
example_config = os.path.join(current_dir, 'config.example.toml')
if os.path.exists(example_config):
try:
shutil.copy2(example_config, dist_config)
print(f"配置文件示例已复制到: {dist_config}")
print("请根据实际情况修改配置文件")
except Exception as e:
print(f"警告: 复制配置文件示例失败: {e}")
else:
print("提示: 请将 config.toml 放在 exe 同级目录")
print()
print("使用方法:") print("使用方法:")
print(" factory_sliceing.exe <command> <work_dir>") print(" factory_sliceing.exe <command> [work_dir]")
print(" 可用命令: batch_dwonload | begin_sliceing | download_zip") print(" 可用命令: batch_download | begin_sliceing | download_zip")
print()
print("注意: 配置文件 config.toml 需要放在 exe 同级目录")
return True return True
else: else:
print("打包失败!") print("打包失败!")

40
factory_sliceing/config.example.toml

@ -0,0 +1,40 @@
# Factory Sliceing 配置文件示例
# 复制此文件为 config.toml 并根据实际情况修改配置
# Redis 配置
[redis]
host = "your-redis-host"
password = "your-redis-password"
port = 6379
db = 6
socket_timeout = 30
socket_connect_timeout = 10
socket_keepalive = true
health_check_interval = 30
# Redis 重试配置
[redis.retry]
retry_interval = 5
max_retry_interval = 60
# OSS 配置
[oss]
access_key_id = "your-access-key-id"
access_key_secret = "your-access-key-secret"
endpoint = "oss-cn-shanghai.aliyuncs.com"
bucket = "your-bucket-name"
# API 配置
[api]
base_url = "https://mp.api.suwa3d.com"
env = "prod" # prod 或 dev
# dev_url = "http://mp.api.dev.com" # 开发环境 URL(可选)
# 工作目录配置
[work]
default_dir = "" # 默认工作目录,为空则使用脚本所在目录
# 日志配置
[log]
level = "INFO" # DEBUG, INFO, WARNING, ERROR

44
factory_sliceing/config.toml

@ -0,0 +1,44 @@
# Factory Sliceing 配置文件
# Redis 配置
[redis]
host = "mp.api.suwa3d.com"
password = "kcV2000"
port = 6379
db = 6
socket_timeout = 30
socket_connect_timeout = 10
socket_keepalive = true
health_check_interval = 30
# Redis 重试配置
[redis.retry]
retry_interval = 5
max_retry_interval = 60
# OSS 配置
[oss]
access_key_id = "LTAI5tSReWm8hz7dSYxxth8f"
access_key_secret = "8ywTDF9upPAtvgXtLKALY2iMYHIxdS"
endpoint = "oss-cn-shanghai.aliyuncs.com"
bucket = "suwa3d-securedata"
# API 配置
[api]
base_url = "https://mp.api.suwa3d.com"
env = "prod" # prod 或 dev
# 工作目录配置
[work]
default_dir = "C://work" # 默认工作目录,为空则使用脚本所在目录
# 日志配置
[log]
level = "INFO" # DEBUG, INFO, WARNING, ERROR
#切片软件的执行路径
[exe]
soft_name = ""
small_exe = ""
big_exe = "C:\Users\Administrator\print_factory_type_setting\software\小机型 切片软件\切片软件V1.4.3.6_2\切片软件V1.4.3.6_2\NormalTek.ThreeDPrinter.UI.exe"

4
factory_sliceing/download_batch_data/main_download_batch_data_and_trans.py

@ -47,9 +47,9 @@ def step1(versionId):
return False return False
#塞入切片的队列 ,SADD 插入 , {batchId}_{machineType}_No{machineId} #塞入切片的队列 ,SADD 插入 , {batchId}_{machineType}_No{machineId}
machineType = "" machineType = ""
if machineInfo["machine_type"] == '1': if str(machineInfo["machine_type"]) == '1':
machineType = 'small' machineType = 'small'
elif machineInfo["machine_type"] == '2': elif str(machineInfo["machine_type"]) == '2':
machineType = 'big' machineType = 'big'
keyValue = f'{versionId}_{machineType}_No{machineInfo["id"]}' keyValue = f'{versionId}_{machineType}_No{machineInfo["id"]}'
r = redisClient() r = redisClient()

22
factory_sliceing/main.py

@ -1,20 +1,24 @@
import os,sys import sys
import os
from auto_sliceing_operate import main_begin_sliceing from auto_sliceing_operate import main_begin_sliceing
from download_batch_data import main_download_batch_data_and_trans from download_batch_data import main_download_batch_data_and_trans
from auto_sliceing_operate import main_download_zip from auto_sliceing_operate import main_download_zip
from utils.config import cfg, get_work_dir
if __name__ == '__main__': if __name__ == '__main__':
# 根据参数决定执行哪个模块 # 根据参数决定执行哪个模块
# 命令映射表:命令名 -> 处理函数 # 命令映射表:命令名 -> 处理函数
command_handlers = { command_handlers = {
'batch_dwonload': main_download_batch_data_and_trans.main, 'batch_download': main_download_batch_data_and_trans.main,
'begin_sliceing': main_begin_sliceing.main, 'begin_sliceing': main_begin_sliceing.main,
'download_zip': main_download_zip.main, 'download_zip': main_download_zip.main,
} }
# 检查参数数量 # 检查参数数量
if len(sys.argv) < 2: if len(sys.argv) < 2:
print('Usage: python main.py <command> <work_dir>') print('Usage: python main.py <command> [work_dir]')
print('可用命令:', ' | '.join(command_handlers.keys())) print('可用命令:', ' | '.join(command_handlers.keys()))
print('\n注意: work_dir 参数可选,如果未提供将从配置文件读取默认值')
sys.exit(1) sys.exit(1)
command = sys.argv[1] command = sys.argv[1]
@ -25,12 +29,14 @@ if __name__ == '__main__':
print('可用命令:', ' | '.join(command_handlers.keys())) print('可用命令:', ' | '.join(command_handlers.keys()))
sys.exit(1) sys.exit(1)
# 检查是否提供了 work_dir 参数 # 获取工作目录:优先使用命令行参数,其次使用配置文件,最后使用当前目录
if len(sys.argv) < 3:
print(f'Usage: python main.py {command} <work_dir>')
sys.exit(1)
work_dir = sys.argv[2] work_dir = sys.argv[2]
# 打印配置信息(可选,用于调试)
if cfg('log.level', 'INFO') == 'DEBUG':
print(f'配置信息:')
print(f' - API URL: {cfg("api.base_url", "未配置")}')
print(f' - Redis Host: {cfg("redis.host", "未配置")}')
print(f' - 工作目录: {work_dir}')
# 执行对应的处理函数 # 执行对应的处理函数
command_handlers[command](work_dir=work_dir) command_handlers[command](work_dir=work_dir)

2
factory_sliceing/utils/__init__.py

@ -0,0 +1,2 @@
# utils 模块

155
factory_sliceing/utils/config.py

@ -0,0 +1,155 @@
"""
配置文件读取工具
支持从 config.toml 文件中读取配置信息
"""
import toml
import os
import sys
def get_config_path():
"""
获取配置文件路径
查找顺序
1. 如果是打包后的 exe优先查找 exe 同级目录的 config.toml
2. 开发环境查找 factory_sliceing 目录下的 config.toml
3. 当前目录下的 config.toml
"""
# 判断是否在 PyInstaller 打包后的环境中
if getattr(sys, 'frozen', False):
# 打包后的 exe 环境
# sys.executable 是 exe 文件的完整路径
exe_dir = os.path.dirname(os.path.abspath(sys.executable))
config_path = os.path.join(exe_dir, 'config.toml')
# 如果 exe 同级目录存在配置文件,直接返回
if os.path.exists(config_path):
return config_path
# 如果不存在,也返回这个路径(让调用者知道应该在哪里创建配置文件)
return config_path
# 开发环境:查找 factory_sliceing 目录下的 config.toml
current_dir = os.path.dirname(os.path.abspath(__file__))
# 向上查找 factory_sliceing 目录
factory_sliceing_dir = os.path.dirname(current_dir)
config_path = os.path.join(factory_sliceing_dir, 'config.toml')
# 如果文件存在,返回
if os.path.exists(config_path):
return config_path
# 如果不存在,尝试当前目录
config_path = os.path.join(current_dir, 'config.toml')
if os.path.exists(config_path):
return config_path
# 都不存在,返回 factory_sliceing 目录下的路径(作为默认路径)
return os.path.join(factory_sliceing_dir, 'config.toml')
def cfg(key_name, default=None):
"""
读取配置文件中的值
:param key_name: 配置项的键名支持点号分隔的嵌套键 "redis.host" "redis.retry.interval"
:param default: 如果配置项不存在返回的默认值
:return: 配置项的值如果不存在且未提供默认值则返回 None
"""
try:
config_path = get_config_path()
if not os.path.exists(config_path):
print(f"警告: 配置文件不存在,路径: {config_path}")
return default
with open(config_path, 'r', encoding='utf-8') as f:
config = toml.load(f)
# 处理嵌套键名,如 "redis.host"
if "." in key_name:
keys = key_name.split(".")
value = config
for key in keys:
if isinstance(value, dict) and key in value:
value = value[key]
else:
if default is not None:
return default
print(f"配置项 {key_name} 不存在")
return None
return value
else:
# 单层键名
if key_name in config:
return config[key_name]
else:
if default is not None:
return default
print(f"配置项 {key_name} 不存在")
return None
except FileNotFoundError:
print(f"配置文件不存在,路径: {config_path}")
return default
except Exception as e:
print(f"读取配置文件时发生错误: {e}")
return default
def get_redis_config():
"""
获取 Redis 配置字典
:return: Redis 配置字典
"""
return {
'host': cfg('redis.host', 'localhost'),
'password': cfg('redis.password', ''),
'port': cfg('redis.port', 6379),
'db': cfg('redis.db', 0),
'socket_timeout': cfg('redis.socket_timeout', 30),
'socket_connect_timeout': cfg('redis.socket_connect_timeout', 10),
'socket_keepalive': cfg('redis.socket_keepalive', True),
'health_check_interval': cfg('redis.health_check_interval', 30)
}
def get_oss_config():
"""
获取 OSS 配置字典
:return: OSS 配置字典
"""
return {
'access_key_id': cfg('oss.access_key_id'),
'access_key_secret': cfg('oss.access_key_secret'),
'endpoint': cfg('oss.endpoint'),
'bucket': cfg('oss.bucket')
}
def get_api_url():
"""
获取 API 基础 URL
:return: API URL 字符串
"""
env = cfg('api.env', 'prod')
base_url = cfg('api.base_url', 'https://mp.api.suwa3d.com')
# 如果环境是 dev,可以覆盖 URL
if env == 'dev':
dev_url = cfg('api.dev_url', 'http://mp.api.dev.com')
return dev_url
return base_url
def get_work_dir():
"""
获取默认工作目录
:return: 工作目录路径如果未配置则返回 None
"""
return cfg('work.default_dir', None)
def get_exe_path(typeExe):
return cfg('exe.'+typeExe+'_exe', None)
Loading…
Cancel
Save