diff --git a/assets/images/printer-icon.png b/assets/images/printer-icon.png new file mode 100644 index 0000000..e5f9b72 Binary files /dev/null and b/assets/images/printer-icon.png differ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..bed37d9 --- /dev/null +++ b/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "php-mqtt/client": "^2.2" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..50aecb7 --- /dev/null +++ b/composer.lock @@ -0,0 +1,189 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "447c16b903c1f7b070e4b4bfb41716da", + "packages": [ + { + "name": "myclabs/php-enum", + "version": "1.8.4", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/a867478eae49c9f59ece437ae7f9506bfaa27483", + "reference": "a867478eae49c9f59ece437ae7f9506bfaa27483", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.4" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } + ], + "time": "2022-08-04T09:53:51+00:00" + }, + { + "name": "php-mqtt/client", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-mqtt/client.git", + "reference": "8042ad93e72da8666e27168dc90670e45bdea274" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-mqtt/client/zipball/8042ad93e72da8666e27168dc90670e45bdea274", + "reference": "8042ad93e72da8666e27168dc90670e45bdea274", + "shasum": "" + }, + "require": { + "myclabs/php-enum": "^1.7", + "php": "^8.0", + "psr/log": "^1.1|^2.0|^3.0" + }, + "require-dev": { + "phpunit/php-invoker": "^3.0", + "phpunit/phpunit": "^9.0", + "squizlabs/php_codesniffer": "^3.5" + }, + "suggest": { + "ext-redis": "Required for the RedisRepository" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpMqtt\\Client\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marvin Mall", + "email": "marvin-mall@msn.com", + "role": "developer" + } + ], + "description": "An MQTT client written in and for PHP.", + "keywords": [ + "client", + "mqtt", + "publish", + "subscribe" + ], + "support": { + "issues": "https://github.com/php-mqtt/client/issues", + "source": "https://github.com/php-mqtt/client/tree/v2.2.0" + }, + "time": "2024-11-24T20:54:32+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} diff --git a/public/logout.php b/public/logout.php index 8aed3f1..a027511 100644 --- a/public/logout.php +++ b/public/logout.php @@ -2,6 +2,6 @@ session_start(); session_unset(); session_destroy(); -header("Location: /login.php"); +header("Location: login.php"); exit(); ?> diff --git a/public/viewPrinters.php b/public/viewPrinters.php new file mode 100644 index 0000000..361da5e --- /dev/null +++ b/public/viewPrinters.php @@ -0,0 +1,249 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + TOD Dashboard + + + + +
+ + + + + + + + +
+
+ + + + + + + +
+
+
+ +
+
+ +
+
+
+ + + +
+
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/header.php b/src/header.php index 028c450..5c2b9fc 100644 --- a/src/header.php +++ b/src/header.php @@ -70,7 +70,7 @@
  • -
  • Logout +
  • Logout
  • diff --git a/src/login.php b/src/login.php index 8904eb1..3a36dfa 100644 --- a/src/login.php +++ b/src/login.php @@ -12,7 +12,7 @@ if ($_SERVER['REQUEST_METHOD'] == 'POST') { if ($user && password_verify($password, $user['password']) && !$user['disabled']) { // Store user ID, username, and role in session - $_SESSION['user_id'] = $user['id']; + $_SESSION['userId'] = $user['id']; $_SESSION['username'] = $user['username']; $_SESSION['role'] = $user['role']; // Store user role echo 'success'; diff --git a/src/nav.php b/src/nav.php index 7d05d3c..92f93a1 100644 --- a/src/nav.php +++ b/src/nav.php @@ -28,131 +28,10 @@
  • - -
    -
    - -
    - -
  • - -
  • - -
    -
    - -
    -
  • -
  • - -
    -
    - -
    - -
  • -
  • - -
    -
    - -
    - -
  • -
  • - -
    -
    - -
    - -
  • -
  • - -
    -
    - -
    - -
  • -
  • - +
    - +
  • diff --git a/src/printers/addPrinter.php b/src/printers/addPrinter.php index f5e0c1b..4508111 100644 --- a/src/printers/addPrinter.php +++ b/src/printers/addPrinter.php @@ -1,12 +1,21 @@ 'error', 'message' => 'User not authenticated.']); + exit; +} + +$userId = $_SESSION['userId']; // Retrieve user ID from session + // Handle POST Request if ($_SERVER['REQUEST_METHOD'] === 'POST') { - header('Content-Type: application/json'); // Return JSON response - // Collect and sanitize form data $printerName = filter_input(INPUT_POST, 'printerName', FILTER_SANITIZE_STRING); $printerIp = filter_input(INPUT_POST, 'printerIp', FILTER_VALIDATE_IP); @@ -19,10 +28,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } try { - // Prepare SQL insert statement + // Prepare SQL insert statement with user ID $stmt = $pdo->prepare(" - INSERT INTO bambuPrinters (printerName, printerIp, mqttPassword, serialNumber) - VALUES (:printerName, :printerIp, :mqttPassword, :serialNumber) + INSERT INTO bambuPrinters (printerName, printerIp, mqttPassword, serialNumber, userId) + VALUES (:printerName, :printerIp, :mqttPassword, :serialNumber, :userId) "); // Execute the query with bound parameters @@ -30,7 +39,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { ':printerName' => $printerName, ':printerIp' => $printerIp, ':mqttPassword' => $accessCode, - ':serialNumber' => $serialNumber + ':serialNumber' => $serialNumber, + ':userId' => $userId ]); echo json_encode(['status' => 'success', 'message' => 'Printer successfully added!']); diff --git a/src/printers/getPrinters.php b/src/printers/getPrinters.php new file mode 100644 index 0000000..ddd3be1 --- /dev/null +++ b/src/printers/getPrinters.php @@ -0,0 +1,79 @@ + 'error', 'message' => 'User not authenticated.']); + exit; +} + +$userId = $_SESSION['userId']; + +try { + // Subquery to fetch latest telemetry for each printer + $stmt = $pdo->prepare(" + SELECT p.*, t.telemetry, t.recordedAt + FROM bambuPrinters p + LEFT JOIN printerTelemetry t + ON t.id = ( + SELECT id FROM printerTelemetry + WHERE printerId = p.id + ORDER BY recordedAt DESC + LIMIT 1 + ) + WHERE p.userId = :userId + "); + + $stmt->execute([':userId' => $userId]); + $printers = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $result = []; + foreach ($printers as $printer) { + $telemetry = json_decode($printer['telemetry'], true); + + $bedTemp = isset($telemetry['print']['bed_temper']) ? $telemetry['print']['bed_temper'] : 'N/A'; + $nozzleTemp = isset($telemetry['print']['device']['nozzle']['0']['temp']) + ? $telemetry['print']['device']['nozzle']['0']['temp'] + : 'N/A'; + $jobName = isset($telemetry['subtask_name']) ? $telemetry['subtask_name'] : 'No job running'; + $status = isset($telemetry['print']['gcode_state']) ? $telemetry['print']['gcode_state'] : 'Unknown'; + + // AMS Data + $humidity = isset($telemetry['print']['ams']['ams'][0]['humidity']) + ? $telemetry['print']['ams']['ams'][0]['humidity'] + : 0; + $trays = isset($telemetry['print']['ams']['ams'][0]['tray']) + ? $telemetry['print']['ams']['ams'][0]['tray'] + : []; + + // Structure tray data for direct output + $trayData = []; + foreach ($trays as $tray) { + $trayData[] = [ + 'id' => $tray['id'], + 'color' => isset($tray['tray_color']) ? $tray['tray_color'] : 'ccc' + ]; + } + + $result[] = [ + 'printerId' => $printer['id'], + 'printerName' => $printer['printerName'], + 'serialNumber' => $printer['serialNumber'], + 'printerIp' => $printer['printerIp'], + 'bedTemp' => $bedTemp, + 'nozzleTemp' => $nozzleTemp, + 'jobName' => $jobName, + 'status' => $status, + 'humidity' => $humidity, + 'trays' => $trayData, + 'recordedAt' => $printer['recordedAt'] ?? 'Never' + ]; + } + + echo json_encode(['status' => 'success', 'data' => $result]); + +} catch (PDOException $e) { + echo json_encode(['status' => 'error', 'message' => 'Failed to fetch printers: ' . $e->getMessage()]); +} +?> diff --git a/src/printers/mqttConnect.php b/src/printers/mqttConnect.php new file mode 100644 index 0000000..8da2b2e --- /dev/null +++ b/src/printers/mqttConnect.php @@ -0,0 +1,105 @@ +prepare("SELECT * FROM bambuPrinters"); + $stmt->execute(); + $printers = $stmt->fetchAll(PDO::FETCH_ASSOC); +} catch (PDOException $e) { + die(json_encode(['status' => 'error', 'message' => 'Failed to fetch printers.'])); +} + +// Process 2 messages per printer +$maxMessagesPerPrinter = 2; + +try { + foreach ($printers as $printer) { + echo "Connecting to " . $printer['printerName'] . " (" . $printer['serialNumber'] . ")...\n"; + echo "IP Address: " . $printer['printerIp'] . "\n"; + echo "MQTT Password: " . $printer['mqttPassword'] . "\n"; + + $mqttPassword = $printer['mqttPassword']; // Use mqttPassword from DB + $printerIp = $printer['printerIp']; // Printer IP from DB + $messageCount = 0; // Reset counter per printer + + $mqtt = new MqttClient($printerIp, $mqttPort, $clientId); + + // Handle SIGINT (CTRL + C) to gracefully exit + pcntl_signal(SIGINT, function () use ($mqtt) { + echo "Interrupt received. Disconnecting MQTT...\n"; + $mqtt->interrupt(); + }); + + $connectionSettings = (new ConnectionSettings()) + ->setUsername($mqttUsername) + ->setPassword($mqttPassword) + ->setKeepAliveInterval(60) + ->setUseTls(true) + ->setTlsVerifyPeer(false) + ->setTlsVerifyPeerName(false); + + // Establish Connection + $mqtt->connect($connectionSettings, true); + + // Subscribe to the printer's report topic + $topic = "device/{$printer['serialNumber']}/report"; + + $mqtt->subscribe($topic, function (string $topic, string $message) use ( + $printer, $pdo, &$messageCount, $maxMessagesPerPrinter, $mqtt + ) { + echo "[" . $printer['printerName'] . "] [$topic] $message\n"; + + // Store full JSON telemetry report + try { + $stmt = $pdo->prepare(" + INSERT INTO printerTelemetry + (printerId, telemetry) + VALUES + (:printerId, :telemetry) + "); + $stmt->execute([ + ':printerId' => $printer['id'], + ':telemetry' => $message + ]); + } catch (PDOException $e) { + error_log("Failed to insert telemetry: " . $e->getMessage()); + } + + $messageCount++; + + // Stop loop after 2 messages for this printer + if ($messageCount >= $maxMessagesPerPrinter) { + echo "Processed $maxMessagesPerPrinter messages for " . $printer['printerName'] . ". Disconnecting...\n"; + $mqtt->interrupt(); + } + }, 0); + + // Start Listening for Messages + $mqtt->loop(true); // Loop until interrupted after processing 2 messages + $mqtt->disconnect(); + } +} catch (Exception $e) { + die(json_encode(['status' => 'error', 'message' => 'MQTT connection failed. ' . $e->getMessage()])); +} +?> diff --git a/src/session_check.php b/src/session_check.php index 5ffae5d..f34a1fb 100644 --- a/src/session_check.php +++ b/src/session_check.php @@ -1,7 +1,7 @@ diff --git a/template.php b/template.php index 33993bc..5537d50 100644 --- a/template.php +++ b/template.php @@ -38,7 +38,7 @@ - +