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.
399 lines
16 KiB
399 lines
16 KiB
from ctypes import util |
|
import os, oss2, time, redis, requests, shutil, sys, subprocess, json, platform,random |
|
from PIL import Image, ImageDraw, ImageFont |
|
from retrying import retry |
|
import atexit,platform |
|
import get_preview_image |
|
# if platform.system() == 'Windows': |
|
# sys.path.append('libs\\') |
|
sys.path.append('/home/acprint/code/libs/') |
|
import common |
|
|
|
|
|
#创建文本文件 |
|
def creatDoingLog(order_id): |
|
#在指定路径创建一条 order_id.txt 文本 |
|
file_path = f"doingLog/{order_id}.txt" |
|
if os.path.exists(file_path): |
|
return |
|
#创建 |
|
with open(file_path, "w", encoding="utf-8") as file: |
|
file.write("1") |
|
|
|
#移除指定的文本文件 |
|
def removeDoingLog(order_id): |
|
file_path = f"doingLog/{order_id}.txt" |
|
if not os.path.exists(file_path): |
|
return |
|
os.remove(file_path) |
|
|
|
#遍历文件夹,返回指定的order_id |
|
def get_order_id_by_txt(): |
|
#遍历文件夹 |
|
for file in os.listdir("doingLog"): |
|
if file != "": |
|
arrFile = file.split(".") |
|
return arrFile[0] |
|
return None |
|
|
|
def find_blender_bin_path(): |
|
if platform.system() == 'Linux': return '/home/acprint/code/blender/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,download_flag="print_build"): |
|
# 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}/' |
|
#根据order_id 获取文件在 oss 上的存储路径 |
|
if order_id is not None: |
|
tempURL = "https://mp.gray.api.suwa3d.com/api/order/getOssSuffixByOrderId?order_id="+str(order_id) |
|
print(tempURL) |
|
res = requests.get(tempURL) |
|
print(res.json()) |
|
resCode = res.json()['code'] |
|
if int(resCode) != 1000: |
|
return -1 |
|
print(res.text) |
|
if res.json()['data'] != "": |
|
prefix = f'objs/print/{pid}/{res.json()["data"]}/{str(order_id)}' |
|
|
|
print(prefix) |
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) |
|
#判断是否有值,没有值的话就从老的路径再获取一次数据 |
|
if len(list(filelist)) == 0: |
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=f'objs/print/{pid}/') |
|
else: |
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) |
|
|
|
|
|
find = False |
|
findTex1Jpg = False |
|
for file in filelist: |
|
filename = file.key.split('/')[-1] |
|
if filename == '': continue |
|
if filename.endswith(f'{pid}.obj'): |
|
find = True |
|
|
|
if download_flag == "print_build": |
|
if filename != str(pid)+".obj" and filename != str(pid)+".mtl" and filename != str(pid)+"Tex1.jpg" and filename != str(pid)+"_RB_B_Tex1.jpg": |
|
continue |
|
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: |
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) |
|
for file in filelist: |
|
filename = file.key.split('/')[-1] |
|
if filename == '': continue |
|
if filename.endswith(f'.obj'): |
|
find = True |
|
|
|
# if download_flag == "print_build": |
|
# if filename != str(pid)+".obj" and filename != str(pid)+".mtl" and filename != str(pid)+"Tex1.jpg": |
|
# continue |
|
localfile = os.path.join(path, filename) |
|
res = oss_client.get_object_to_file(file.key, localfile) |
|
print(f'下载文件:{file.key},状态:{res.status}') |
|
break |
|
|
|
if find: |
|
os.rename(localfile, os.path.join(path,f"{pid}.obj")) |
|
#重命名文件 |
|
|
|
#判断是否有Tex1.jpg |
|
if not os.path.exists(os.path.join(path,f"{pid}Tex1.jpg")): |
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) |
|
for file in filelist: |
|
filename = file.key.split('/')[-1] |
|
if filename == '': continue |
|
if filename.endswith(f'{pid}.jpg'): |
|
findTex1Jpg = True |
|
|
|
# if download_flag == "print_build": |
|
# if filename != str(pid)+".obj" and filename != str(pid)+".mtl" and filename != str(pid)+"Tex1.jpg": |
|
# continue |
|
localfile = os.path.join(path, filename) |
|
res = oss_client.get_object_to_file(file.key, localfile) |
|
print(f'下载文件:{file.key},状态:{res.status}') |
|
break |
|
|
|
if findTex1Jpg: |
|
os.rename(localfile, os.path.join(path,f"{pid}Tex1.jpg")) |
|
#重命名文件 |
|
|
|
# for file in filelist: |
|
# filename = file.key.split('/')[-1] |
|
# if filename == '': continue |
|
# if filename.endswith(f'{pid}.obj'): |
|
# find = True |
|
# if filename.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文件,跳过') |
|
common.notify(f"{pid}-构建打印文件,找不到obj文件,异常,跳过该任务处理") |
|
# sys.exit(1) |
|
os.system(f'python auto_convert3d.py') |
|
return |
|
|
|
# print('下载完成后静默10秒,等待文件写入完成') |
|
# time.sleep(10) |
|
#根据pid获取orderId |
|
def getPidFromOrderId(orderId): |
|
getPidFromOrderId_url = 'https://mp.gray.api.suwa3d.com/api/printOrder/infoByOrderId' |
|
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 restart_current_process(new_command): |
|
try: |
|
# 保存新进程的命令 |
|
command = new_command.split() |
|
|
|
# 启动新进程 |
|
new_process = subprocess.Popen(command) |
|
|
|
# 打印新进程的PID |
|
print(f"New process started with PID: {new_process.pid}") |
|
|
|
# 终止当前进程 |
|
os._exit(0) |
|
|
|
except Exception as e: |
|
print(f"An error occurred: {e}") |
|
|
|
|
|
def make3d4print_task(r): |
|
|
|
|
|
tempOrderId = "0" |
|
try: |
|
if r.llen('model:printOrder') == 0: |
|
time.sleep(5) |
|
|
|
# tempOrderId = get_order_id_by_txt() |
|
# if tempOrderId == "0": |
|
# 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 = None |
|
if tempOrderId == "0": |
|
orderId = r.lpop('model:printOrder') |
|
else: |
|
orderId = tempOrderId |
|
|
|
if orderId is None: return |
|
|
|
if type(orderId) != str: |
|
orderId = orderId.decode('utf-8') |
|
# orderId = 56077 |
|
res = getPidFromOrderId(orderId) |
|
if res == -1: |
|
print("查询打印订单信息失败,重新开启进程") |
|
#os.system(f'python auto_convert3d.py') |
|
return |
|
|
|
#根据 buy_type 判断 是否是冰箱贴 或者徽章 |
|
buyType = str(res['buy_type']) |
|
if buyType == "2" or buyType == "3" or buyType == "4": |
|
#塞入到no_resize 队列 |
|
r.lpush("model:noresize", orderId) |
|
return |
|
|
|
pid = str(res['pid']) |
|
if pid == "88985": |
|
return |
|
if pid == "": |
|
return |
|
#创建正在处理的文本内容 |
|
creatDoingLog(orderId) |
|
|
|
print_type = 1 |
|
digital_type = 1 # 0: 只有手办 1: 只有数字模型 2: 手办+数字模型 |
|
|
|
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成待打印模型 start', ) |
|
isFindObj = False |
|
print("AAAAAAAAAAAAAAAAAA") |
|
downloadRes = down_obj_fromoss(pid, print_type, orderId,download_flag="print_build") |
|
print("downloadRes",downloadRes) |
|
if downloadRes == -1: |
|
print("下载错误") |
|
return |
|
# 获取程序运行当前目录 |
|
resize_py_path = os.path.join(os.getcwd(), 'blender', 'build_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文件生成异常,退出,重新执行') |
|
# restart_current_process("python gray_auto_convert3d.py") |
|
return |
|
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}') |
|
#上传jpg文件 |
|
#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}') |
|
|
|
|
|
# 如果指定文件夹目标文件存在,则先删除 |
|
if os.path.exists(os.path.join(workdir, f'complate/objs/{pid}/order_{orderId}/')): |
|
delete_files_in_directory(os.path.join(workdir, f'complate/objs/{pid}/order_{orderId}/')) |
|
|
|
for file in os.listdir(path): |
|
# 跳过一些不需要上传的文件 |
|
if file in [f'{pid}.png',f'{pid}_old.jpg', f'{pid}.obj', f'{pid}_decimate.glb', f'{pid}_decimate.obj', f'{pid}_decimate.mtl', f'{pid}Tex1_decimate.jpg', f'{pid}_original.obj', f'{pid}_original.mtl']: continue |
|
print("当前目录",os.path.join(path, file)) |
|
|
|
print(f"复制文件路径-{file}") |
|
#将文件移动到指定目录 |
|
if not os.path.exists(os.path.join(workdir, f'complate/objs/{pid}/')): |
|
os.makedirs(os.path.join(workdir, f'complate/objs/{pid}/'),mode=0o777, exist_ok=True) |
|
|
|
if not os.path.exists(os.path.join(workdir, f'complate/objs/{pid}/order_{orderId}/')): |
|
os.makedirs(os.path.join(workdir, f'complate/objs/{pid}/order_{orderId}/'),mode=0o777, exist_ok=True) |
|
|
|
shutil.move(os.path.join(path, file), os.path.join(workdir, f'complate/objs/{pid}/order_{orderId}/')) |
|
|
|
|
|
# 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') |
|
removeDoingLog(orderId) |
|
#生成封面图片 |
|
print('小票封面图处理中....') |
|
get_preview_image.createImage(pid) |
|
#os.system(f'python get_preview_image.py {pid}') |
|
|
|
print(f"{pid}-已处理结束") |
|
|
|
# restart_current_process("python gray_auto_convert3d.py") |
|
|
|
|
|
def delete_files_in_directory(directory): |
|
for file_name in os.listdir(directory): |
|
file_path = os.path.join(directory, file_name) |
|
try: |
|
if os.path.isfile(file_path): |
|
os.remove(file_path) |
|
print(f"Deleted: {file_path}") |
|
except Exception as e: |
|
print(f"Error deleting {file_path}: {e}") |
|
|
|
|
|
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: |
|
#构建打印文件 |
|
make3d4print_task(r) |
|
except Exception as e: |
|
print(f'出现异常:{e}') |
|
time.sleep(15) |
|
r = create_redis_connection() |
|
continue |
|
|
|
if __name__ == '__main__': |
|
|
|
# atexit.register(common.notify,"虚拟机,生成打印任务程序停止") |
|
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.gray.api.suwa3d.com/api/customerP3dLog/updateStatusToWaitingPlatformCheckingStatus' |
|
update_team_check_url = 'https://mp.gray.api.suwa3d.com/api/customerP3dLog/updateStatusToWaitingTeamCheckingStatus' |
|
update_status_printstatus_url = 'https://mp.gray.api.suwa3d.com/api/customerP3dLog/updateBuildPrintModelStatus' |
|
update_makeprintobj_status_url = 'https://mp.gray.api.suwa3d.com/api/printOrder/updateMakePrintObjSucceed' |
|
getRepairInfo_url = 'https://repair.gray.api.suwa3d.com/api/modelRepairOrder/teamCheckGLBInfo' |
|
update_repair_status_url = 'https://repair.gray.api.suwa3d.com/api/modelRepairOrder/updateStatusToWaitingTeamCheckingStatus' |
|
if platform.system() == 'Windows': |
|
workdir = 'E:\\' |
|
else: |
|
workdir = '/data/datasets/' |
|
blenderbin = find_blender_bin_path() |
|
|
|
r = create_redis_connection() |
|
#E:\\complate/objs/147852_54579/ |
|
# os.remove(os.path.join(workdir, f'complate/objs/147852_54579/')) |
|
main(r) |