Skip to content

Commit

Permalink
⚗️ #1 Failing to run both webserver and websockets at a time.
Browse files Browse the repository at this point in the history
  • Loading branch information
Balaji-Ganesh committed Jun 14, 2023
1 parent 0efb628 commit 2e2d7cc
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 37 deletions.
26 changes: 18 additions & 8 deletions app/middleware/communication/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,50 @@
from flask_socketio import SocketIO



class ESP32Communication:
def __init__(self) -> None:
# these get initialized properly in their respective methods
self.cameraws = None

async def _establish_esp32connection(self):
global camera_ws, data_ws # defining as global, as to be used in other file
try:
self.camera_ws = await websockets.connect(self.camera_ws_url)
print("{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ [ESP32 communication establishment] }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}")
# if hasattr(self, 'cameraws'):
self.cameraws = await websockets.connect(self.camera_ws_url)
self.data_ws = await websockets.connect(self.data_txrx_url)
logging.debug(
"comm: Connection to ESP32 established successfully..!!")
print("{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ [ESP32 communication established ..!!!!!!!!!!!] }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}")
except websockets.exceptions.ConnectionClosedError:
logging.error(
"comm: Cannot connect to ESP32. Try the following solutions..")
logging.error(
"comm: Please ensure that ESP32 is powered on. IP address (of same network) of ESP32 is properly entered.")
except Exception as e:
logging.error("comm: error: ", e)
# print(self.cameraws)

def init_communication(self, ip: str, cam_port: int = 81, data_port: int = 82):
# set it to the assigned IP address to ESP32 when connected to WiFi.
self.esp32_ip = ip
# configured ports for camera and data-transfer in ESP32.
self.camera_port, self.data_port = cam_port, data_port
self.camera_ws_url = "ws://"+self.esp32_ip+":" + \
self.camera_ws_url:str = "ws://"+self.esp32_ip+":" + \
str(self.camera_port) # url of camera websockets
# url of data transfer websockets
self.data_txrx_url = "ws://"+self.esp32_ip+":"+str(self.data_port)
self.data_txrx_url:str = "ws://"+self.esp32_ip+":"+str(self.data_port)

logging.debug('ESP32 communication setup done')

logging.debug(
f'Proceeding to establish communication with IP: {self.esp32_ip} and ports {self.camera_port}, {self.data_port}')
asyncio.get_event_loop().run_until_complete(self._establish_esp32connection())
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(self._establish_esp32connection())
logging.debug('Connection with ESP32 is established successfully');

# import other utility modules
from .esp32_communicator import get_cam_feed
# from .esp32_communicator import get_cam_feed


class WebCommunication:
Expand All @@ -64,6 +73,7 @@ def init_communication(self, socketio):
self.sock.on_event('ack', self.handle_ack)
self.sock.on_event('stream', self.handle_stream)


# Defining globally to enable accessiblity to other modules.
web_comm = WebCommunication()
esp32_comm = ESP32Communication()
11 changes: 6 additions & 5 deletions app/middleware/communication/esp32_communicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# Camera related..


async def get_cam_feed(self):
async def get_cam_feed():
"""This function with the established websocket, gets the cam feed form ESP32.
Usage: Just call this function as like some generator in loop to get the feed.
Expand All @@ -26,18 +26,18 @@ async def get_cam_feed(self):
cv2 image: Frames sent by ESP32
"""
logging.debug("esp32: Proceeding to begin stream from ESP32....")
from . import web_comm
from . import web_comm, esp32_comm
try:
logging.debug("esp32: Stream begins from ESP32....")
while True:
msg = await self.camera_ws.recv()
msg = await esp32_comm.cameraws.recv()
logging.debug("esp32: Received frame from esp32")
# even try with msg.data
npimg = np.array(bytearray(msg), dtype=np.uint8)
# print(npimg)
img = cv2.imdecode(npimg, -1)
cv2.imshow("img", img)
# send the image to web-app
# send the image to web-app -- encoding, do as did for the webcam
# frame = cv2.imencode('.jpg', img)[1].tobytes()
# frame = base64.encodebytes(frame).decode("utf-8")
# web_comm.sock.emit('img_data', frame)
Expand All @@ -53,4 +53,5 @@ async def get_cam_feed(self):
print("Exception type: ", type(e))
logging.error("esp32: error: ", e)
finally:
await self.camera_ws.close()
# await esp32_comm.cameraws.close()
pass
53 changes: 30 additions & 23 deletions app/middleware/communication/web_communicator.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import cv2
import base64


