Chore: rename api->camera-management-api and web->management-dashboard-web-app; update compose, ignore, README references
This commit is contained in:
95
camera-management-api/ai_agent/examples/demos/cv_grab.py
Normal file
95
camera-management-api/ai_agent/examples/demos/cv_grab.py
Normal file
@@ -0,0 +1,95 @@
|
||||
#coding=utf-8
|
||||
import cv2
|
||||
import numpy as np
|
||||
import mvsdk
|
||||
import platform
|
||||
|
||||
def main_loop():
|
||||
# 枚举相机
|
||||
DevList = mvsdk.CameraEnumerateDevice()
|
||||
nDev = len(DevList)
|
||||
if nDev < 1:
|
||||
print("No camera was found!")
|
||||
return
|
||||
|
||||
for i, DevInfo in enumerate(DevList):
|
||||
print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType()))
|
||||
i = 0 if nDev == 1 else int(input("Select camera: "))
|
||||
DevInfo = DevList[i]
|
||||
print(DevInfo)
|
||||
|
||||
# 打开相机
|
||||
hCamera = 0
|
||||
try:
|
||||
hCamera = mvsdk.CameraInit(DevInfo, -1, -1)
|
||||
except mvsdk.CameraException as e:
|
||||
print("CameraInit Failed({}): {}".format(e.error_code, e.message) )
|
||||
return
|
||||
|
||||
# 获取相机特性描述
|
||||
cap = mvsdk.CameraGetCapability(hCamera)
|
||||
|
||||
# 判断是黑白相机还是彩色相机
|
||||
monoCamera = (cap.sIspCapacity.bMonoSensor != 0)
|
||||
|
||||
# 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度
|
||||
if monoCamera:
|
||||
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)
|
||||
else:
|
||||
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)
|
||||
|
||||
# 相机模式切换成连续采集
|
||||
mvsdk.CameraSetTriggerMode(hCamera, 0)
|
||||
|
||||
# 手动曝光,曝光时间30ms
|
||||
mvsdk.CameraSetAeState(hCamera, 0)
|
||||
mvsdk.CameraSetExposureTime(hCamera, 30 * 1000)
|
||||
|
||||
# 让SDK内部取图线程开始工作
|
||||
mvsdk.CameraPlay(hCamera)
|
||||
|
||||
# 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配
|
||||
FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)
|
||||
|
||||
# 分配RGB buffer,用来存放ISP输出的图像
|
||||
# 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer)
|
||||
pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)
|
||||
|
||||
while (cv2.waitKey(1) & 0xFF) != ord('q'):
|
||||
# 从相机取一帧图片
|
||||
try:
|
||||
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 200)
|
||||
mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)
|
||||
mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)
|
||||
|
||||
# windows下取到的图像数据是上下颠倒的,以BMP格式存放。转换成opencv则需要上下翻转成正的
|
||||
# linux下直接输出正的,不需要上下翻转
|
||||
if platform.system() == "Windows":
|
||||
mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1)
|
||||
|
||||
# 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据
|
||||
# 把pFrameBuffer转换成opencv的图像格式以进行后续算法处理
|
||||
frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer)
|
||||
frame = np.frombuffer(frame_data, dtype=np.uint8)
|
||||
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 1 if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8 else 3) )
|
||||
|
||||
frame = cv2.resize(frame, (640,480), interpolation = cv2.INTER_LINEAR)
|
||||
cv2.imshow("Press q to end", frame)
|
||||
|
||||
except mvsdk.CameraException as e:
|
||||
if e.error_code != mvsdk.CAMERA_STATUS_TIME_OUT:
|
||||
print("CameraGetImageBuffer failed({}): {}".format(e.error_code, e.message) )
|
||||
|
||||
# 关闭相机
|
||||
mvsdk.CameraUnInit(hCamera)
|
||||
|
||||
# 释放帧缓存
|
||||
mvsdk.CameraAlignFree(pFrameBuffer)
|
||||
|
||||
def main():
|
||||
try:
|
||||
main_loop()
|
||||
finally:
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
main()
|
||||
127
camera-management-api/ai_agent/examples/demos/cv_grab2.py
Normal file
127
camera-management-api/ai_agent/examples/demos/cv_grab2.py
Normal file
@@ -0,0 +1,127 @@
|
||||
#coding=utf-8
|
||||
import cv2
|
||||
import numpy as np
|
||||
import mvsdk
|
||||
import platform
|
||||
|
||||
class Camera(object):
|
||||
def __init__(self, DevInfo):
|
||||
super(Camera, self).__init__()
|
||||
self.DevInfo = DevInfo
|
||||
self.hCamera = 0
|
||||
self.cap = None
|
||||
self.pFrameBuffer = 0
|
||||
|
||||
def open(self):
|
||||
if self.hCamera > 0:
|
||||
return True
|
||||
|
||||
# 打开相机
|
||||
hCamera = 0
|
||||
try:
|
||||
hCamera = mvsdk.CameraInit(self.DevInfo, -1, -1)
|
||||
except mvsdk.CameraException as e:
|
||||
print("CameraInit Failed({}): {}".format(e.error_code, e.message) )
|
||||
return False
|
||||
|
||||
# 获取相机特性描述
|
||||
cap = mvsdk.CameraGetCapability(hCamera)
|
||||
|
||||
# 判断是黑白相机还是彩色相机
|
||||
monoCamera = (cap.sIspCapacity.bMonoSensor != 0)
|
||||
|
||||
# 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度
|
||||
if monoCamera:
|
||||
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)
|
||||
else:
|
||||
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)
|
||||
|
||||
# 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配
|
||||
FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)
|
||||
|
||||
# 分配RGB buffer,用来存放ISP输出的图像
|
||||
# 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer)
|
||||
pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)
|
||||
|
||||
# 相机模式切换成连续采集
|
||||
mvsdk.CameraSetTriggerMode(hCamera, 0)
|
||||
|
||||
# 手动曝光,曝光时间30ms
|
||||
mvsdk.CameraSetAeState(hCamera, 0)
|
||||
mvsdk.CameraSetExposureTime(hCamera, 30 * 1000)
|
||||
|
||||
# 让SDK内部取图线程开始工作
|
||||
mvsdk.CameraPlay(hCamera)
|
||||
|
||||
self.hCamera = hCamera
|
||||
self.pFrameBuffer = pFrameBuffer
|
||||
self.cap = cap
|
||||
return True
|
||||
|
||||
def close(self):
|
||||
if self.hCamera > 0:
|
||||
mvsdk.CameraUnInit(self.hCamera)
|
||||
self.hCamera = 0
|
||||
|
||||
mvsdk.CameraAlignFree(self.pFrameBuffer)
|
||||
self.pFrameBuffer = 0
|
||||
|
||||
def grab(self):
|
||||
# 从相机取一帧图片
|
||||
hCamera = self.hCamera
|
||||
pFrameBuffer = self.pFrameBuffer
|
||||
try:
|
||||
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 200)
|
||||
mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)
|
||||
mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)
|
||||
|
||||
# windows下取到的图像数据是上下颠倒的,以BMP格式存放。转换成opencv则需要上下翻转成正的
|
||||
# linux下直接输出正的,不需要上下翻转
|
||||
if platform.system() == "Windows":
|
||||
mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1)
|
||||
|
||||
# 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据
|
||||
# 把pFrameBuffer转换成opencv的图像格式以进行后续算法处理
|
||||
frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer)
|
||||
frame = np.frombuffer(frame_data, dtype=np.uint8)
|
||||
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 1 if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8 else 3) )
|
||||
return frame
|
||||
except mvsdk.CameraException as e:
|
||||
if e.error_code != mvsdk.CAMERA_STATUS_TIME_OUT:
|
||||
print("CameraGetImageBuffer failed({}): {}".format(e.error_code, e.message) )
|
||||
return None
|
||||
|
||||
def main_loop():
|
||||
# 枚举相机
|
||||
DevList = mvsdk.CameraEnumerateDevice()
|
||||
nDev = len(DevList)
|
||||
if nDev < 1:
|
||||
print("No camera was found!")
|
||||
return
|
||||
|
||||
for i, DevInfo in enumerate(DevList):
|
||||
print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType()))
|
||||
|
||||
cams = []
|
||||
for i in map(lambda x: int(x), raw_input("Select cameras: ").split()):
|
||||
cam = Camera(DevList[i])
|
||||
if cam.open():
|
||||
cams.append(cam)
|
||||
|
||||
while (cv2.waitKey(1) & 0xFF) != ord('q'):
|
||||
for cam in cams:
|
||||
frame = cam.grab()
|
||||
if frame is not None:
|
||||
frame = cv2.resize(frame, (640,480), interpolation = cv2.INTER_LINEAR)
|
||||
cv2.imshow("{} Press q to end".format(cam.DevInfo.GetFriendlyName()), frame)
|
||||
|
||||
for cam in cams:
|
||||
cam.close()
|
||||
|
||||
def main():
|
||||
try:
|
||||
main_loop()
|
||||
finally:
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,110 @@
|
||||
#coding=utf-8
|
||||
import cv2
|
||||
import numpy as np
|
||||
import mvsdk
|
||||
import time
|
||||
import platform
|
||||
|
||||
class App(object):
|
||||
def __init__(self):
|
||||
super(App, self).__init__()
|
||||
self.pFrameBuffer = 0
|
||||
self.quit = False
|
||||
|
||||
def main(self):
|
||||
# 枚举相机
|
||||
DevList = mvsdk.CameraEnumerateDevice()
|
||||
nDev = len(DevList)
|
||||
if nDev < 1:
|
||||
print("No camera was found!")
|
||||
return
|
||||
|
||||
for i, DevInfo in enumerate(DevList):
|
||||
print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType()))
|
||||
i = 0 if nDev == 1 else int(input("Select camera: "))
|
||||
DevInfo = DevList[i]
|
||||
print(DevInfo)
|
||||
|
||||
# 打开相机
|
||||
hCamera = 0
|
||||
try:
|
||||
hCamera = mvsdk.CameraInit(DevInfo, -1, -1)
|
||||
except mvsdk.CameraException as e:
|
||||
print("CameraInit Failed({}): {}".format(e.error_code, e.message) )
|
||||
return
|
||||
|
||||
# 获取相机特性描述
|
||||
cap = mvsdk.CameraGetCapability(hCamera)
|
||||
|
||||
# 判断是黑白相机还是彩色相机
|
||||
monoCamera = (cap.sIspCapacity.bMonoSensor != 0)
|
||||
|
||||
# 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度
|
||||
if monoCamera:
|
||||
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)
|
||||
else:
|
||||
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_BGR8)
|
||||
|
||||
# 相机模式切换成连续采集
|
||||
mvsdk.CameraSetTriggerMode(hCamera, 0)
|
||||
|
||||
# 手动曝光,曝光时间30ms
|
||||
mvsdk.CameraSetAeState(hCamera, 0)
|
||||
mvsdk.CameraSetExposureTime(hCamera, 30 * 1000)
|
||||
|
||||
# 让SDK内部取图线程开始工作
|
||||
mvsdk.CameraPlay(hCamera)
|
||||
|
||||
# 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配
|
||||
FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)
|
||||
|
||||
# 分配RGB buffer,用来存放ISP输出的图像
|
||||
# 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer)
|
||||
self.pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)
|
||||
|
||||
# 设置采集回调函数
|
||||
self.quit = False
|
||||
mvsdk.CameraSetCallbackFunction(hCamera, self.GrabCallback, 0)
|
||||
|
||||
# 等待退出
|
||||
while not self.quit:
|
||||
time.sleep(0.1)
|
||||
|
||||
# 关闭相机
|
||||
mvsdk.CameraUnInit(hCamera)
|
||||
|
||||
# 释放帧缓存
|
||||
mvsdk.CameraAlignFree(self.pFrameBuffer)
|
||||
|
||||
@mvsdk.method(mvsdk.CAMERA_SNAP_PROC)
|
||||
def GrabCallback(self, hCamera, pRawData, pFrameHead, pContext):
|
||||
FrameHead = pFrameHead[0]
|
||||
pFrameBuffer = self.pFrameBuffer
|
||||
|
||||
mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)
|
||||
mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)
|
||||
|
||||
# windows下取到的图像数据是上下颠倒的,以BMP格式存放。转换成opencv则需要上下翻转成正的
|
||||
# linux下直接输出正的,不需要上下翻转
|
||||
if platform.system() == "Windows":
|
||||
mvsdk.CameraFlipFrameBuffer(pFrameBuffer, FrameHead, 1)
|
||||
|
||||
# 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据
|
||||
# 把pFrameBuffer转换成opencv的图像格式以进行后续算法处理
|
||||
frame_data = (mvsdk.c_ubyte * FrameHead.uBytes).from_address(pFrameBuffer)
|
||||
frame = np.frombuffer(frame_data, dtype=np.uint8)
|
||||
frame = frame.reshape((FrameHead.iHeight, FrameHead.iWidth, 1 if FrameHead.uiMediaType == mvsdk.CAMERA_MEDIA_TYPE_MONO8 else 3) )
|
||||
|
||||
frame = cv2.resize(frame, (640,480), interpolation = cv2.INTER_LINEAR)
|
||||
cv2.imshow("Press q to end", frame)
|
||||
if (cv2.waitKey(1) & 0xFF) == ord('q'):
|
||||
self.quit = True
|
||||
|
||||
def main():
|
||||
try:
|
||||
app = App()
|
||||
app.main()
|
||||
finally:
|
||||
cv2.destroyAllWindows()
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Demo script to show MQTT console logging in action.
|
||||
|
||||
This script demonstrates the enhanced MQTT logging by starting just the MQTT client
|
||||
and showing the console output.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import signal
|
||||
import logging
|
||||
|
||||
# Add the current directory to Python path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from usda_vision_system.core.config import Config
|
||||
from usda_vision_system.core.state_manager import StateManager
|
||||
from usda_vision_system.core.events import EventSystem
|
||||
from usda_vision_system.core.logging_config import setup_logging
|
||||
from usda_vision_system.mqtt.client import MQTTClient
|
||||
|
||||
def signal_handler(signum, frame):
|
||||
"""Handle Ctrl+C gracefully"""
|
||||
print("\n🛑 Stopping MQTT demo...")
|
||||
sys.exit(0)
|
||||
|
||||
def main():
|
||||
"""Main demo function"""
|
||||
print("🚀 MQTT Console Logging Demo")
|
||||
print("=" * 50)
|
||||
print()
|
||||
print("This demo shows enhanced MQTT console logging.")
|
||||
print("You'll see colorful console output for MQTT events:")
|
||||
print(" 🔗 Connection status")
|
||||
print(" 📋 Topic subscriptions")
|
||||
print(" 📡 Incoming messages")
|
||||
print(" ⚠️ Disconnections and errors")
|
||||
print()
|
||||
print("Press Ctrl+C to stop the demo.")
|
||||
print("=" * 50)
|
||||
|
||||
# Setup signal handler
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
try:
|
||||
# Setup logging with INFO level for console visibility
|
||||
setup_logging(log_level="INFO", log_file="mqtt_demo.log")
|
||||
|
||||
# Load configuration
|
||||
config = Config()
|
||||
|
||||
# Initialize components
|
||||
state_manager = StateManager()
|
||||
event_system = EventSystem()
|
||||
|
||||
# Create MQTT client
|
||||
mqtt_client = MQTTClient(config, state_manager, event_system)
|
||||
|
||||
print(f"\n🔧 Configuration:")
|
||||
print(f" Broker: {config.mqtt.broker_host}:{config.mqtt.broker_port}")
|
||||
print(f" Topics: {list(config.mqtt.topics.values())}")
|
||||
print()
|
||||
|
||||
# Start MQTT client
|
||||
print("🚀 Starting MQTT client...")
|
||||
if mqtt_client.start():
|
||||
print("✅ MQTT client started successfully!")
|
||||
print("\n👀 Watching for MQTT messages... (Press Ctrl+C to stop)")
|
||||
print("-" * 50)
|
||||
|
||||
# Keep running and show periodic status
|
||||
start_time = time.time()
|
||||
last_status_time = start_time
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
|
||||
# Show status every 30 seconds
|
||||
current_time = time.time()
|
||||
if current_time - last_status_time >= 30:
|
||||
status = mqtt_client.get_status()
|
||||
uptime = current_time - start_time
|
||||
print(f"\n📊 Status Update (uptime: {uptime:.0f}s):")
|
||||
print(f" Connected: {status['connected']}")
|
||||
print(f" Messages: {status['message_count']}")
|
||||
print(f" Errors: {status['error_count']}")
|
||||
if status['last_message_time']:
|
||||
print(f" Last Message: {status['last_message_time']}")
|
||||
print("-" * 50)
|
||||
last_status_time = current_time
|
||||
|
||||
else:
|
||||
print("❌ Failed to start MQTT client")
|
||||
print(" Check your MQTT broker configuration in config.json")
|
||||
print(" Make sure the broker is running and accessible")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n🛑 Demo stopped by user")
|
||||
except Exception as e:
|
||||
print(f"\n❌ Error: {e}")
|
||||
finally:
|
||||
# Cleanup
|
||||
try:
|
||||
if 'mqtt_client' in locals():
|
||||
mqtt_client.stop()
|
||||
print("🔌 MQTT client stopped")
|
||||
except:
|
||||
pass
|
||||
|
||||
print("\n👋 Demo completed!")
|
||||
print("\n💡 To run the full system with this enhanced logging:")
|
||||
print(" python main.py")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
111
camera-management-api/ai_agent/examples/demos/grab.py
Normal file
111
camera-management-api/ai_agent/examples/demos/grab.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#coding=utf-8
|
||||
import mvsdk
|
||||
|
||||
def main():
|
||||
# 枚举相机
|
||||
DevList = mvsdk.CameraEnumerateDevice()
|
||||
nDev = len(DevList)
|
||||
if nDev < 1:
|
||||
print("No camera was found!")
|
||||
return
|
||||
|
||||
for i, DevInfo in enumerate(DevList):
|
||||
print("{}: {} {}".format(i, DevInfo.GetFriendlyName(), DevInfo.GetPortType()))
|
||||
i = 0 if nDev == 1 else int(input("Select camera: "))
|
||||
DevInfo = DevList[i]
|
||||
print(DevInfo)
|
||||
|
||||
# 打开相机
|
||||
hCamera = 0
|
||||
try:
|
||||
hCamera = mvsdk.CameraInit(DevInfo, -1, -1)
|
||||
except mvsdk.CameraException as e:
|
||||
print("CameraInit Failed({}): {}".format(e.error_code, e.message) )
|
||||
return
|
||||
|
||||
# 获取相机特性描述
|
||||
cap = mvsdk.CameraGetCapability(hCamera)
|
||||
PrintCapbility(cap)
|
||||
|
||||
# 判断是黑白相机还是彩色相机
|
||||
monoCamera = (cap.sIspCapacity.bMonoSensor != 0)
|
||||
|
||||
# 黑白相机让ISP直接输出MONO数据,而不是扩展成R=G=B的24位灰度
|
||||
if monoCamera:
|
||||
mvsdk.CameraSetIspOutFormat(hCamera, mvsdk.CAMERA_MEDIA_TYPE_MONO8)
|
||||
|
||||
# 相机模式切换成连续采集
|
||||
mvsdk.CameraSetTriggerMode(hCamera, 0)
|
||||
|
||||
# 手动曝光,曝光时间30ms
|
||||
mvsdk.CameraSetAeState(hCamera, 0)
|
||||
mvsdk.CameraSetExposureTime(hCamera, 30 * 1000)
|
||||
|
||||
# 让SDK内部取图线程开始工作
|
||||
mvsdk.CameraPlay(hCamera)
|
||||
|
||||
# 计算RGB buffer所需的大小,这里直接按照相机的最大分辨率来分配
|
||||
FrameBufferSize = cap.sResolutionRange.iWidthMax * cap.sResolutionRange.iHeightMax * (1 if monoCamera else 3)
|
||||
|
||||
# 分配RGB buffer,用来存放ISP输出的图像
|
||||
# 备注:从相机传输到PC端的是RAW数据,在PC端通过软件ISP转为RGB数据(如果是黑白相机就不需要转换格式,但是ISP还有其它处理,所以也需要分配这个buffer)
|
||||
pFrameBuffer = mvsdk.CameraAlignMalloc(FrameBufferSize, 16)
|
||||
|
||||
# 从相机取一帧图片
|
||||
try:
|
||||
pRawData, FrameHead = mvsdk.CameraGetImageBuffer(hCamera, 2000)
|
||||
mvsdk.CameraImageProcess(hCamera, pRawData, pFrameBuffer, FrameHead)
|
||||
mvsdk.CameraReleaseImageBuffer(hCamera, pRawData)
|
||||
|
||||
# 此时图片已经存储在pFrameBuffer中,对于彩色相机pFrameBuffer=RGB数据,黑白相机pFrameBuffer=8位灰度数据
|
||||
# 该示例中我们只是把图片保存到硬盘文件中
|
||||
status = mvsdk.CameraSaveImage(hCamera, "./grab.bmp", pFrameBuffer, FrameHead, mvsdk.FILE_BMP, 100)
|
||||
if status == mvsdk.CAMERA_STATUS_SUCCESS:
|
||||
print("Save image successfully. image_size = {}X{}".format(FrameHead.iWidth, FrameHead.iHeight) )
|
||||
else:
|
||||
print("Save image failed. err={}".format(status) )
|
||||
except mvsdk.CameraException as e:
|
||||
print("CameraGetImageBuffer failed({}): {}".format(e.error_code, e.message) )
|
||||
|
||||
# 关闭相机
|
||||
mvsdk.CameraUnInit(hCamera)
|
||||
|
||||
# 释放帧缓存
|
||||
mvsdk.CameraAlignFree(pFrameBuffer)
|
||||
|
||||
def PrintCapbility(cap):
|
||||
for i in range(cap.iTriggerDesc):
|
||||
desc = cap.pTriggerDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iImageSizeDesc):
|
||||
desc = cap.pImageSizeDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iClrTempDesc):
|
||||
desc = cap.pClrTempDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iMediaTypeDesc):
|
||||
desc = cap.pMediaTypeDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iFrameSpeedDesc):
|
||||
desc = cap.pFrameSpeedDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iPackLenDesc):
|
||||
desc = cap.pPackLenDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iPresetLut):
|
||||
desc = cap.pPresetLutDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iAeAlmSwDesc):
|
||||
desc = cap.pAeAlmSwDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iAeAlmHdDesc):
|
||||
desc = cap.pAeAlmHdDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iBayerDecAlmSwDesc):
|
||||
desc = cap.pBayerDecAlmSwDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
for i in range(cap.iBayerDecAlmHdDesc):
|
||||
desc = cap.pBayerDecAlmHdDesc[i]
|
||||
print("{}: {}".format(desc.iIndex, desc.GetDescription()) )
|
||||
|
||||
main()
|
||||
@@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
MQTT Publisher Test Script for USDA Vision Camera System
|
||||
|
||||
This script allows you to manually publish test messages to the MQTT topics
|
||||
to simulate machine state changes for testing purposes.
|
||||
|
||||
Usage:
|
||||
python mqtt_publisher_test.py
|
||||
|
||||
The script provides an interactive menu to:
|
||||
1. Send 'on' state to vibratory conveyor
|
||||
2. Send 'off' state to vibratory conveyor
|
||||
3. Send 'on' state to blower separator
|
||||
4. Send 'off' state to blower separator
|
||||
5. Send custom message
|
||||
"""
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
import time
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
# MQTT Configuration (matching your system config)
|
||||
MQTT_BROKER_HOST = "192.168.1.110"
|
||||
MQTT_BROKER_PORT = 1883
|
||||
MQTT_USERNAME = None # Set if your broker requires authentication
|
||||
MQTT_PASSWORD = None # Set if your broker requires authentication
|
||||
|
||||
# Topics (from your config.json)
|
||||
MQTT_TOPICS = {
|
||||
"vibratory_conveyor": "vision/vibratory_conveyor/state",
|
||||
"blower_separator": "vision/blower_separator/state"
|
||||
}
|
||||
|
||||
class MQTTPublisher:
|
||||
def __init__(self):
|
||||
self.client = None
|
||||
self.connected = False
|
||||
|
||||
def setup_client(self):
|
||||
"""Setup MQTT client"""
|
||||
try:
|
||||
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1)
|
||||
self.client.on_connect = self.on_connect
|
||||
self.client.on_disconnect = self.on_disconnect
|
||||
self.client.on_publish = self.on_publish
|
||||
|
||||
if MQTT_USERNAME and MQTT_PASSWORD:
|
||||
self.client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"❌ Error setting up MQTT client: {e}")
|
||||
return False
|
||||
|
||||
def connect(self):
|
||||
"""Connect to MQTT broker"""
|
||||
try:
|
||||
print(f"🔗 Connecting to MQTT broker at {MQTT_BROKER_HOST}:{MQTT_BROKER_PORT}...")
|
||||
self.client.connect(MQTT_BROKER_HOST, MQTT_BROKER_PORT, 60)
|
||||
self.client.loop_start() # Start background loop
|
||||
|
||||
# Wait for connection
|
||||
timeout = 10
|
||||
start_time = time.time()
|
||||
while not self.connected and (time.time() - start_time) < timeout:
|
||||
time.sleep(0.1)
|
||||
|
||||
return self.connected
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to connect to MQTT broker: {e}")
|
||||
return False
|
||||
|
||||
def disconnect(self):
|
||||
"""Disconnect from MQTT broker"""
|
||||
if self.client:
|
||||
self.client.loop_stop()
|
||||
self.client.disconnect()
|
||||
|
||||
def on_connect(self, client, userdata, flags, rc):
|
||||
"""Callback when client connects"""
|
||||
if rc == 0:
|
||||
self.connected = True
|
||||
print(f"✅ Connected to MQTT broker successfully!")
|
||||
else:
|
||||
self.connected = False
|
||||
print(f"❌ Connection failed with return code {rc}")
|
||||
|
||||
def on_disconnect(self, client, userdata, rc):
|
||||
"""Callback when client disconnects"""
|
||||
self.connected = False
|
||||
print(f"🔌 Disconnected from MQTT broker")
|
||||
|
||||
def on_publish(self, client, userdata, mid):
|
||||
"""Callback when message is published"""
|
||||
print(f"📤 Message published successfully (mid: {mid})")
|
||||
|
||||
def publish_message(self, topic, payload):
|
||||
"""Publish a message to a topic"""
|
||||
if not self.connected:
|
||||
print("❌ Not connected to MQTT broker")
|
||||
return False
|
||||
|
||||
try:
|
||||
timestamp = datetime.now().strftime('%H:%M:%S.%f')[:-3]
|
||||
print(f"📡 [{timestamp}] Publishing message:")
|
||||
print(f" 📍 Topic: {topic}")
|
||||
print(f" 📄 Payload: '{payload}'")
|
||||
|
||||
result = self.client.publish(topic, payload)
|
||||
|
||||
if result.rc == mqtt.MQTT_ERR_SUCCESS:
|
||||
print(f"✅ Message queued for publishing")
|
||||
return True
|
||||
else:
|
||||
print(f"❌ Failed to publish message (error: {result.rc})")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error publishing message: {e}")
|
||||
return False
|
||||
|
||||
def show_menu(self):
|
||||
"""Show interactive menu"""
|
||||
print("\n" + "=" * 50)
|
||||
print("🎛️ MQTT PUBLISHER TEST MENU")
|
||||
print("=" * 50)
|
||||
print("1. Send 'on' to vibratory conveyor")
|
||||
print("2. Send 'off' to vibratory conveyor")
|
||||
print("3. Send 'on' to blower separator")
|
||||
print("4. Send 'off' to blower separator")
|
||||
print("5. Send custom message")
|
||||
print("6. Show current topics")
|
||||
print("0. Exit")
|
||||
print("-" * 50)
|
||||
|
||||
def handle_menu_choice(self, choice):
|
||||
"""Handle menu selection"""
|
||||
if choice == "1":
|
||||
self.publish_message(MQTT_TOPICS["vibratory_conveyor"], "on")
|
||||
elif choice == "2":
|
||||
self.publish_message(MQTT_TOPICS["vibratory_conveyor"], "off")
|
||||
elif choice == "3":
|
||||
self.publish_message(MQTT_TOPICS["blower_separator"], "on")
|
||||
elif choice == "4":
|
||||
self.publish_message(MQTT_TOPICS["blower_separator"], "off")
|
||||
elif choice == "5":
|
||||
self.custom_message()
|
||||
elif choice == "6":
|
||||
self.show_topics()
|
||||
elif choice == "0":
|
||||
return False
|
||||
else:
|
||||
print("❌ Invalid choice. Please try again.")
|
||||
|
||||
return True
|
||||
|
||||
def custom_message(self):
|
||||
"""Send custom message"""
|
||||
print("\n📝 Custom Message")
|
||||
print("Available topics:")
|
||||
for i, (name, topic) in enumerate(MQTT_TOPICS.items(), 1):
|
||||
print(f" {i}. {name}: {topic}")
|
||||
|
||||
try:
|
||||
topic_choice = input("Select topic (1-2): ").strip()
|
||||
if topic_choice == "1":
|
||||
topic = MQTT_TOPICS["vibratory_conveyor"]
|
||||
elif topic_choice == "2":
|
||||
topic = MQTT_TOPICS["blower_separator"]
|
||||
else:
|
||||
print("❌ Invalid topic choice")
|
||||
return
|
||||
|
||||
payload = input("Enter message payload: ").strip()
|
||||
if payload:
|
||||
self.publish_message(topic, payload)
|
||||
else:
|
||||
print("❌ Empty payload, message not sent")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n❌ Cancelled")
|
||||
|
||||
def show_topics(self):
|
||||
"""Show configured topics"""
|
||||
print("\n📋 Configured Topics:")
|
||||
for name, topic in MQTT_TOPICS.items():
|
||||
print(f" 🏭 {name}: {topic}")
|
||||
|
||||
def run(self):
|
||||
"""Main interactive loop"""
|
||||
print("📤 MQTT Publisher Test")
|
||||
print("=" * 50)
|
||||
print(f"🎯 Broker: {MQTT_BROKER_HOST}:{MQTT_BROKER_PORT}")
|
||||
|
||||
if not self.setup_client():
|
||||
return False
|
||||
|
||||
if not self.connect():
|
||||
print("❌ Failed to connect to MQTT broker")
|
||||
return False
|
||||
|
||||
try:
|
||||
while True:
|
||||
self.show_menu()
|
||||
choice = input("Enter your choice: ").strip()
|
||||
|
||||
if not self.handle_menu_choice(choice):
|
||||
break
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n\n🛑 Interrupted by user")
|
||||
except Exception as e:
|
||||
print(f"\n❌ Error: {e}")
|
||||
finally:
|
||||
self.disconnect()
|
||||
print("👋 Goodbye!")
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
publisher = MQTTPublisher()
|
||||
|
||||
try:
|
||||
publisher.run()
|
||||
except Exception as e:
|
||||
print(f"❌ Unexpected error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
242
camera-management-api/ai_agent/examples/demos/mqtt_test.py
Normal file
242
camera-management-api/ai_agent/examples/demos/mqtt_test.py
Normal file
@@ -0,0 +1,242 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
MQTT Test Script for USDA Vision Camera System
|
||||
|
||||
This script tests MQTT message reception by connecting to the broker
|
||||
and listening for messages on the configured topics.
|
||||
|
||||
Usage:
|
||||
python mqtt_test.py
|
||||
|
||||
The script will:
|
||||
1. Connect to the MQTT broker
|
||||
2. Subscribe to all configured topics
|
||||
3. Display received messages with timestamps
|
||||
4. Show connection status and statistics
|
||||
"""
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
import time
|
||||
import json
|
||||
import signal
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from typing import Dict, Optional
|
||||
|
||||
# MQTT Configuration (matching your system config)
|
||||
MQTT_BROKER_HOST = "192.168.1.110"
|
||||
MQTT_BROKER_PORT = 1883
|
||||
MQTT_USERNAME = None # Set if your broker requires authentication
|
||||
MQTT_PASSWORD = None # Set if your broker requires authentication
|
||||
|
||||
# Topics to monitor (from your config.json)
|
||||
MQTT_TOPICS = {
|
||||
"vibratory_conveyor": "vision/vibratory_conveyor/state",
|
||||
"blower_separator": "vision/blower_separator/state"
|
||||
}
|
||||
|
||||
class MQTTTester:
|
||||
def __init__(self):
|
||||
self.client: Optional[mqtt.Client] = None
|
||||
self.connected = False
|
||||
self.message_count = 0
|
||||
self.start_time = None
|
||||
self.last_message_time = None
|
||||
self.received_messages = []
|
||||
|
||||
def setup_client(self):
|
||||
"""Setup MQTT client with callbacks"""
|
||||
try:
|
||||
# Create MQTT client
|
||||
self.client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION1)
|
||||
|
||||
# Set callbacks
|
||||
self.client.on_connect = self.on_connect
|
||||
self.client.on_disconnect = self.on_disconnect
|
||||
self.client.on_message = self.on_message
|
||||
self.client.on_subscribe = self.on_subscribe
|
||||
|
||||
# Set authentication if provided
|
||||
if MQTT_USERNAME and MQTT_PASSWORD:
|
||||
self.client.username_pw_set(MQTT_USERNAME, MQTT_PASSWORD)
|
||||
print(f"🔐 Using authentication: {MQTT_USERNAME}")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error setting up MQTT client: {e}")
|
||||
return False
|
||||
|
||||
def connect(self):
|
||||
"""Connect to MQTT broker"""
|
||||
try:
|
||||
print(f"🔗 Connecting to MQTT broker at {MQTT_BROKER_HOST}:{MQTT_BROKER_PORT}...")
|
||||
self.client.connect(MQTT_BROKER_HOST, MQTT_BROKER_PORT, 60)
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to connect to MQTT broker: {e}")
|
||||
return False
|
||||
|
||||
def on_connect(self, client, userdata, flags, rc):
|
||||
"""Callback when client connects to broker"""
|
||||
if rc == 0:
|
||||
self.connected = True
|
||||
self.start_time = datetime.now()
|
||||
print(f"✅ Successfully connected to MQTT broker!")
|
||||
print(f"📅 Connection time: {self.start_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print()
|
||||
|
||||
# Subscribe to all topics
|
||||
print("📋 Subscribing to topics:")
|
||||
for machine_name, topic in MQTT_TOPICS.items():
|
||||
result, mid = client.subscribe(topic)
|
||||
if result == mqtt.MQTT_ERR_SUCCESS:
|
||||
print(f" ✅ {machine_name}: {topic}")
|
||||
else:
|
||||
print(f" ❌ {machine_name}: {topic} (error: {result})")
|
||||
|
||||
print()
|
||||
print("🎧 Listening for MQTT messages...")
|
||||
print(" (Manually turn machines on/off to trigger messages)")
|
||||
print(" (Press Ctrl+C to stop)")
|
||||
print("-" * 60)
|
||||
|
||||
else:
|
||||
self.connected = False
|
||||
print(f"❌ Connection failed with return code {rc}")
|
||||
print(" Return codes:")
|
||||
print(" 0: Connection successful")
|
||||
print(" 1: Connection refused - incorrect protocol version")
|
||||
print(" 2: Connection refused - invalid client identifier")
|
||||
print(" 3: Connection refused - server unavailable")
|
||||
print(" 4: Connection refused - bad username or password")
|
||||
print(" 5: Connection refused - not authorised")
|
||||
|
||||
def on_disconnect(self, client, userdata, rc):
|
||||
"""Callback when client disconnects from broker"""
|
||||
self.connected = False
|
||||
if rc != 0:
|
||||
print(f"🔌 Unexpected disconnection from MQTT broker (code: {rc})")
|
||||
else:
|
||||
print(f"🔌 Disconnected from MQTT broker")
|
||||
|
||||
def on_subscribe(self, client, userdata, mid, granted_qos):
|
||||
"""Callback when subscription is confirmed"""
|
||||
print(f"📋 Subscription confirmed (mid: {mid}, QoS: {granted_qos})")
|
||||
|
||||
def on_message(self, client, userdata, msg):
|
||||
"""Callback when a message is received"""
|
||||
try:
|
||||
# Decode message
|
||||
topic = msg.topic
|
||||
payload = msg.payload.decode("utf-8").strip()
|
||||
timestamp = datetime.now()
|
||||
|
||||
# Update statistics
|
||||
self.message_count += 1
|
||||
self.last_message_time = timestamp
|
||||
|
||||
# Find machine name
|
||||
machine_name = "unknown"
|
||||
for name, configured_topic in MQTT_TOPICS.items():
|
||||
if topic == configured_topic:
|
||||
machine_name = name
|
||||
break
|
||||
|
||||
# Store message
|
||||
message_data = {
|
||||
"timestamp": timestamp,
|
||||
"topic": topic,
|
||||
"machine": machine_name,
|
||||
"payload": payload,
|
||||
"message_number": self.message_count
|
||||
}
|
||||
self.received_messages.append(message_data)
|
||||
|
||||
# Display message
|
||||
time_str = timestamp.strftime('%H:%M:%S.%f')[:-3] # Include milliseconds
|
||||
print(f"📡 [{time_str}] Message #{self.message_count}")
|
||||
print(f" 🏭 Machine: {machine_name}")
|
||||
print(f" 📍 Topic: {topic}")
|
||||
print(f" 📄 Payload: '{payload}'")
|
||||
print(f" 📊 Total messages: {self.message_count}")
|
||||
print("-" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error processing message: {e}")
|
||||
|
||||
def show_statistics(self):
|
||||
"""Show connection and message statistics"""
|
||||
print("\n" + "=" * 60)
|
||||
print("📊 MQTT TEST STATISTICS")
|
||||
print("=" * 60)
|
||||
|
||||
if self.start_time:
|
||||
runtime = datetime.now() - self.start_time
|
||||
print(f"⏱️ Runtime: {runtime}")
|
||||
|
||||
print(f"🔗 Connected: {'Yes' if self.connected else 'No'}")
|
||||
print(f"📡 Messages received: {self.message_count}")
|
||||
|
||||
if self.last_message_time:
|
||||
print(f"🕐 Last message: {self.last_message_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
|
||||
if self.received_messages:
|
||||
print(f"\n📋 Message Summary:")
|
||||
for msg in self.received_messages[-5:]: # Show last 5 messages
|
||||
time_str = msg["timestamp"].strftime('%H:%M:%S')
|
||||
print(f" [{time_str}] {msg['machine']}: {msg['payload']}")
|
||||
|
||||
print("=" * 60)
|
||||
|
||||
def run(self):
|
||||
"""Main test loop"""
|
||||
print("🧪 MQTT Message Reception Test")
|
||||
print("=" * 60)
|
||||
print(f"🎯 Broker: {MQTT_BROKER_HOST}:{MQTT_BROKER_PORT}")
|
||||
print(f"📋 Topics: {list(MQTT_TOPICS.values())}")
|
||||
print()
|
||||
|
||||
# Setup signal handler for graceful shutdown
|
||||
def signal_handler(sig, frame):
|
||||
print(f"\n\n🛑 Received interrupt signal, shutting down...")
|
||||
self.show_statistics()
|
||||
if self.client and self.connected:
|
||||
self.client.disconnect()
|
||||
sys.exit(0)
|
||||
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
|
||||
# Setup and connect
|
||||
if not self.setup_client():
|
||||
return False
|
||||
|
||||
if not self.connect():
|
||||
return False
|
||||
|
||||
# Start the client loop
|
||||
try:
|
||||
self.client.loop_forever()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"❌ Error in main loop: {e}")
|
||||
|
||||
return True
|
||||
|
||||
def main():
|
||||
"""Main function"""
|
||||
tester = MQTTTester()
|
||||
|
||||
try:
|
||||
success = tester.run()
|
||||
if not success:
|
||||
print("❌ Test failed")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"❌ Unexpected error: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
4
camera-management-api/ai_agent/examples/demos/readme.txt
Normal file
4
camera-management-api/ai_agent/examples/demos/readme.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
mvsdk.py: 相机SDK接口库(参考文档 WindowsSDK安装目录\Document\MVSDK_API_CHS.chm)
|
||||
|
||||
grab.py: 使用SDK采集图片,并保存到硬盘文件
|
||||
cv_grab.py: 使用SDK采集图片,转换为opencv的图像格式
|
||||
Reference in New Issue
Block a user