建模程序 多个定时程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

359 lines
13 KiB

import requests,time
import os,platform
import shutil
import json
import shlex
from .oss_redis import ossClient
from .logs import log
from .oss_func import download_file_with_check, checkFileExists
from .changeFiles import changeObjFile, changeMtlFile
from .small_machine_transform import transform_save
ENV = 'prod'
url = 'https://mp.api.suwa3d.com'
if ENV == 'dev':
url = 'http://mp.api.dev.com'
elif ENV == 'prod':
url = 'https://mp.api.suwa3d.com'
#根据打印ID 获取下载目录
def getDownloadDirByPrintId(printIds):
#调用接口获取下载的路径
api_url = f"{url}/api/printOrder/getInfoByPrintIds"
res = requests.post(api_url,json={"print_ids":printIds})
res = res.json()
print(f"根据打印ID 获取下载目录, res={res}")
if res["code"] == 1000:
return res["data"]
else:
return False
#根据批次id,进行切片中的状态变更
def requestApiToUpdateSliceStatus(versionId,downloadCounts):
api_url = f"{url}/api/printTypeSettingOrder/updateBatchSliceing?batch_id={versionId}&download_counts="+str(downloadCounts)
log(f'发起状态变更请求url={api_url}, versionId={versionId}')
try:
# 添加超时参数,防止请求时间过长
res = requests.post(api_url, timeout=60) # 60秒超时
if res.status_code != 200:
log(f'状态变更请求失败, res={res.text}')
return False
log(f'状态变更请求成功, res={res.text}')
return True
except requests.exceptions.Timeout:
log(f'状态变更请求超时, url={api_url}')
return False
except requests.exceptions.RequestException as e:
log(f'状态变更请求异常, error={str(e)}')
return False
#判断是否上传了 JSON 文件
def checkJsonFileExists(versionId):
log(f"检测文件和图片是否存在, versionId={versionId}")
jsonFilePath = f'batchPrint/{versionId}/{versionId}.json'
#判断oss 上是否存在
jpgFilePath = f'batchPrint/{versionId}/{versionId}.jpg'
if not ossClient().object_exists(jsonFilePath):
log(f'JSON文件不存在: {jsonFilePath}')
return False,False
if not ossClient().object_exists(jpgFilePath):
log(f'JPG文件不存在: {jpgFilePath}')
return False,False
log(f"文件和图片检测成功,存在, versionId={versionId}")
return jsonFilePath,jpgFilePath
#检测本地文件是否存在
def checkLocalFileExists(localFilePath):
if not os.path.exists(localFilePath):
return False
return True
#读取JSON文件内容
def readJsonFile(localFilePath):
with open(localFilePath, 'r', encoding='utf-8') as f:
jsonData = json.load(f)
return jsonData
#根据批次ID,获取批次信息
def getBatchInfo(versionId):
url1 = f"{url}/api/printTypeSettingOrder/getBatchInfoAndPrintMachineInfoByBatchId?batch_id={versionId}"
res = requests.get(url1)
res = res.json()
log(f"获取批次信息和打印机信息, url={url1}, res={res}")
if res["code"] == 1000:
return res["data"]
else:
return False
#下载文件,读取文件内容,并且文件迁移至正确的目录里,不再放在临时目录里
def downloadJsonAndJpgFileAndMoveToCorrectDir(versionId,currentDir):
jsonFilePath,jpgFilePath = checkJsonFileExists(versionId)
if jsonFilePath == False or jpgFilePath == False:
return False,False
#将文件下载到临时目录,待会要判断是否什么类型机型
tempDir = os.path.join(currentDir, 'batchPrint', 'temp', versionId)
if not os.path.exists(tempDir):
os.makedirs(tempDir)
localFilePath = os.path.join(tempDir, f'{versionId}.json')
# 使用带完整性校验的下载方法下载JSON文件
ok = download_file_with_check(jsonFilePath, localFilePath)
if not ok:
log(f"JSON 文件下载失败或不完整, versionId={versionId}")
return False,False
#下载JPG文件
localJpgFilePath = os.path.join(tempDir, f'{versionId}.jpg')
ok = download_file_with_check(jpgFilePath, localJpgFilePath)
if not ok:
log(f"JPG 文件下载失败或不完整, versionId={versionId}")
return False,False
#根据批次ID,获取批次信息和打印机信息
batchMachineInfo = getBatchInfo(versionId)
if not batchMachineInfo:
log(f"获取批次信息和打印机信息失败, versionId={versionId}")
return False,False
# "batch_info": batchInfo,
# "print_machine_info": printMachineInfo,
machineInfo = batchMachineInfo["print_machine_info"]
print(f"machineInfo={machineInfo['id']}")
dirNewName = ""
if str(machineInfo["machine_type"]) == '1':
dirNewName = os.path.join(currentDir, 'batchPrint', versionId + '_small_No'+str(machineInfo['id']))
else:
dirNewName = os.path.join(currentDir, 'batchPrint', versionId + '_big_No'+str(machineInfo['id']))
#判断目录是否存在,存在就删除
if os.path.exists(dirNewName):
shutil.rmtree(dirNewName)
#创建目录
os.makedirs(dirNewName)
#创建json子目录
jsonSubDir = os.path.join(dirNewName, 'json')
if not os.path.exists(jsonSubDir):
os.makedirs(jsonSubDir)
#将数据移动过来
shutil.move(localFilePath, os.path.join(jsonSubDir, '3DPrintLayout.json'))
shutil.move(localJpgFilePath, os.path.join(jsonSubDir, f'{versionId}.jpg'))
#检测文件是否移动成功
if not os.path.exists(os.path.join(jsonSubDir, '3DPrintLayout.json')):
log(f"JSON文件不存在, versionId={versionId}")
return False,False
if not os.path.exists(os.path.join(jsonSubDir, f'{versionId}.jpg')):
log(f"JPG文件不存在, versionId={versionId}")
return False,False
log(f"文件移动成功, versionId={versionId}")
#返回目录路径
return dirNewName,machineInfo
#整合json文件,读取对应的数据,返回数据结构
def getJsonData(dirNewName):
jsonFilePath = os.path.join(dirNewName, 'json', '3DPrintLayout.json')
if not os.path.exists(jsonFilePath):
log(f"JSON文件不存在, dirNewName={dirNewName}")
return False
#读取JSON文件内容
jsonData = readJsonFile(jsonFilePath)
#读取models
models = jsonData.get('models', [])
if not models:
log(f"models不存在, dirNewName={dirNewName}")
return False
listData = []
#遍历models
for model in models:
file_name = model.get('file_name', '')
#分割数据
arrFileName = file_name.split('_')
orderId = arrFileName[0]
pid = arrFileName[1]
printId = arrFileName[2].replace("P", "")
size = arrFileName[3]
counts = arrFileName[4].replace("x", "").replace(".obj", "")
#检测这些数据
if not orderId or not pid or not printId or not size or not counts:
log(f"数据不完整, orderId={orderId}, pid={pid}, printId={printId}, size={size}, counts={counts}")
return False
#创建数据结构
modelInfo = {
"orderId": orderId,
"printId": printId,
"pid": pid,
"size": size,
"counts": counts,
"file_name": file_name,
}
listData.append(modelInfo)
#检测数据长度
if len(listData) == 0:
log(f"数据长度为0, dirNewName={dirNewName}")
return False
#返回数据结构
return listData
# 读取 json 文件,获取 homo_matrix 数据,根据 file_name 获取 homo_matrix 数据
def getHomoMatrixByFileName(dirNewName,fileName):
jsonFilePath = os.path.join(dirNewName, 'json', '3DPrintLayout.json')
if not os.path.exists(jsonFilePath):
log(f"JSON文件不存在, dirNewName={dirNewName}")
return False
#读取JSON文件内容
jsonData = readJsonFile(jsonFilePath)
if not jsonData:
log(f"读取JSON文件内容失败, dirNewName={dirNewName}")
return False
for model in jsonData["models"]:
log(f"jsonData={model['file_name']} == {fileName}")
if model["file_name"] == fileName:
log(f"model={model['transform']}")
return model["transform"]["homo_matrix"]
return False
#json文件进行下载对应的数据 和转换数据,传递目录路径
def downloadDataByOssAndTransformSave(dirNewName,isSmallMachine=False):
listData = getJsonData(dirNewName)
if not listData:
log(f"获取数据失败, dirNewName={dirNewName}")
return False
#遍历数据
arrPrintId = []
arrPrintDataInfo = []
for modelInfo in listData:
arrPrintId.append(modelInfo.get('printId'))
arrPrintDataInfo.append({
"printId": modelInfo.get('printId'),
"file_name": modelInfo.get('file_name'),
})
#调用接口获取下载的路径
arrDownloadPath = getDownloadDirByPrintId(arrPrintId)
if not arrDownloadPath:
log(f"获取下载路径失败, arrPrintId={arrPrintId}")
return False
dirPath = os.path.join(dirNewName, 'data')
if not os.path.exists(dirPath):
os.makedirs(dirPath)
#遍历数据
for v in listData:
info = {}
for tempv in arrDownloadPath:
#print(f"tempv={tempv['print_order_id']} == {v['printId']}")
if str(tempv["print_order_id"]) == str(v["printId"]):
info = tempv
break
#print(f"info={info}")
filePath = info["path"]
pid = info["pid"]
orderId = info["order_id"]
printId = info["print_order_id"]
size = info["real_size"]
counts = info["quantity"]
fileName = v["file_name"]
#判断文件是否存在
ossJpgFilePath = f"{filePath}/printId_{printId}Tex1.jpg"
if not checkFileExists(ossJpgFilePath):
ossJpgFilePath = f"{filePath}/{pid}Tex1.jpg"
localJpgName = os.path.join(f"{orderId}_{pid}Tex1.jpg")
loaclMtlName = os.path.join(f"{orderId}_{pid}.mtl")
localObjName = fileName
arrDownloadFiles = [
{"ossPath": ossJpgFilePath, "localPath": os.path.join(dirPath, localJpgName)},
{"ossPath": f"{filePath}/{pid}.obj", "localPath": os.path.join(dirPath, localObjName)},
{"ossPath": f"{filePath}/{pid}.mtl", "localPath": os.path.join(dirPath, loaclMtlName)},
]
#遍历下载文件
beginTime = time.time()
objsLocal = ""
for objFiles in arrDownloadFiles:
if "F" in fileName:
#判断 mtl 和 jpg 文件是否存在,存在就不在下载了
if "mtl" in objFiles["localPath"] or "jpg" in objFiles["localPath"]:
if os.path.exists(objFiles["localPath"]):
continue
downloadOk = download_file_with_check(objFiles["ossPath"], objFiles["localPath"])
if not downloadOk:
log(f"下载文件失败, ossPath={objFiles["ossPath"]}, localPath={objFiles["localPath"]}")
return False
#下载成功之后要修改文件之间的关联路径
if objFiles["localPath"].endswith(".obj"):
objsLocal = objFiles["localPath"]
changeObjFile(objFiles["localPath"], f"{orderId}_{pid}.mtl")
if objFiles["localPath"].endswith(".mtl"):
changeMtlFile(objFiles["localPath"], f"{orderId}_{pid}Tex1.jpg")
endTime = time.time()
log(f"下载文件和修改文件之间的关联路径 : 耗时{endTime - beginTime}")
#如果是小机台,则要转换数据
if not isSmallMachine:
continue
timeBegin = time.time()
homo_matrix = getHomoMatrixByFileName(dirNewName, localObjName)
if not homo_matrix:
log(f"获取homo_matrix失败, dirNewName={dirNewName}, objsLocal={objsLocal}")
return False
# transform_save(objFiles["localPath"], homo_matrix)
#通过blender 调用执行 python 文件
blender_bin_path = findBpyModule()
# 获取 small_machine_transform.py 的绝对路径
script_dir = os.path.dirname(os.path.abspath(__file__))
transform_script_path = os.path.join(script_dir, 'small_machine_transform.py')
# 将 homo_matrix 转换为 JSON 字符串,并对路径进行转义
homo_matrix_json = json.dumps(homo_matrix)
# 使用 shlex.quote 来安全地转义路径和参数
transform_script_path_quoted = shlex.quote(transform_script_path)
objsLocal_quoted = shlex.quote(objsLocal)
homo_matrix_quoted = shlex.quote(homo_matrix_json)
error = os.system(f"{blender_bin_path} -b -P {transform_script_path_quoted} -- --objPathName={objsLocal_quoted} --trans={homo_matrix_quoted}")
if error != 0:
log(f"调用blender 执行 python 文件失败, error={error}")
return False
log(f"调用blender 执行 python 文件成功, error={error}")
timeEnd = time.time()
log(f"转换数据时间: 耗时{timeEnd - timeBegin}秒 - {objsLocal}")
return True
def findBpyModule():
# 返回 Blender 可执行文件路径(macOS)
blender_bin_path = '/Applications/Blender.app/Contents/MacOS/Blender'
# 判断当前是 windows 还是 macOS
if platform.system() == 'Windows':
blender_bin_path = 'C:\\Program Files\\Blender Foundation\\Blender 4.4\\blender.exe'
else:
blender_bin_path = '/Applications/Blender.app/Contents/MacOS/Blender'
return blender_bin_path