From 842a20cc961a6950f9b10c9000a49cea9d04f29d Mon Sep 17 00:00:00 2001
From: flaisch <simon.flaisch@student.reutlingen-university.de>
Date: Tue, 30 Apr 2024 15:37:25 +0200
Subject: [PATCH] Changed the game to work with our architecture. For that I
 implemented mqtt clients and a Server.js

---
 Server.js  | 31 ++++++++++++++++++
 app.js     |  7 +++-
 index.html |  2 +-
 main.py    | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 132 insertions(+), 3 deletions(-)
 create mode 100644 Server.js

diff --git a/Server.js b/Server.js
new file mode 100644
index 0000000..7d6fd60
--- /dev/null
+++ b/Server.js
@@ -0,0 +1,31 @@
+const mqtt = require("mqtt");
+const ws = require ("ws");
+
+let socketserver = new ws.WebSocketServer({
+    port: 443
+});
+
+ let client = mqtt.connect("mqtt://localhost:1883",{
+         username: "standardUser",
+         password: "GreatHHZ4Ever!"
+     });
+client.on("connect", function() {
+    let topicID = "Topic1";
+    client.subscribe(topicID);
+});
+socketserver.on('connection', ws => {
+    console.log("new client connected");
+
+});
+socketserver.on('close', () => console.log('Client has disconnected!'));
+
+
+
+
+
+client.on("message", function(topic, message){
+    data = JSON.parse(message.toString())
+    var column =  {column: Math.min(data.total_fingers,6)}
+    socketserver.clients.forEach(client => {
+        client.send(JSON.stringify(column));
+})});
diff --git a/app.js b/app.js
index b8a28f5..7b97c0a 100644
--- a/app.js
+++ b/app.js
@@ -1,3 +1,4 @@
+
 document.addEventListener('DOMContentLoaded', () => {
   const flaechen = document.querySelectorAll('.grid div');
   const ergebnis = document.querySelector('#result');
@@ -5,6 +6,7 @@ document.addEventListener('DOMContentLoaded', () => {
   let currentPlayer = 1;
 
 
+
   const gewinnFlaechen = [
     [0, 1, 2, 3],
     [41, 40, 39, 38],
@@ -77,7 +79,8 @@ document.addEventListener('DOMContentLoaded', () => {
     [13, 20, 27, 34],
   ]
   // Verbinden mit dem WebSocket.
-  const ws = new WebSocket('ws://localhost:89/ws');
+
+  const ws = new WebSocket('ws://localhost:443/ws');
 
     ws.onmessage = function(event) {
     const data = JSON.parse(event.data);
@@ -155,3 +158,5 @@ function placeChipInColumn(column) {
   }
 
 })
+
+
diff --git a/index.html b/index.html
index 05368d4..07a5a0d 100644
--- a/index.html
+++ b/index.html
@@ -5,7 +5,7 @@
   <meta charset="utf-8">
   <title>Connect Four</title>
   <link rel="stylesheet" href="style.css">
-  <script src="app.js" charset="utf-8" defer></script>
+  <script type="module" src="app.js" charset="utf-8" defer></script>
 </head>
 <body>
   <h1>Der derzeitige Spieler ist: Spieler <span id="current-player">1</span></h1>
diff --git a/main.py b/main.py
index 025bdf2..78579c7 100644
--- a/main.py
+++ b/main.py
@@ -1,17 +1,65 @@
+import json
+
 import uvicorn
 from fastapi import FastAPI, WebSocket
 from fastapi.responses import HTMLResponse, Response
 import cv2
 from cvzone.HandTrackingModule import HandDetector
 from imutils.video import VideoStream
+import paho.mqtt.client as mqtt
 import asyncio
+import time
+
+
+unacked_publish = set()
+main_time = 0
+response = None
+
+def on_connect( client, userdata, flags, reason_code, properties):
+    print(f"Connected with result code {reason_code}\n")
+    client.subscribe("Topic1")
+
+
+# Funktion, die bei einem Publish in ein Topic ausgeführt wird.
+def on_publish( client, userdata, mid, reason_code, properties):
+    try:
+        userdata.remove(mid)  # Removed die gesendete Nachricht vom Speicher, um eine doppelte Sendung zu verhindern
+    except KeyError:
+        "Something went wrong. Please check if you have removed the mid from the userdata"
+
 
+# Funktion zur Verbindung mit MQTT
+def connectwithmqtt( adress: str, targetport: int):
+    mqttc = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, userdata=None)  # Intitalisierung des Clients
+    mqttc.on_connect = on_connect
+    mqttc.on_publish = on_publish
+    mqttc.user_data_set(unacked_publish)  # Den lokalen Speicher als User data setzen
+    mqttc.username_pw_set(username="standardUser",
+                          password="GreatHHZ4Ever!")  # Username und Passwort - vorgegeben vom MQTT Server
+    mqttc.connect(host=adress, port=targetport)
+    while not mqttc.is_connected():
+        mqttc.loop()
+        print("Waiting for connection...")
+    return mqttc
+
+
+# Funktion zum senden einer Nachricht
+def sendMessage(mqttc, topic, message):
+    mqttc.loop_start()  # Started einen gethreaded connection loop zum senden der Nachrichten.
+    msg = mqttc.publish(topic, message, qos=1)
+    unacked_publish.add(msg.mid)  # Mid sind die Daten der aktuellen Nachricht
+    while len(unacked_publish):
+        time.sleep(0.1)  # Wartet bis alle gequeten Nachrichten gepublished werden
+    msg.wait_for_publish()
+
+
+mqttClient = connectwithmqtt(adress="localhost", targetport=1883)
 
 app = FastAPI()
 
 # Video-Capture initialisieren
 try:
-    video_capture = VideoStream("http://localhost:88/video_feed").start()
+    video_capture = VideoStream("http://localhost:80/video_feed").start()
 except Exception as e:
     print(f"We couldn't reach the camera")
     exit()
@@ -19,7 +67,42 @@ except Exception as e:
 # Hand-Detektor initialisieren
 detector = HandDetector(maxHands=2)
 
+while True:
+    frame = video_capture.read()
+    if frame is None:
+        print("Sorry, couldn't receive videostream")
+        exit()
+
+    # Handgesten-Erkennung
+    hands, img = detector.findHands(frame)
+    current_time = time.time()  # Aktueller Zeitpunkt
+    if current_time - main_time > 5:  # Timer
+        main_time = current_time
+        if hands:
+            # Zähle die Anzahl der gestreckten Finger
+            total_fingers = 0
+            for hand in hands:
+                fingers = detector.fingersUp(hand)
+                total_fingers += sum(fingers)
+                response = {
+                    "fingers": fingers,
+                    "total_fingers": total_fingers
+                }
+            if response is not None:
+                sendMessage(mqttc=mqttClient, topic="Topic1", message=json.dumps(response))
+
+
+    # Bild fürs Debugging anzeigen
+    cv2.imshow("Video", img)
+    if cv2.waitKey(1) & 0xFF == ord('q'):
+        print("Goodbye!")
+        mqttClient.disconnect()
+        mqttClient.loop_stop()
+        break
+video_capture.stop()
+cv2.destroyAllWindows()
 
+'''
 @app.websocket("/ws")
 async def websocket_endpoint(websocket: WebSocket):
     await websocket.accept()
@@ -83,3 +166,13 @@ async def get_image():
 
 if __name__ == "__main__":
     uvicorn.run(app, host="localhost", port=89)
+    
+    
+ # Begrenze die Fingeranzahl auf 7, da wir 7 Spalten haben (0-6)
+            selected_column = min(total_fingers, 6)
+            print("Selected column:", selected_column)
+            try:
+                await websocket.send_json({"column": selected_column})
+            except Exception as e:
+                print(f"Error sending message: {str(e)}")
+'''
\ No newline at end of file
-- 
GitLab