def handle_connect(self, ):
print("[DEBUG] web: Client connected successfully")
self.sock.send({'ack': "Connection established"})
Expand All @@ -22,42 +23,48 @@ def handle_ack(self, data):


def stream_cam(self):
# from .esp32_communicator import get_cam_feed
# from . import esp32_comm
# asyncio.get_event_loop().run_until_complete(esp32_comm.get_cam_feed())
# Stream from webcam
# -- test: First, could able to stream the webcam or not? w/ a separate process or thread.
# With threading (after monkey patching), this way working.
cap = cv2.VideoCapture(0)
while (cap.isOpened()):
ret, img = cap.read()
if ret:
cv2.imshow("img", img)
img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)
frame = cv2.imencode('.jpg', img)[1].tobytes()
frame = base64.encodebytes(frame).decode("utf-8")
self.sock.emit('img_data', frame)
self.sock.sleep(0)
if cv2.waitKey(1) == 27:
break
else:
print("Can't stream ")
break
pass
from .esp32_communicator import get_cam_feed
# Stream from esp32 cam feed
from . import esp32_comm
print("------------------------------ object check ----------------------", hasattr(esp32_comm, 'cameraws'))
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(get_cam_feed())

# # Stream from webcam
# # -- test: First, could able to stream the webcam or not? w/ a separate process or thread.
# # With threading (after monkey patching), this way working.
# cap = cv2.VideoCapture(0)
# while (cap.isOpened()):
# ret, img = cap.read()
# if ret:
# cv2.imshow("img", img)
# img = cv2.resize(img, (0, 0), fx=0.5, fy=0.5)
# frame = cv2.imencode('.jpg', img)[1].tobytes()
# frame = base64.encodebytes(frame).decode("utf-8")
# self.sock.emit('img_data', frame)
# self.sock.sleep(0)
# if cv2.waitKey(1) == 27:
# break
# else:
# print("Can't stream ")
# break
# pass


def handle_stream(self, response):
# Get the camera streamer..
print("[DEBUG] web: (stream event) client sent: "+str(response))
print("[[[[[[[[[[[[[[[[[[[[[[[[[[[STREAMING BEGINS]]]]]]]]]]]]]]]]]]]]]]]]]]]")

print("[DEBUG] web: Creating proceses to begin streaming")
from . import web_comm
camThread = Thread(target=web_comm.stream_cam)
print("[DEBUG] web: about to start spawned process for streaming")
camThread.start()
print("[DEBUG] web: Started spawned process for streaming")
camThread.join()
# web_comm.sock.start_background_task(web_comm.stream_cam) # ref: https://stackoverflow.com/a/62095829

# A test -- whether could able to stream without creating separate process/thread or not.
# Test result: This way (w/o any process or thread) is working
Expand Down
2 changes: 1 addition & 1 deletion main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
print("[DEBUG] main: About to establish communications")
webapp = create_app()
web_comm.init_communication(socketio)
# esp32_comm.init_communication(ip='192.168.157.165')
esp32_comm.init_communication(ip='192.168.157.165')
# from app.middleware.communication.web_communicator import * # register event handlers
print("[DEBUG] main: Communications established")

Expand Down

0 comments on commit 2e2d7cc

Please sign in to comment.