Skip to content

Commit

Permalink
fixed websocket server
Browse files Browse the repository at this point in the history
  • Loading branch information
infinitel8p committed Nov 11, 2023
1 parent 193f948 commit 1ce13b8
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 14 deletions.
7 changes: 4 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
picamera
pybluez
python-dotenv
flask
flask-socketio
eventlet
eventlet

opencv-python
websocket-client
23 changes: 22 additions & 1 deletion server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"author": "Ludovico Ferrara",
"license": "MIT",
"dependencies": {
"express": "^4.18.2"
"express": "^4.18.2",
"ws": "^8.14.2"
}
}
74 changes: 72 additions & 2 deletions server/public/css/style.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,75 @@
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
font-family: 'Arial', sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
color: #333;
}

.navbar {
background-color: #005f73;
overflow: hidden;
padding: 10px 0;
}

.navbar-nav {
list-style: none;
padding: 0;
margin: 0;
display: flex;
justify-content: center;
flex-wrap: wrap;
}

.nav-item {
padding: 10px 20px;
}

.nav-item a {
text-decoration: none;
color: white;
transition: color 0.3s, background-color 0.3s;
}

.nav-item a:hover {
background-color: #0a9396;
color: #e9d8a6;
border-radius: 5px;
}

.main-content {
padding: 20px;
text-align: center;
}

.video-container {
max-width: 600px;
margin: auto;
border: 1px solid #ddd;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
padding: 10px;
background-color: white;
}

#videoCanvas {
max-width: 100%;
height: auto;
border: 1px solid #ddd;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* Responsive Styling */
@media only screen and (max-width: 600px) {
.navbar-nav {
flex-direction: column;
}

.nav-item a {
margin-bottom: 5px;
/* Space out items in mobile view */
}

.video-container {
width: 90%;
}
}
14 changes: 12 additions & 2 deletions server/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,21 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Security Cam Webserver</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/script.js"></script>
</head>

<body>
<h1>Security Cam Webserver</h1>
<nav class="navbar">
<ul class="navbar-nav">
<li class="nav-item"><a href="/">Home</a></li>
<li class="nav-item"><a href="/recordings">Recordings</a></li>
<li class="nav-item"><a href="/settings">Settings</a></li>
</ul>
</nav>
<div class="main-content">
<h1>Security Cam Webserver</h1>
<canvas id="videoCanvas"></canvas>
</div>
<script src="js/script.js"></script>
</body>

</html>
21 changes: 18 additions & 3 deletions server/public/js/script.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
document.addEventListener('DOMContentLoaded', function () {
console.log("Page loaded!");
});
const canvas = document.getElementById('videoCanvas');
const context = canvas.getContext('2d');

const ws = new WebSocket('ws://localhost:3000');
ws.binaryType = 'blob';

ws.onmessage = function (event) {
const blob = new Blob([event.data], { type: 'image/jpeg' });

const url = URL.createObjectURL(blob);

const image = new Image();
image.onload = function () {
context.drawImage(this, 0, 0, canvas.width, canvas.height);
URL.revokeObjectURL(url);
};
image.src = url;
};
36 changes: 34 additions & 2 deletions server/server.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,42 @@
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
const app = express();
const port = 3000;

// Serve static files from the 'public' directory
app.use(express.static('public'));

app.listen(port, () => {
// Create an HTTP server
const server = http.createServer(app);

// Create a WebSocket server
const wss = new WebSocket.Server({ server });

let connectedClients = 0;

wss.on('connection', function connection(ws) {
connectedClients++;
console.log('A new client connected! Total clients:', connectedClients);

ws.on('message', function incoming(data) {
if (connectedClients > 1) {
// Broadcast the received data (video frame) to all connected clients
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
}
});

ws.on('close', () => {
connectedClients--;
console.log('Client disconnected. Total clients:', connectedClients);
});
});

// Start the server
server.listen(port, () => {
console.log(`Server running on http://localhost:${port}`);
});
});
33 changes: 33 additions & 0 deletions test-stream.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import cv2
import websocket
import _thread
import time


def on_open(ws):
def run(*args):
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if ret:
# Convert the image to JPEG
retval, buffer = cv2.imencode(
'.jpg', frame, [int(cv2.IMWRITE_JPEG_QUALITY), 70])

# Send the binary data
ws.send(buffer.tobytes(), opcode=websocket.ABNF.OPCODE_BINARY)

# Sleep for a bit to prevent overwhelming the server
time.sleep(0.1)

cap.release()
ws.close()
print("Thread terminating...")

_thread.start_new_thread(run, ())


if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://localhost:3000", on_open=on_open)
ws.run_forever()

0 comments on commit 1ce13b8

Please sign in to comment.