建模程序 多个定时程序
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.
 
 

315 lines
14 KiB

from ctypes import util
import os, oss2, time, redis, requests, shutil, sys, subprocess, json, platform
from PIL import Image, ImageDraw, ImageFont
from retrying import retry
import atexit,platform
if platform.system() == 'Windows':
sys.path.append('e:\\libs\\')
import common
def find_blender_bin_path():
if platform.system() == 'Linux': return 'blender'
base_path = 'C:\\Program Files\\Blender Foundation\\'
if os.path.exists(base_path):
for dir in os.listdir(base_path):
if dir.startswith('Blender'):
blender_bin_path = base_path + dir + '\\blender.exe'
return f'"{blender_bin_path}"'
else:
print('未找到blender安装目录')
exit(1)
@retry(stop_max_attempt_number=10, wait_fixed=3000)
def down_obj_fromoss(pid, print_type=1, order_id=None):
# print_type:// 打印状态 1:正常打印 2:重打 3:加打,4: 样品
print('开始下载obj文件...' , pid)
if not order_id is None:
path = os.path.join(workdir, 'print', f'{pid}_{order_id}')
else:
path = os.path.join(workdir, 'print', pid)
if not os.path.exists(path): os.makedirs(path)
# 根据前缀获取文件列表
prefix = f'objs/print/{pid}/'
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix)
find = False
for file in filelist:
filename = file.key.split('/')[-1]
if filename == '': continue
if filename.endswith(f'{pid}.obj'):
find = True
localfile = os.path.join(path, filename)
res = oss_client.get_object_to_file(file.key, localfile)
print(f'下载文件:{file.key},状态:{res.status}')
if not find and print_type == 3:
for file in os.listdir(path):
if file.endswith('.obj'):
print('找到其他obj文件,采用这个文件来生成需要的尺寸', file)
shutil.copy(os.path.join(path, file), os.path.join(path, f'{pid}.obj'))
find = True
break
if not find:
print('找不到obj文件,异常退出')
sys.exit(1)
# print('下载完成后静默10秒,等待文件写入完成')
# time.sleep(10)
def getPidFromOrderId(orderId):
getPidFromOrderId_url = 'https://mp.api.suwa3d.com/api/printOrder/info'
print(f'{getPidFromOrderId_url}?id={orderId}')
res = requests.get(f'{getPidFromOrderId_url}?id={orderId}')
resCode = res.json()['code']
if int(resCode) != 1000:
return -1
print(res.text)
return res.json()['data']
def detect_obj4print(pid, orderId):
for file in os.listdir(os.path.join(workdir, 'print', f'{pid}_{orderId}')):
if file.endswith('.obj') and 'x' in file:
return True
def make3d4print_task(r):
try:
if r.llen('model:printOrder') == 0:
time.sleep(5)
return
except Exception as e:
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,重新连接')
print(e)
time.sleep(5)
r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
return
orderId = r.lpop('model:printOrder')
if orderId is None: return
orderId = orderId.decode('utf-8')
res = getPidFromOrderId(orderId)
if res == -1:
print("查询打印订单信息失败,重新开启进程")
os.system(f'python auto_convert3d.py')
return
pid = str(res['pid'])
print_type = res['print_type']
digital_type = res['digital_type'] # 0: 只有手办 1: 只有数字模型 2: 手办+数字模型
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成待打印模型 start', )
down_obj_fromoss(pid, print_type, orderId)
# 获取程序运行当前目录
resize_py_path = os.path.join(os.getcwd(), 'blender', 'resize_model.py')
print(f'{blenderbin} -b -P {resize_py_path} -- {orderId}')
os.system(f'{blenderbin} -b -P {resize_py_path} -- {orderId}')
if not detect_obj4print(pid, orderId):
print('obj文件生成异常,退出')
sys.exit(1)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成待打印模型 end')
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 处理鼻孔 start')
if os.path.exists(f'{workdir}/print/{pid}_{orderId}/{pid}Tex1_old.jpg'):
print('已经处理过鼻孔,跳过')
else:
os.system(f'python fix_nose.py {pid}_{orderId}')
oss_client.put_object_from_file(f'objs/print/{pid}/{pid}Tex1.jpg', os.path.join(workdir, 'print', f'{pid}_{orderId}', f'{pid}Tex1.jpg'))
oss_client.put_object_from_file(f'objs/print/{pid}/{pid}Tex1_old.jpg', os.path.join(workdir, 'print', f'{pid}_{orderId}', f'{pid}Tex1_old.jpg'))
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 处理鼻孔 end')
# print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成脚底板二维码 start')
# os.system(f'{blenderbin} -b -P d:\\apps\\blender\\auto_dm.py -- {pid}_{orderId}')
# print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成脚底板二维码 end')
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 上传生成的模型 start')
path = os.path.join(workdir, 'print', f'{pid}_{orderId}')
for file in os.listdir(path):
# 跳过一些不需要上传的文件
if file in [f'{pid}.png', f'{pid}.obj', f'{pid}_decimate.glb', f'{pid}_decimate.obj',f'{pid}.mtl', f'{pid}_decimate.mtl', f'{pid}Tex1_decimate.jpg', f'{pid}_original.obj', f'{pid}_original.mtl']: continue
# oss_client.put_object_from_file(f'objs/print/{pid}/{file}', os.path.join(path, file))
# texture_file = os.path.join(path, f'{pid}Tex1_decimate.jpg')
# if os.path.exists(texture_file):
# img = Image.open(texture_file)
# img = img.resize((int(img.size[0] * 0.5), int(img.size[1] * 0.5)))
# img.save(texture_file, quality=90, optimize=True)
# print('resize texture file to 50% success')
input = os.path.join(path, f'{pid}_decimate.obj')
output = os.path.join(path, f'{pid}_decimate.glb')
# os.system(f'gltfpack -c -i {input} -o {output}')
# oss_client.put_object_from_file(f'glbs/3d/{pid}.glb', output)
shutil.rmtree(path, ignore_errors=True)
print(f'{update_makeprintobj_status_url}?id={orderId}')
if digital_type == 1:
print('只有数字模型,不需要推送手办打印任务,仍有调用接口')
res = requests.get(f'{update_makeprintobj_status_url}?id={orderId}')
print('更新打印状态:', res.text)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 上传生成的模型 end')
def team_check(r):
try:
if r.llen('model:IndependentRepairTeamcheckGLBQueue') == 0:
time.sleep(5)
return
except Exception as e:
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,5秒后重试')
print(e)
time.sleep(5)
r = create_redis_connection()
return
repair_id = r.lpop('model:IndependentRepairTeamcheckGLBQueue')
if repair_id is None: return
repair_id = repair_id.decode('utf-8')
res = requests.get(f'{getRepairInfo_url}?id={repair_id}')
print(f'getRepairInfo_url:{getRepairInfo_url}?id={repair_id}')
print(res.text)
pid = res.json()['data']['pid']
pid = str(pid)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} repair_id:{repair_id} 生成团队审核模型 start model:IndependentRepairTeamcheckGLBQueue', )
down_obj_fromoss(pid)
obj_filename = f'{pid}.obj'
glb_filename = f'{pid}.glb'
print('开始转换obj文件为glb文件...')
os.system(f'gltfpack -c -i {os.path.join(workdir, "print", pid, obj_filename)} -o {os.path.join(workdir, "print", pid, glb_filename)} -vt 16 -vc 16')
#处理封面图
#执行获取obj缩略图
print("执行获取obj全身缩略图脚本")
os.system(f'python d:\\make2\\tools\pic_for_obj\image_rander_small.py -pid {pid} -i D://print/{pid} -o D://print/{pid}')
#判断文件是否存在,存在则上传到oss, 更新数据库内容
if os.path.exists(f'D://print/{pid}/{pid}_pic.png'):
#获取拍照订单的信息,从中得到拍照订单的信息
uuid = get_p3d_info(str(pid))
if uuid != 0:
print("uuid",uuid)
config.oss_bucket_3d_view.put_object_from_file(f'{uuid}/3d_view.png', f'D://print/{pid}/{pid}_pic.png')
#os.system(f'FBX2glTF -i {os.path.join(workdir, "print", pid, obj_filename)} -o {os.path.join(workdir, "print", pid, glb_filename)}')
#如果压缩后的glb文件小于2M,文件贴图异常,需要重新生成,直到成功
# while os.path.getsize(os.path.join(workdir, "print", pid, glb_filename)) < 2 * 1024 * 1024:
# print(f'{pid}glb文件大小:{os.path.getsize(os.path.join(workdir, "print", pid, glb_filename))}')
# print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 压缩后的glb文件小于2M,文件贴图异常,重新生成glb文件')
# # 将有异常的pid相关文件全部移动到异常文件夹,然后重新下载重新生成
# if not os.path.exists(os.path.join(workdir, 'print', 'error', pid)):
# os.makedirs(os.path.join(workdir, 'print', 'error', pid))
# for file in os.listdir(os.path.join(workdir, 'print', pid)):
# shutil.move(os.path.join(workdir, 'print', pid, file), os.path.join(workdir, 'print', 'error', pid, file))
# down_obj_fromoss(pid)
# os.system(f'gltfpack -c -i {os.path.join(workdir, "print", pid, obj_filename)} -o {os.path.join(workdir, "print", pid, glb_filename)}')
print('上传glb文件到oss...')
oss_client.put_object_from_file(f'glbs/print/{glb_filename}', os.path.join(workdir, "print", pid, glb_filename))
print(f'{update_repair_status_url}?id={repair_id}')
res = requests.get(f'{update_repair_status_url}?id={repair_id}')
print('更新团队审核状态:', res.text)
shutil.rmtree(os.path.join(workdir, 'print', pid), ignore_errors=True)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 生成团队审核模型 end')
def get_p3d_info(pid):
url = "https://mp.api.suwa3d.com/api/customerP3dLog/info?id="+pid
res = requests.get(url)
res = res.json()
if res["code"] == 1000:
return res["data"]["guid"]
else:
return 0
def platform_check(r):
try:
if r.llen('model:modelRepairGLBQueue') == 0:
time.sleep(5)
return
except Exception as e:
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,5秒后重试')
print(e)
time.sleep(5)
r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
return
pid = r.lpop('model:modelRepairGLBQueue')
if pid is None: return
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 生成平台审核模型 start', )
pid = pid.decode('utf-8')
down_obj_fromoss(pid)
obj_filename = f'{pid}.obj'
glb_filename = f'{pid}.glb'
os.system(f'gltfpack -c -i {os.path.join(workdir, "print", pid, obj_filename)} -o {os.path.join(workdir, "print", pid, glb_filename)}')
oss_client.put_object_from_file(f'glbs/print/{glb_filename}', os.path.join(workdir, "print", pid, glb_filename))
print(f'{update_check_url}?id={pid}')
res = requests.get(f'{update_check_url}?id={pid}')
print(res.text)
shutil.rmtree(os.path.join(workdir, 'print', pid), ignore_errors=True)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 生成平台审核模型 end')
#obj文件转成 glb文件
def objToGlbAndUpload(pid):
obj_filename = f'{pid}_original.obj'
glb_filename = f'{pid}.glb'
print('开始转换obj文件为glb文件...')
os.system(f'gltfpack -c -i {os.path.join(workdir, "print", pid, obj_filename)} -o {os.path.join(workdir, "print", pid, glb_filename)}')
#重命名产生的glb 文件
print('上传glb文件到oss...')
oss_client.put_object_from_file(f'glbs/print/{glb_filename}', os.path.join(workdir, "print", pid, glb_filename))
def create_redis_connection():
"""创建 Redis 连接,若连接失败则重试"""
while True:
try:
r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
# 尝试进行一次操作,检查连接是否有效
r.ping() # ping 操作是一个简单的连接测试
print("Redis连接成功!")
return r
except ConnectionError:
print("Redis连接失败,正在重试...")
time.sleep(5)
def main(r):
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '模型生成程序 start')
while True:
try:
team_check(r)
# platform_check(r)
#make3d4print_task(r)
except Exception as e:
print('出现异常:', e)
time.sleep(5)
r = create_redis_connection()
continue
if __name__ == '__main__':
atexit.register(common.notify,"R13-修模师审核通过,生成打印任务程序停止")
AccessKeyId = 'LTAI5tSReWm8hz7dSYxxth8f'
AccessKeySecret = '8ywTDF9upPAtvgXtLKALY2iMYHIxdS'
Endpoint = 'oss-cn-shanghai.aliyuncs.com'
Bucket = 'suwa3d-securedata'
oss_client = oss2.Bucket(oss2.Auth(AccessKeyId, AccessKeySecret), Endpoint, Bucket)
update_check_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/updateStatusToWaitingPlatformCheckingStatus'
update_team_check_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/updateStatusToWaitingTeamCheckingStatus'
update_status_printstatus_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/updateBuildPrintModelStatus'
update_makeprintobj_status_url = 'https://mp.api.suwa3d.com/api/printOrder/updateMakePrintObjSucceed'
getRepairInfo_url = 'https://repair.api.suwa3d.com/api/modelRepairOrder/teamCheckGLBInfo'
update_repair_status_url = 'https://repair.api.suwa3d.com/api/modelRepairOrder/updateStatusToWaitingTeamCheckingStatus'
if platform.system() == 'Windows':
workdir = 'D:\\'
else:
workdir = '/data/datasets/'
blenderbin = find_blender_bin_path()
r = create_redis_connection()
main(r)