From db7c8c45771d8d3818e8ee32c365464faab1bbba Mon Sep 17 00:00:00 2001 From: Cole Deck Date: Sat, 17 Feb 2024 20:06:37 -0600 Subject: [PATCH] Add video abstraction class --- banner_ivu_export.py | 166 +++++++++++++++++++++++++++++++++++++++++++ config.yml | 6 ++ led_control.py | 4 +- process_video.py | 45 ++++++++++++ run.py | 26 +++++-- server.py | 27 ++++--- util.py | 8 +-- 7 files changed, 259 insertions(+), 23 deletions(-) create mode 100755 banner_ivu_export.py create mode 100755 process_video.py diff --git a/banner_ivu_export.py b/banner_ivu_export.py new file mode 100755 index 0000000..cb61bb5 --- /dev/null +++ b/banner_ivu_export.py @@ -0,0 +1,166 @@ +#!/usr/bin/env python3 + +import socket +from datetime import datetime +from time import sleep +from util import fprint + +""" + +from: https://github.com/MoisesBrito31/ve_data_log/blob/main/serverContagem/VE/drive.py +(no license) + +(partially) adapted to English language & iVu camera instead of classic VE by Cole Deck + +""" + +def gravaLog(ip="1",tipo="Evento", msg="", file="log_imagem.txt"): + # removed full logging + fprint(msg) + +class DriveImg(): + HEADERSIZE = 100 + ip = "192.168.0.1" + port = 32200 + onLine = False + + def __init__(self, ip, port, pasta = "media/"): + self.pasta = pasta + self.ip=ip + self.port = port + self.trans = socket.socket(socket.AF_INET,socket.SOCK_STREAM) + self.trans.settimeout(5) + fprint("Trying to connect...") + try: + self.trans.connect((self.ip,self.port)) + self.onLine = True + fprint("Camera Online") + #self.trans.close() + except: + self.onLine = False + fprint("Offline") + + def read_img(self): + resposta = 'Falha' + try: + if not self.onLine: + #print(f'tentando Conectar camera {self.ip}...') + gravaLog(ip=self.ip,msg=f'Trying to connect...') + sleep(2) + try: + self.trans = socket.socket(socket.AF_INET,socket.SOCK_STREAM) + self.trans.connect((self.ip,self.PORT)) + self.onLine = True + gravaLog(ip=self.ip,msg=f'Connection established.') + except: + self.onLine = False + self.trans.close() + return resposta + ret = self.trans.recv(64) + try: + valida = str(ret[0:15].decode('UTF-8')) + #print(valida) + if valida.find("TC IMAGE")<0: + self.onLine = False + self.trans.close() + sleep(2) + gravaLog(ip=self.ip,tipo="Falha",msg=f'Unable to find TC IMAGE bookmark') + return "Error" + except Exception as ex: + self.onLine = False + self.trans.close() + sleep(2) + gravaLog(ip=self.ip,tipo="Falha",msg=f'Error - {str(ex)}') + return "Error" + if ret: + frame = int.from_bytes(ret[24:27],"little") + isJpeg = int.from_bytes(ret[32:33],"little") + img_size = int.from_bytes(ret[20:23],"little") + data = self.trans.recv(5000) + while img_size>len(data) and ret: + ret = self.trans.recv(10000) + if ret: + data = data+ret + #print(f'{len(ret)}b dados recebidos, total de: {len(data)+64}b') + else: + gravaLog(ip=self.ip,tipo="Falha",msg="Unable to recieve the image") + self.onLine = False + return "Unable to recieve the image" + hoje = datetime.now() + idcam = self.ip.split('.') + """try: + nomeFile = f'{hoje.day}{hoje.month}{hoje.year}-{idcam[3]}-{frame}' + if isJpeg==1: + file = open(f'{self.pasta}{nomeFile}.jpg','wb') + nomeFile = f'{nomeFile}.jpg' + else: + file = open(f'{self.pasta}{nomeFile}.bmp','wb') + nomeFile = f'{nomeFile}.bmp' + file.write(data) + file.close() + except Exception as ex: + sleep(2) + gravaLog(ip=self.ip,tipo="Falha",msg=f'Error - {str(ex)}') + return "Falha" + """ + if isJpeg==1: + return "jpeg",data + else: + return "bmp",data + + except Exception as ex: + gravaLog(ip=self.ip,tipo="Falha Generica",msg=f'Error - {str(ex)}') + #print(f'erro {str(ex)}') + self.onLine = False + self.trans.close() + sleep(2) + return resposta + +class DriveData(): + HEADERSIZE = 100 + ip = "192.168.0.1" + port = 32100 + onLine = False + + def __init__(self, ip, port): + gravaLog(ip=self.ip,msg=f'iniciou drive',file="log_data.txt") + self.ip=ip + self.port = port + self.trans = socket.socket(socket.AF_INET,socket.SOCK_STREAM) + try: + self.trans.connect((self.ip,self.port)) + self.onLine = True + except: + self.onLine = False + + def read_data(self): + resposta = 'falha' + try: + if not self.onLine: + #print(f'tentando Conectar...\n') + gravaLog(ip=self.ip,msg=f'tentando Conectar...',file="log_data.txt") + sleep(2) + try: + self.trans = socket.socket(socket.AF_INET,socket.SOCK_STREAM) + self.trans.connect((self.ip,self.PORT)) + self.onLine = True + gravaLog(ip=self.ip,msg=f'Conexão restabelecida...',file="log_data.txt") + except: + self.onLine = False + return resposta + resposta = self.trans.recv(self.HEADERSIZE).decode("utf-8") + resposta = str(resposta).split(',') + return resposta + except Exception as ex: + self.onLine = False + gravaLog(ip=self.ip,tipo="Falha Generica",msg=f'erro {str(ex)}',file="log_data.txt") + sleep(2) + return resposta + + +if __name__ == "__main__": + test = DriveImg("192.168.1.125", 32200) + x = 0 + while x < 100: + x=x+1 + imgtype, img = test.read_img() \ No newline at end of file diff --git a/config.yml b/config.yml index 6c86f16..a04918a 100644 --- a/config.yml +++ b/config.yml @@ -7,6 +7,12 @@ core: arm: ip: 192.168.1.145 +#cable_map: +cameras: + banner: + ip: 192.168.1.125 + port: 32200 + led: fps: 90 timeout: 0 diff --git a/led_control.py b/led_control.py index 4a55fff..b208480 100755 --- a/led_control.py +++ b/led_control.py @@ -170,7 +170,7 @@ def init(): data = list() for x in range(len(leds)): if leds_size[x] == 3: - data.append((50,50,255)) + data.append((20,20,127)) elif leds_size[x] == 4: data.append((50,50,255,0)) else: @@ -290,7 +290,7 @@ def close(): time.sleep(0.5) sender.stop() -def mapimage(image, fps=30): +def mapimage(image, fps=60): global start while uptime() - start < 1/fps: time.sleep(0.00001) diff --git a/process_video.py b/process_video.py new file mode 100755 index 0000000..42b020a --- /dev/null +++ b/process_video.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 + +import cv2 +import banner_ivu_export +import numpy as np +from util import fprint + +class qr_reader(): + camera = None + def __init__(self, ip, port): + self.camera = banner_ivu_export.DriveImg(ip, port) + + def read_qr(self, tries=1): + print("Trying " + str(tries) + " frames.") + for x in range(tries): + try: + imgtype, img = self.camera.read_img() + #fprint(imgtype) + image_array = np.frombuffer(img, np.uint8) + img = cv2.imdecode(image_array, cv2.IMREAD_COLOR) + #cv2.imshow('Image', img) + #cv2.waitKey(1) + detect = cv2.QRCodeDetector() + value, points, straight_qrcode = detect.detectAndDecode(img) + return value + except: + continue + return False + + +class video_streamer(): + camera = None + def __init__(self, ip, port): + self.camera = banner_ivu_export.DriveImg(ip, port) + + def get_frame(self): + try: + return self.camera.read_img() + except: + return False + +if __name__ == "__main__": + test = qr_reader("192.168.1.125", 32200) + while True: + fprint(test.read_qr(5)) \ No newline at end of file diff --git a/run.py b/run.py index 287e4fc..e2bedef 100755 --- a/run.py +++ b/run.py @@ -21,6 +21,7 @@ import led_control import server import asyncio import json +import process_video @@ -34,6 +35,7 @@ vm_ready = False killme = None #pool = None serverproc = None +camera = None to_server_queue = Queue() from_server_queue = Queue() @@ -78,7 +80,7 @@ def start_server_socket(): app.run(host='0.0.0.0', port=5000)""" global to_server_queue global from_server_queue - + fprint("Starting WebSocket server...") websocket_process = server.start_websocket_server(to_server_queue, from_server_queue) # Example @@ -86,9 +88,10 @@ def start_server_socket(): while True: + #print("HI") if not from_server_queue.empty(): - message = from_server_queue.get() - fprint(f"Message from client: {message}") + client_id, message = from_server_queue.get() + fprint(f"Message from client {client_id}: {message}") # Message handler try: @@ -141,6 +144,13 @@ def start_server_socket(): fprint("") elif call == "request": fprint("") + if data["enabled"] == True: + # todo : send this to client + p = Process(target=run_cmd, args=("./keyboard-up.ps1",)) + p.start() + elif data["enabled"] == False: + p = Process(target=run_cmd, args=("./keyboard-down.ps1",)) + p.start() case "machine_settings": fprint("machine_settings message") @@ -202,10 +212,10 @@ def setup_server(pool): global led_ready global arm_ready global serverproc + global camera pool.apply_async(ur5_control.init, (config["arm"]["ip"],), callback=arm_start_callback) pool.apply_async(led_control.init, callback=led_start_callback) - #pool.apply_async(camera_control.init, callback=camera_start_callback) #pool.apply_async(sensor_control.init, callback=sensor_start_callback) serverproc = Process(target=start_server_socket) serverproc.start() @@ -225,10 +235,11 @@ def setup_server(pool): if camera_ready is False: fprint("waiting for " + "Camera initilization" + " to complete...", sendqueue=to_server_queue) - while camera_ready is False: - sleep(0.1) + camera = process_video.qr_reader(config["cameras"]["banner"]["ip"], config["cameras"]["banner"]["port"]) + fprint("Camera initialized.", sendqueue=to_server_queue) + arm_ready = True if arm_ready is False: fprint("waiting for " + "UR5 initilization" + " to complete...", sendqueue=to_server_queue) while arm_ready is False: @@ -251,6 +262,9 @@ def mainloop_server(pool): killall() counter = counter + 1 + fprint("Looking for QR code...") + print(camera.read_qr(30)) + def run_loading_app(): app = Flask(__name__) diff --git a/server.py b/server.py index 63ff41c..17dab98 100755 --- a/server.py +++ b/server.py @@ -50,32 +50,37 @@ def run_server(): import asyncio import websockets from multiprocessing import Process, Queue +from util import fprint +import uuid -connected_clients = set() +connected_clients = {} async def handler(websocket, path, to_server_queue, from_server_queue): # Register websocket connection - connected_clients.add(websocket) + client_id = str(uuid.uuid4()) + connected_clients[client_id] = websocket try: # Handle incoming messages async for message in websocket: #print(f"Received message: {message}") - from_server_queue.put(message) # Put received message into from_server_queue + print(client_id) + from_server_queue.put((client_id, message)) finally: # Unregister websocket connection - connected_clients.remove(websocket) + if client_id in connected_clients: + del connected_clients[client_id] + print(f"Client {client_id} connection closed") async def send_messages(to_server_queue): while True: if not to_server_queue.empty(): - message = to_server_queue.get() - if connected_clients: # Check if there are any connected clients - #await asyncio.wait([client.send(message) for client in connected_clients]) - #await [client.send(message) for client in connected_clients] - for client in connected_clients: + client_id, message = to_server_queue.get() + if client_id in connected_clients: # Send message to specific client + await connected_clients[client_id].send(message) + elif len(connected_clients) > 0: # Broadcast message to all clients + for client in connected_clients.values(): await client.send(message) - - await asyncio.sleep(0.1) # Prevent the loop from running too fast + await asyncio.sleep(0.001) def websocket_server(to_server_queue, from_server_queue): start_server = websockets.serve(lambda ws, path: handler(ws, path, to_server_queue, from_server_queue), "localhost", 9000) diff --git a/util.py b/util.py index 77b9c91..f4eaa09 100755 --- a/util.py +++ b/util.py @@ -62,7 +62,7 @@ def fprint(msg, settings = None, sendqueue = None): print(logMsg) if (sendqueue is not None): - sendqueue.put("{ \"type\": \"log\", \"call\":\"send\", \"data\": \"" + logMsg + "\" }") + sendqueue.put(("*", "{ \"type\": \"log\", \"call\":\"send\", \"data\": \"" + logMsg + "\" }")) if (settings is not None): tmpList = settings["logMsg"] tmpList.append(logMsg) @@ -111,9 +111,9 @@ def run_cmd(cmd): return completed def setup_child(sets=None): - #if not getattr(sys, "frozen", False): - # sys.stdout = Logger(filename=find_data_file("output.log")) - # sys.stderr = Logger(filename=find_data_file("output.log")) + if not getattr(sys, "frozen", False): + sys.stdout = Logger(filename=find_data_file("output.log")) + sys.stderr = Logger(filename=find_data_file("output.log")) if sets is not None: settings = sets