Skip to content

Commit

Permalink
Refactor code and add WebSocket streaming
Browse files Browse the repository at this point in the history
functionality
  • Loading branch information
infinitel8p committed Nov 13, 2023
1 parent 9a8fcbc commit 2d99c2c
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 45 deletions.
6 changes: 3 additions & 3 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,20 @@ <h2 id="setup">Setup</h2>
<ol>
<li>
<h3 id="hardware-setup">Hardware setup</h3>
The Instructions to the hardware setup can be found <a href="./docs/HARDWARE.html">here</a>. If you are new to the
The Instructions to the hardware setup can be found <a href="./HARDWARE.html">here</a>. If you are new to the
project, please start here.<br>
They explain how to connect the camera module and the magnetic reed switch to the Raspberry Pi and serve as entry
point to the project.
</li>
<li>
<h3 id="wifi-setup">WiFi setup</h3>
The Instructions to the WiFi setup can be found <a href="./docs/WIFI.html">here</a>.<br>
The Instructions to the WiFi setup can be found <a href="./WIFI.html">here</a>.<br>
They explain how to set up the Raspberry Pi as an access point and how to connect to it. This will be necessary to
connect to the Raspberry Pi when outside of the home network and to access the web interface.
</li>
<li>
<h3 id="bluetooth-and-script-setup">Bluetooth and Script setup</h3>
The Instructions to the Bluetooth setup and the script setup can be found <a href="./docs/SCRIPT.html">here</a>.
The Instructions to the Bluetooth setup and the script setup can be found <a href="./SCRIPT.html">here</a>.
They explain how to pair the Raspberry Pi with a Bluetooth device and how to set up the script.
</li>
</ol>
Expand Down
177 changes: 135 additions & 42 deletions main2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,155 @@
import logging
import os
import time
import threading
from datetime import datetime
import picamera
import RPi.GPIO as GPIO
from dotenv import load_dotenv
import websocket
import threading
import io
import base64
from dotenv import load_dotenv
from functions import *

# Set up logging with custom timestamp format
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%d-%m-%Y %H:%M:%S')

logging.info("Initializing...")

# Try to load config from .env file
logging.info("Loading config from .env file...")
load_dotenv()

TARGET_BT_ADDRESSES = os.getenv("TARGET_BT_ADDRESSES")
TARGET_AP_MAC_ADDRESSES = os.getenv("TARGET_AP_MAC_ADDRESSES")

# ... [Your existing setup code goes here] ...
# If not found in .env, fall back to config.json
if not TARGET_BT_ADDRESSES or not TARGET_AP_MAC_ADDRESSES:
logging.info(".env not found, falling back to config.json file...")
with open('config.json', 'r') as f:
config = json.load(f)
TARGET_BT_ADDRESSES = config["TARGET_BT_ADDRESSES"]
TARGET_AP_MAC_ADDRESSES = config["TARGET_AP_MAC_ADDRESSES"]

# Convert the comma-separated string from .env to a list
if isinstance(TARGET_BT_ADDRESSES, str):
TARGET_BT_ADDRESSES = TARGET_BT_ADDRESSES.split(',')
if isinstance(TARGET_AP_MAC_ADDRESSES, str):
TARGET_AP_MAC_ADDRESSES = TARGET_AP_MAC_ADDRESSES.split(',')

# Initialize the camera
camera = picamera.PiCamera()
recording = False

# Set up WebSocket
ws = None
# Set up GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
Digital_Pin = 22
GPIO.setup(Digital_Pin, GPIO.IN)

# Enable timestamp on the video
camera.annotate_background = picamera.Color('black')

"""
"""

# WebSocket related global variables
should_stream_frames = False
streaming_running = False

# Function to stream frames


def stream_frames():
global should_stream_frames, streaming_running
streaming_running = True

with picamera.PiCamera() as camera:
camera.resolution = (1920, 1080)
camera.framerate = 24
stream = io.BytesIO()

for _ in camera.capture_continuous(stream, 'jpeg', use_video_port=True):
if not should_stream_frames:
break

# Send frame
stream.seek(0)
buffer = stream.read()
if should_stream_frames:
ws.send(buffer, opcode=websocket.ABNF.OPCODE_BINARY)

def send_frame():
global ws
while True:
if ws:
stream = io.BytesIO()
camera.capture(stream, format='jpeg')
stream.seek(0)
frame = stream.read()
frame_base64 = base64.b64encode(frame).decode('utf-8')
ws.send(frame_base64)
stream.close()
time.sleep(0.1) # Adjust frame rate

def on_open(new_ws):
global ws
ws = new_ws
send_frame_thread = threading.Thread(target=send_frame)
send_frame_thread.start()

def start_websocket():
websocket.enableTrace(True)
ws_app = websocket.WebSocketApp("ws://localhost:3000", on_open=on_open)
ws_app.run_forever()

# Start WebSocket in a separate thread
websocket_thread = threading.Thread(target=start_websocket)
websocket_thread.start()

# Your existing GPIO and recording logic goes here
# ...
stream.truncate()

streaming_running = False

# WebSocket handlers


def on_open(ws):
print("WebSocket opened and thread started")
global streaming_running
if not streaming_running:
threading.Thread(target=stream_frames).start()


def on_close(ws, close_status_code, close_msg):
global should_stream_frames
print("WebSocket closed")
ws.send("Python Script")
should_stream_frames = False


def on_message(ws, message):
global should_stream_frames
if message == "START":
should_stream_frames = True
elif message == "STOP":
should_stream_frames = False


# Initialize WebSocket
ws = websocket.WebSocketApp(
"ws://localhost:3000",
on_open=on_open,
on_message=on_message,
on_close=on_close
)

# Run WebSocket in a separate thread
threading.Thread(target=ws.run_forever).start()

try:
# Your existing loop logic goes here
# ...
while True:
if GPIO.input(Digital_Pin):
logging.info("Door is closed.")
if recording:
logging.info("Recording was in progress. Pausing recording.")
camera.stop_recording()
recording = False
else:
logging.warning("Door is open.")
# Check if any of the smartphones' Bluetooth addresses are visible or if they're connected to the AP
if is_device_connected_to_bt(TARGET_BT_ADDRESSES) or is_device_connected_to_ap(TARGET_AP_MAC_ADDRESSES):
if recording:
logging.info("Device detected. Stop recording.")
camera.stop_recording()
recording = False
# If no device is connected, start recording
else:
if not recording:
logging.info("Device not detected. Start recording.")
camera.start_recording(
f"./server/public/recordings/video_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.h264")
recording = True
time.sleep(1)
except KeyboardInterrupt:
# Your existing KeyboardInterrupt handling goes here
# ...
if recording:
camera.stop_recording()
camera.close()
logging.info("Script manually interrupted! Recording stopped.")
finally:
if streaming_running:
should_stream_frames = False
GPIO.cleanup()
if ws:
ws.close()

0 comments on commit 2d99c2c

Please sign in to comment.