import time
import json
import fastapi
import uvicorn
import serial
import signal
# from fastapi import FastAPI, HTTPException
from fastapi import FastAPI, HTTPException, Request
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
#from PLC_Siemens import UserControlReadWriteOp
from Modbus_TCP import Modbus_TCP
from PanasonicFPXHPLC import PanasonicFPXHPLC
import threading
import os
import sys
from pathlib import Path
from ScrewInfo import ScrewInfo
from ScannerInfo import ScannerInfo
from fastapi.responses import FileResponse
import glob
from HZG import HZG
import logging
from HIKCamera import HikCamera
from logging.handlers import RotatingFileHandler
from logging.handlers import TimedRotatingFileHandler
logging.basicConfig(filename='app.log', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
app = FastAPI()
# 新增全局退出控制
exit_flag = threading.Event()
main_pid = os.getpid()
#x相机初始化
Camera_Left = HikCamera()
Camera_Left.SetConnect("192.168.0.100", 7930)
Camera_Right = HikCamera()
Camera_Right.SetConnect("192.168.0.100", 7931)
app.mount("/static", StaticFiles(directory="static"), name="static")
sys.modules["fastapi.openapi.docs"].get_swagger_ui_html.__kwdefaults__["swagger_js_url"] = "/static/swagger-ui-bundle.js"
sys.modules["fastapi.openapi.docs"].get_swagger_ui_html.__kwdefaults__["swagger_css_url"] = "/static/swagger-ui.css"
# plc = PanasonicFPXHPLC("192.168.0.20")
plc = PanasonicFPXHPLC(port='COM16', baudrate=115200)
hzg = HZG()
SignalDi = None
lock_Barcode = threading.Lock()
lock_Plc = threading.Lock()
lock_Screw = threading.Lock()
lock_Camera_Left = threading.Lock()
lock_Camera_Right = threading.Lock()
############################################################
#根据路径下的json文件,创建螺钉机实例
base_dir = os.path.dirname(os.path.abspath(__file__))
# 使用Path对象处理路径
root_path = Path(base_dir)
# 递归遍历所有.json文件
#构造空的螺钉机字典
ScrewDeviceList ={}
#构造空的扫码枪机字典
ScannerDeviceList ={}
#遍历路径下 json文件
for json_file in root_path.rglob("*.json"):
with open(json_file, 'r', encoding='utf-8') as file:
data = json.load(file)
# 获取配置文件中的IP和Port
DeviceType = data["DeviceType"]
if DeviceType == "Screw":
# 将文件信息存入字典
# 获取配置文件中的IP和Port
ip = data["Ip"]
port = (data["Port"])
info = {json_file.stem: ScrewInfo(ip,port)}
ScrewDeviceList.update(info)
elif DeviceType == "Scanner":
#根据json配置内容,创建扫码枪对象实例
info = {json_file.stem: ScannerInfo(json_file.stem,data["Port"],data["Baudrate"])}
ScannerDeviceList.update(info)
############################################################
# 创建一个锁对象
lock = threading.Lock()
# # 绑定find_image文件夹路径
IMAGE_FOLDER_SaveImage = "D:\\SaveImg\\" # 替换为你的文件夹路径
##绑定左工位image文件夹路径
IMAGE_FOLDER = ("D:\\SaveImg\\")
LastImageFile = None
CreateTime_LastImage = None
##绑定右工位image文件夹路径
IMAGE_FOLDER2 = ("D:\\SaveImg\\")
LastImageFile2 = None
CreateTime_LastImage2 = None
# 新增监控线程
def shutdown_monitor():
while True:
if exit_flag.is_set():
print("检测到致命错误,触发系统关闭...")
hzg.SendMessageToHZG("检测到致命错误,触发系统关闭...")
os.kill(main_pid, signal.SIGINT) # 优雅关闭FastAPI
break
time.sleep(1)
def ScanBarcode():
try:
while not exit_flag.is_set():
try:
for key, scanner in ScannerDeviceList.items():
if not scanner.connected:
continue
try:
waiting = scanner.Device.in_waiting
if waiting > 0:
#time.sleep(0.1)
raw_data = scanner.Device.read(scanner.Device.in_waiting)
try:
decoded_data = raw_data.decode('utf-8').strip()
if decoded_data:
with lock_Barcode:
scanner.Data = decoded_data
print(decoded_data)
#扫到码后调用HZG 服务端指令 HZG完成业务逻辑处理
logging.info("扫码调用活字格文件")
print(hzg.BarcodeProcess(key,decoded_data))
logging.info("扫码调用活字格文件完成")
print(f"[扫码数据] {scanner.Data}")
except UnicodeDecodeError as e:
print(f"解码失败 @ {scanner.Port}: {raw_data.hex()}")
raise RuntimeError("连续解码错误") from e
except (serial.SerialException, OSError) as e:
print(f"硬件错误 @ {scanner.Port}: {str(e)}")
hzg.SendMessageToHZG(f"硬件错误 @ {scanner.Port}: {str(e)}")
raise # 向上抛出致命错误
except RuntimeError as e:
print(f"扫码系统关键错误: {str(e)}")
hzg.SendMessageToHZG(f"扫码系统关键错误: {str(e)}")
exit_flag.set() # 设置全局退出标志
break
time.sleep(0.1)
except Exception as e:
#print(f"扫码线程崩溃: {str(e)}")
exit_flag.set()
os.kill(main_pid, signal.SIGINT) # 直接发送终止信号
def ReadTorque ():
while True:
try:
for key, screw in ScrewDeviceList.items():
print(key)
print("TorqueData")
print(screw.Data)
time.sleep(0.5)
with lock_Screw:
rlt = screw.device.read_holding_register(0, 100)
#print(rlt)
#打螺钉结束信号
#print(rlt[32] )
if rlt[32] == 1:
screw.SetScrewFinish()
if rlt[32] !=1:
screw.ResetScrewFinish()
screw.ResetorqueFinish()
if screw.CheckIfNeedGetTorque() :
#计算扭矩
torque = rlt[24]/10 + rlt[25]/1000
# 计算角度
angle = rlt[26]*10000 + rlt[27]
#判断拧紧结果
if rlt[31] == 0:
data = {"Torque":torque,"Angle":angle,"Result":True,"ErrorCode":rlt[31]}
else:
data = {"Torque": torque, "Angle": angle, "Result": False,"ErrorCode":rlt[31]}
screw.Data.append(data)
screw.SetorqueFinish()
#保存扭矩
pass
except Exception as ex:
print(f"螺钉枪关键错误: {str(ex)}")
hzg.SendMessageToHZG(f"螺钉枪关键错误: {str(ex)}")
exit_flag.set() # 设置全局退出标志
break
time.sleep(0.1)
def ScrewLeftFinishProcess ():
while True:
try:
# R50 左打螺钉完成信号 R55 右侧打螺钉完成信号
# 判断完成信号是否从0跳转到1,发生跳转时调用或资格接口
with lock_Plc:
IsLeftScrewFinish = plc.read_r_register(50)
logging.info(f"IsLeftScrewFinish:{IsLeftScrewFinish}")
time.sleep(0.1)
with lock_Plc:
IsLeftReadTorqueFinish = plc.read_r_register(51)
logging.info(f"IsLeftReadTorqueFinish:{IsLeftReadTorqueFinish}")
if IsLeftScrewFinish and not IsLeftReadTorqueFinish:
logging.info(f"StartCallGettorqueByPython")
rlt = hzg.CallGettorqueByPython("Left")
logging.info(f"EndCallGettorqueByPython:{rlt}")
#延时三秒,防止重复调用
time.sleep(2)
except Exception as ex:
print(f"扫码系统关键错误: {str(ex)}")
hzg.SendMessageToHZG(f"扫码系统关键错误: {str(ex)}")
exit_flag.set() # 设置全局退出标志
break
time.sleep(0.1)
def ScrewRightFinishProcess ():
while True:
try:
# R50 左打螺钉完成信号 R55 右侧打螺钉完成信号
# 判断完成信号是否从0跳转到1,发生跳转时调用或资格接口
with lock_Plc:
IsRightScrewFinish = plc.read_r_register(55)
logging.info(f"IsRightScrewFinish:{IsRightScrewFinish}")
time.sleep(0.1)
with lock_Plc:
IsRightReadTorqueFinish = plc.read_r_register(56)
logging.info(f"IsRightReadTorqueFinish:{IsRightReadTorqueFinish}")
if IsRightScrewFinish and not IsRightReadTorqueFinish:
logging.info(f"StartCallGettorqueByPython")
rlt = hzg.CallGettorqueByPython("Right")
logging.info(f"EndCallGettorqueByPython:{rlt}")
#延时三秒,防止重复调用
time.sleep(2)
except Exception as ex:
print(f"扫码系统关键错误: {str(ex)}")
hzg.SendMessageToHZG(f"扫码系统关键错误: {str(ex)}")
exit_flag.set() # 设置全局退出标志
break
time.sleep(0.1)
def CameraLeftProcess():#L:读:触发相机D414写入结果地址:D406,R:触发相机读D402,写入结果地址:D404
while True:
try:
with lock_Plc:
IsLeftCameraReady = plc.read_d_register(414)
time.sleep(0.1)
logging.info(f"IsLeftCameraReady:{IsLeftCameraReady}")
if IsLeftCameraReady==1:
Camera_Left.Open()
barcide_Left=hzg.getbarcodefromHZG("左工位")
if barcide_Left["照片保存信息"]=="1":
save_info="Y"
else:
save_info="N"
Camera_Left_name = barcide_Left["合成的条码返回"]
Camera_Left_name=Camera_Left_name.replace("\"", "").replace("#", "_")
Camera_Left_road_list=Camera_Left.Trigger(Camera_Left_name, "L", save_info).split(";")
Camera_Left_is=Camera_Left_road_list[0]
if len(Camera_Left_road_list)==2:
path=os.path.join(Camera_Left_road_list[1].replace("\"", ""),Camera_Left_name+ ".jpg").replace('\\', "\\\"")
path1 = path.replace("\"", "")
Barcode=barcide_Left["合成的条码返回"].split("#")[1]
hzg.getImgRoadfromHZG("左工位", path1,Barcode,Camera_Left_name)
# HZG.getImgRoadfromHZG("右工位", os.path.join(Camera_Left_road_list[1].replace("\"", ""), barcide_Left["合成的条码返回"].replace("\"", "") + ".jpg"))
# HZG.getImgRoadfromHZG("右工位", Camera_Left_road)
if Camera_Left_is=="1":
with lock_Plc:
plc.write_d_register(406, 1)
logging.info(f"writeIsLeftCameraFinish:1")
time.sleep(2)
with lock_Plc:
plc.write_d_register(406, 0)
time.sleep(0.1)
logging.info(f"RedaIsLeftCamera:Clear")
else:
with lock_Plc:
plc.write_d_register(406, 2)
logging.info(f"writeIsLeftCameraFinish:2")
time.sleep(2)
with lock_Plc:
plc.write_d_register(406, 0)
logging.info(f"RedaIsLeftCamera:Clear")
time.sleep(1)
except Exception as ex:
with lock_Camera_Left:
Camera_Left.Close()
Camera_Left.Open()
print(f"拍照系统关键错误: {str(ex)}")
hzg.SendMessageToHZG(f"拍照系统关键错误: {str(ex)}")
exit_flag.set() # 设置全局退出标志
break
time.sleep(0.1)
def CameraRightProcess():#L:读:触发相机D414写入结果地址:D406,R:触发相机读D402,写入结果地址:D404
while True:
try:
with lock_Plc:
IsRightCameraReady = plc.read_d_register(402)
logging.info(f"IsRightCameraReady:{IsRightCameraReady}")
if IsRightCameraReady == 1:
with lock_Camera_Right:
Camera_Right.Open()
barcide_Right = hzg.getbarcodefromHZG("右工位")
if barcide_Right["照片保存信息"] == "1":
save_info = "Y"
else:
save_info = "N"
print(barcide_Right["合成的条码返回"])
Camera_Right_name = barcide_Right["合成的条码返回"].replace("\"", "").replace("#", "_")
Camera_Right_road_list=Camera_Right.Trigger( Camera_Right_name,"R", save_info).split(";")
Camera_Left_is = Camera_Right_road_list[0]
if len(Camera_Right_road_list) == 2:
path=os.path.join(Camera_Right_road_list[1].replace("\"", ""),Camera_Right_name + ".jpg").replace('\\', "\\\"")
path1 = path.replace("\"","")
Barcode = barcide_Right["合成的条码返回"].split("#")[1]
hzg.getImgRoadfromHZG("右工位", path1, Barcode,Camera_Right_name)
# HZG.getImgRoadfromHZG("右工位", Camera_Right_road)
if Camera_Left_is=="1":
logging.info(f"CameraRightProcess:SUCCESS")
with lock_Plc:
plc.write_d_register(404, 1)
logging.info(f"writeIsRightCameraFinish:1")
time.sleep(2)
with lock_Plc:
plc.write_d_register(404, 0)
logging.info(f"RedaIsRightCamera:Clear")
else:
with lock_Plc:
plc.write_d_register(404, 2)
logging.info(f"writeIsRightCameraFinish:2")
time.sleep(2)
with lock_Plc:
plc.write_d_register(404, 0)
logging.info(f"RedaIsRightCamera:Clear")
time.sleep(1)
except Exception as ex:
with lock_Camera_Right:
Camera_Right.Close()
Camera_Right.Open()
print(f"拍照系统关键错误: {str(ex)}")
hzg.SendMessageToHZG(f"拍照系统关键错误: {str(ex)}")
exit_flag.set() # 设置全局退出标志
break
time.sleep(0.1)
# def ScrewRightFinishProcess ():
#
#
# while True:
#
# try:
#
#
# # R50 左打螺钉完成信号 R55 右侧打螺钉完成信号
# # 判断完成信号是否从0跳转到1,发生跳转时调用或资格接口
# with lock_Plc:
# IsLeftScrewFinish = plc.read_r_register(50)
#
# if not IsLeftScrewFinish :
# time.sleep(0.5)
# with lock_Plc:
# IsLeftScrewFinish = plc.read_r_register(50)
# if IsLeftScrewFinish:
# hzg.CallGettorqueByPython("Left")
#
# with lock_Plc:
# IsRightScrewFinish = plc.read_r_register(55)
# if not IsRightScrewFinish :
# time.sleep(0.1)
# with lock_Plc:
# IsRightScrewFinish = plc.read_r_register(55)
# if IsRightScrewFinish:
# hzg.CallGettorqueByPython("Right")
#
#
# except Exception as ex:
# print(f"扫码系统关键错误: {str(ex)}")
# exit_flag.set() # 设置全局退出标志
# break
#
# time.sleep(0.1)
@app.get("/CameraSelectJob")
async def CameraSelectJob (Job:str):
try:
with lock_Camera_Left:
#Camera_Left.Open()
if Camera_Left.SelectJob(Job):
return {"status": 0, "msg": "success" }
else:
return {"status": -1, "msg": "NG"}
except Exception as ex:
with lock_Camera_Left:
Camera_Left.Close()
Camera_Left.Open()
print(f"拍照系统换型错误: {str(ex)}")
hzg.SendMessageToHZG(f"拍照系统换型错误: {str(ex)}")
return {"status": -1, "msg": "NG"}
#exit_flag.set() # 设置全局退出标志
@app.get("/GetBarcode")
async def GetBarcode (Device:str):
try:
if Device in ScannerDeviceList:
device = ScannerDeviceList[Device]
with lock_Barcode:
barcode = device.Data
device.Data = ""
return {"status": 0, "msg": "success", "data": barcode}
else:
return {"status": -1, "msg": "该设备不存在", "data": None}
except Exception as ex:
return {"status": -1, "msg": str(ex), "data": None}
@app.get("/GetTorque")
async def GetTorque (Device:str):
try:
if Device in ScrewDeviceList:
device = ScrewDeviceList[Device]
return {"status": 0, "msg": "success", "data": device.Data}
else:
return {"status": -1, "msg": "该设备不存在", "data": None}
except Exception as ex:
return {"status": -1, "msg": str(ex), "data": None}
@app.post("/SetScrewparameter")
async def SetScrewparameter(Device: str, value: str, TorqueUpperLimit: str, TorqueLowerLimit: str, AngleUpperLimit: str, AngleLowerLimit: str):
"""
向指定设备的寄存器中写入地址和值,并设置扭矩上下限
:param Device: 设备名称
:param address: 寄存器地址
:param value: 要写入的值
:param TorqueUpperLimit: 扭矩上限,写入地址 58
:param TorqueLowerLimit: 扭矩下限,写入地址 60
:return: 返回操作状态和信息
"""
try:
Rlt = {
"status": 0,
"msg": "写入成功",
"data": {
"address": None,
"TorqueUpperLimit": None,
"TorqueLowerLimit": None
}
}
if Device in ScrewDeviceList:
device = ScrewDeviceList[Device]
with lock_Screw:
#写入任务数和参数
result_Task = device.device.write_holding_register(48, 1)
if result_Task != (48, 1):
Rlt["status"] = -1
Rlt["msg"] = "写入任务数失败"
return Rlt
print("写入任务数到地址 48 成功")
with lock_Screw:
result_Parameter = device.device.write_holding_register(49, 1)
if result_Parameter != (49, 1):
Rlt["status"] = -1
Rlt["msg"] = "写入参数失败"
return Rlt
print("写入参数到地址 49 成功")
with lock_Screw:
# 写入扭矩目标值到地址 56
result_StandardValue = device.device.write_holding_register(56, int(value))
if result_StandardValue != (56, int(value)):
Rlt["status"] = -1
Rlt["msg"] = "写入扭矩目标值失败"
return Rlt
print(f"写入目标值到地址 56 成功,值: {value}")
# 写入扭矩上限到地址 58
with lock_Screw:
result_TorqueUpperLimit = device.device.write_holding_register(58, int(TorqueUpperLimit))
if result_TorqueUpperLimit != (58, int(TorqueUpperLimit)):
Rlt["status"] = -1
Rlt["msg"] = "写入扭矩上限失败"
return Rlt
print(f"写入扭矩上限到地址 58 成功,值: {TorqueUpperLimit}")
with lock_Screw:
# 写入扭矩下限到地址 60
result_TorqueLowerLimit = device.device.write_holding_register(60, int(TorqueLowerLimit))
if result_TorqueLowerLimit != (60, int(TorqueLowerLimit)):
Rlt["status"] = -1
Rlt["msg"] = "写入扭矩下限失败"
return Rlt
print(f"写入扭矩下限到地址 60 成功,值: {TorqueLowerLimit}")
with lock_Screw:
# 写入转角上限到地址 64
result_AngleUpperLimit = device.device.write_holding_register(64, int(AngleUpperLimit))
if result_AngleUpperLimit != (64, int(AngleUpperLimit)):
Rlt["status"] = -1
Rlt["msg"] = "写入转角上限失败"
return Rlt
print(f"写入转角上限到地址 64 成功,值: {AngleUpperLimit}")
# 写入转角下限到地址 66
with lock_Screw:
result_AngleLowerLimit = device.device.write_holding_register(66, int(AngleLowerLimit))
if result_AngleLowerLimit != (66, int(AngleLowerLimit)):
Rlt["status"] = -1
Rlt["msg"] = "写入转角下限失败"
return Rlt
print(f"写入转角下限到地址 66 成功,值: {AngleLowerLimit}")
# 写入扭矩参数保存
with lock_Screw:
result_ScrewSave = device.device.write_holding_register(50, 1)
if result_ScrewSave!= (50, 1):
Rlt["status"] = -1
Rlt["msg"] = "写入扭矩参数保存失败"
return Rlt
print("写入扭矩参数保存到地址 50 成功")
return {"status": 0, "msg": "写入成功", "data": None}
else:
return {"status": -1, "msg": "该设备不存在", "data": None}
except Exception as ex:
return {"status": -1, "msg": str(ex), "data": None}
@app.get("/ClearTorque")
async def ClearTorque (Device:str):
try:
if Device in ScrewDeviceList:
device = ScrewDeviceList[Device]
device.Data.clear()
return {"status": 0, "msg": "success", "data": None}
else:
return {"status": -1, "msg": "该设备不存在", "data": None}
except Exception as ex:
return {"status": -1, "msg": str(ex), "data": None}
@app.get("/SetData")
async def SetData (RegisterType:str,Address:str,Value:str,Type:str):
try:
if RegisterType == "DT":
if Type == "U8":
logging.info("SetData:开始读取write_d_register_fineshed数据")
with lock_Plc:
write_d_register_fineshed=plc.write_d_register(int(Address), int(Value), Type)
logging.info(f"write_d_register_fineshed:{write_d_register_fineshed}")
if write_d_register_fineshed:#plc.write_d_register(int(Address),int(Value),Type):
return {"status": 0, "msg": "写入成功", "data": None}
else:
return {"status": -1, "msg": "写入失败", "data": None}
if Type == "String":
logging.info("SetData:开始读取write_d_register_fineshed数据")
with lock_Plc:
write_d_register_fineshed = plc.write_d_register(int(Address),Value,Type)
logging.info(f"write_d_register_fineshed:{write_d_register_fineshed}")
if write_d_register_fineshed: # plc.write_d_register(int(Address),Value,Type):
return {"status": 0, "msg": "写入成功", "data": None}
else:
return {"status": -1, "msg": "写入失败", "data": None}
elif RegisterType == "R":
logging.info("SetData:开始读取write_r_register_fineshed数据")
with lock_Plc:
write_r_register_fineshed = plc.write_r_register(int(Address),int(Value))
logging.info(f"write_r_register_fineshed:{write_r_register_fineshed}")
if write_r_register_fineshed:#plc.write_r_register(int(Address),int(Value)):
return {"status": 0, "msg": "写入成功", "data": None}
else:
return {"status": -1, "msg": "写入失败", "data": None}
else:
return {"status": -1, "msg": "寄存器类型不存在", "data": None}
except Exception as ex:
print(f"读写PLC错误: {str(ex)}")
hzg.SendMessageToHZG(f"读写PLC错误: {str(ex)}")
exit_flag.set() # 设置全局退出标志
@app.get("/GetData")
async def GetData(RegisterType: str, Address: str,Type:str):
try:
logging.info("Start:开始读取PLC数据")
if RegisterType == "DT":
if Type == "String":
with lock_Plc:
rlt = plc.Read_string(int(Address))
if rlt != None:
logging.info(f"End:DT/String{rlt}")
return {"status": 0, "msg": "读取成功", "data":rlt}
else:
return {"status": -1, "msg": "读取失败", "data": None}
else:
with lock_Plc:
rlt = plc.read_dt_register(int(Address))
if rlt != None:
logging.info(f"End:DT/U8{rlt}")
return {"status": 0, "msg": "读取成功", "data": rlt}
else:
return {"status": -1, "msg": "读取失败", "data": None}
elif RegisterType == "R":
with lock_Plc:
rlt = plc.read_r_register(int(Address))
if rlt != None:
logging.info(f"End:R/Bool{rlt}")
return {"status": 0, "msg": "读取成功", "data": rlt}
else:
return {"status": -1, "msg": "读取失败", "data": None}
else:
return {"status": -1, "msg": "寄存器类型不存在", "data": None}
except Exception as ex:
print(f"读写PLC错误: {str(ex)}")
hzg.SendMessageToHZG(f"读写PLC错误: {str(ex)}")
exit_flag.set() # 设置全局退出标志
@app.get("/imagesLeft/{filename}")
async def get_image(filename: str):
# images = glob.glob(os.path.join((IMAGE_FOLDER+"*.bmp")))
# images = glob.glob(os.path.join((IMAGE_FOLDER+"*.jpg")))
# if not images:
# return {"error": "File not found"}
# images.sort(key=os.path.getmtime)
# if os.path.isfile(images[-1]):
# LastImageFile = images[-1]
return FileResponse(LastImageFile)
# @app.get("/CheckIfHaveNewImage1/")
# async def CheckIfHaveNewImage():
# global LastImageFile,CreateTime_LastImage
#
# images = glob.glob(os.path.join((IMAGE_FOLDER + "*.jpg")))
# if not images:
# return {"status": -1, "msg": "文件夹无照片", "data": None}
# images.sort(key=os.path.getmtime)
#
# if os.path.isfile(images[-1]):
# if LastImageFile != None:
# CreateTime_new = os.path.getmtime(images[-1])
# if CreateTime_LastImage != CreateTime_new:
# CreateTime_LastImage = CreateTime_new
# LastImageFile = images[-1]
# return {"status": 0, "msg": "照片已经更新", "data": None}
# else:
# CreateTime_new = os.path.getmtime(images[-1])
# CreateTime_LastImage = CreateTime_new
# LastImageFile = images[-1]
# return {"status": 0, "msg": "照片已经更新", "data": None}
# return {"status": -1, "msg": "照片未更新", "data": None}
@app.get("/CheckIfHaveNewImage1/")
async def CheckIfHaveNewImage():
global LastImageFile, CreateTime_LastImage
all_images = []
# 递归遍历所有Left文件夹
for root, dirs, files in os.walk(IMAGE_FOLDER):
# 只处理包含 Left 且为 OK 或 NG 的文件夹
if "Left" in root and (os.path.basename(root) in ["OK", "NG"]):
images = glob.glob(os.path.join(root, "*.jpg"))
all_images.extend(images)
# 所有目录遍历完成后检查
if not all_images:
return {"status": -1, "msg": "所有Left文件夹无照片", "data": None}
# 获取最新的文件
all_images.sort(key=os.path.getmtime)
latest_image = all_images[-1]
current = os.path.getmtime(latest_image) # 修复变量名
# 首次初始化
if LastImageFile is None:
LastImageFile = latest_image
CreateTime_LastImage = current # 修复变量赋值
return {"status": 0, "msg": "首次发现照片", "data": latest_image}
# 检测更新(使用精确时间比对)
if current > CreateTime_LastImage: # 改为时间戳比较而非不等于
LastImageFile = latest_image
CreateTime_LastImage = current
return {"status": 0, "msg": "照片已更新", "data": latest_image}
return {"status": -1, "msg": "照片未更新", "data": None}
@app.get("/imagesRight/{filename}")
async def get_image(filename: str):
# images = glob.glob(os.path.join((IMAGE_FOLDER2+"*.bmp")))
# images = glob.glob(os.path.join((IMAGE_FOLDER2+"*.jpg")))
# if not images:
# return {"error": "File not found"}
# images.sort(key=os.path.getmtime)
# if os.path.isfile(images[-1]):
# LastImageFile = images[-1]
return FileResponse(LastImageFile2)
# @app.get("/CheckIfHaveNewImage2/")
# async def CheckIfHaveNewImage():
# global LastImageFile2,CreateTime_LastImage2
#
# images = glob.glob(os.path.join((IMAGE_FOLDER2 + "*.jpg")))
# if not images:
# return {"status": -1, "msg": "文件夹无照片", "data": None}
# images.sort(key=os.path.getmtime)
#
# if os.path.isfile(images[-1]):
# if LastImageFile2 != None:
# CreateTime_new = os.path.getmtime(images[-1])
# if CreateTime_LastImage2 != CreateTime_new:
# CreateTime_LastImage2 = CreateTime_new
# LastImageFile2 = images[-1]
# return {"status": 0, "msg": "照片已经更新", "data": None}
# else:
# CreateTime_new = os.path.getmtime(images[-1])
# CreateTime_LastImage2 = CreateTime_new
# LastImageFile2 = images[-1]
# return {"status": 0, "msg": "照片已经更新", "data": None}
# return {"status": -1, "msg": "照片未更新", "data": None}
@app.get("/CheckIfHaveNewImage2/")
async def CheckIfHaveNewImage():
global LastImageFile2, CreateTime_LastImage2
all_images = []
# 递归遍历所有Left文件夹
for root, dirs, files in os.walk(IMAGE_FOLDER2):
# 只处理包含 Left 且为 OK 或 NG 的文件夹
if "Right" in root and (os.path.basename(root) in ["OK", "NG"]):
images = glob.glob(os.path.join(root, "*.jpg"))
all_images.extend(images)
# 所有目录遍历完成后检查
if not all_images:
return {"status": -1, "msg": "所有Left文件夹无照片", "data": None}
# 获取最新的文件
all_images.sort(key=os.path.getmtime)
latest_image = all_images[-1]
current = os.path.getmtime(latest_image) # 修复变量名
# 首次初始化
if LastImageFile2 is None:
LastImageFile2 = latest_image
CreateTime_LastImage2 = current # 修复变量赋值
return {"status": 0, "msg": "首次发现照片", "data": latest_image}
# 检测更新(使用精确时间比对)
if current > CreateTime_LastImage2: # 改为时间戳比较而非不等于
LastImageFile2 = latest_image
CreateTime_LastImage2 = current
return {"status": 0, "msg": "照片已更新", "data": latest_image}
return {"status": -1, "msg": "照片未更新", "data": None}
@app.get("/find-image/{filename}")
async def find_image(filename: str):
try:
# 支持的图片扩展名
# image_extensions = [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".JPG", ".JPEG", ".PNG", ".GIF", ".BMP"]
# # 遍历文件夹,查找匹配的文件
# for file in os.listdir(IMAGE_FOLDER_SaveImage):
# file_name, file_extension = os.path.splitext(file)
# if file_name == filename and file_extension in image_extensions:
# # 找到匹配的文件,返回图片
# image_path = os.path.join(IMAGE_FOLDER_SaveImage, file)
# if os.path.isfile(image_path):
# return FileResponse(image_path)
if os.path.isfile(filename):
return FileResponse(filename)
# 如果没有找到匹配的文件,返回错误信息
raise HTTPException(status_code=404, detail="Image not found")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.on_event("startup")
async def startup_event():
hzg.SendMessageToHZG("系统初始化中...")
#遍历螺钉机,连接每一个螺钉机
for key, screw in ScrewDeviceList.items():
screw.Open()
#遍历扫码枪,扫码枪
for key, Scanner in ScannerDeviceList.items():
Scanner.connect()
# 启动监控线程
threading.Thread(target=shutdown_monitor, daemon=True).start()
# 启动数据读取线程
threading.Thread(target=ReadTorque, daemon=True).start()
threading.Thread(target=ScanBarcode, daemon=True).start()
#线程读取打螺钉完成信号
threading.Thread(target=ScrewLeftFinishProcess, daemon=True).start()
threading.Thread(target=ScrewRightFinishProcess, daemon=True).start()
# #线程读取拍照信号CameraLeftProcess()CameraRightProcess()
threading.Thread(target=CameraLeftProcess, daemon=True).start()
threading.Thread(target=CameraRightProcess, daemon=True).start()
print("系统初始化完成")
hzg.SendMessageToHZG("系统初始化完成")
print("PLC connected and FastAPI started.")
# 增强关闭事件
@app.on_event("shutdown")
def shutdown_event():
print("\n执行安全关闭...")
exit_flag.set()
# 释放所有硬件资源
for scanner in ScannerDeviceList.values():
scanner.stop()
for screw in ScrewDeviceList.values():
screw.Close()
print("所有设备连接已安全关闭")
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=39000, log_level="info")
#uvicorn.run(app, host="127.0.0.1", port=57000, log_level="info")
以上代码 是使用hikcamera类的 帮我把以上代码怎么使用的提取出来 我要加入另一段程序里面去