From 69b45e386f459d7a6eb4b4947de2413cadafe29b Mon Sep 17 00:00:00 2001 From: el-yazide mohamed Date: Sat, 7 Jun 2025 19:44:29 +0200 Subject: [PATCH] test son raspberry --- node-server/assets/script.js | 59 +++++++++++++- node-server/server.js | 146 +++++++++++++++++++++-------------- 2 files changed, 147 insertions(+), 58 deletions(-) diff --git a/node-server/assets/script.js b/node-server/assets/script.js index be921a6..5fdd4c3 100644 --- a/node-server/assets/script.js +++ b/node-server/assets/script.js @@ -1,4 +1,4 @@ -// 1. Sélection des éléments DOM +/*// 1. Sélection des éléments DOM const vinyl = document.getElementById('vinyl'); const audio = document.getElementById('audio'); const progress = document.getElementById('progress'); @@ -147,4 +147,61 @@ audio.addEventListener('ended', () => { } else { isPlaying = false; } +});*/ + +// 1. Sélection des éléments DOM +const vinyl = document.getElementById('vinyl'); + +// 2. Variables utiles +let lastPosition = null; +let lastTime = null; +let idleTimeout = null; + +// 3. Connexion Socket.io +const socket = io(); + +socket.on('position', (position) => { + const now = Date.now(); + + if (lastPosition !== null && lastTime !== null) { + const deltaPos = position - lastPosition; + const deltaTime = (now - lastTime) / 1000; + const speed = deltaPos / deltaTime; + + clearTimeout(idleTimeout); + + // Seuil de mouvement pour considérer que la balle est immobile + if (Math.abs(speed) < 5) { + // Par exemple : diminuer l'opacité pour montrer l'arrêt + vinyl.style.opacity = 0.5; + return; + } + + // Si la balle bouge, on remet l'opacité normale + vinyl.style.opacity = 1; + + // Calcul de la rotation visuelle du vinyle en fonction de la position + // Ici on fait simplement tourner le vinyle à vitesse proportionnelle à speed + // Ajuste le facteur multiplicateur selon l'effet désiré + const rotationDeg = (speed * 5) % 360; + + // Appliquer la rotation cumulée au vinyle + // Si tu veux que la rotation soit cumulée dans le temps, tu peux stocker et additionner la rotation précédente + // Ici on fait une rotation relative (exemple simple) + vinyl.style.transform = `rotate(${rotationDeg}deg)`; + } + + lastPosition = position; + lastTime = now; + + // Timeout pour gérer l'inactivité (après 300ms d'arrêt, opacité réduite) + idleTimeout = setTimeout(() => { + vinyl.style.opacity = 0.5; + }, 300); +}); + +// Optionnel : clique sur le vinyle pour un effet visuel (pas de lecture audio ici) +vinyl.addEventListener('click', () => { + // Par exemple, ajouter une animation ou un effet au clic + console.log('Vinyl clicked'); }); diff --git a/node-server/server.js b/node-server/server.js index 97ff2ee..134203a 100644 --- a/node-server/server.js +++ b/node-server/server.js @@ -1,75 +1,107 @@ const express = require('express'); const { createServer } = require('node:http'); -// socket const { Server } = require('socket.io'); -// usb serial (arduino) -var { SerialPort } = require("serialport"); -const { ReadlineParser } = require('@serialport/parser-readline') +const { SerialPort } = require('serialport'); +const { ReadlineParser } = require('@serialport/parser-readline'); +const { spawn } = require('child_process'); const app = express(); const server = createServer(app); const io = new Server(server); -const port = 3000 +const PORT = 3000; +const SOUND_FILE = 'assets/sounds/muddy_files.mp3'; // chemin vers ton fichier mp3 +let mpg123Process = null; +let lastPosition = null; +let lastTime = null; +let stopTimeout = null; -// https://serialport.io/docs/guide-usage - -var arduinoCOMPort = "/dev/ttyUSB0"; -var arduinoSerialPort = new SerialPort({ - path: arduinoCOMPort, - baudRate: 9600 +const arduinoCOMPort = '/dev/ttyUSB0'; // adapte si besoin +const arduinoSerialPort = new SerialPort({ + path: arduinoCOMPort, + baudRate: 9600 }); -arduinoSerialPort.on('open',function() { - console.log('Serial Port ' + arduinoCOMPort + ' is opened.'); +// Lorsqu’on ouvre la connexion série +arduinoSerialPort.on('open', () => { + console.log('Port série ouvert:', arduinoCOMPort); }); +const parser = arduinoSerialPort.pipe(new ReadlineParser({ delimiter: '\n' })); -// // Read data that is available but keep the stream in "paused mode" -// arduinoSerialPort.on('readable', function () { -// console.log('Data:', arduinoSerialPort.read()) -// }) - -// // Switches the port into "flowing mode" -// arduinoSerialPort.on('data', function (data) { -// console.log('Data:', data) -// }) - -// const serialParser = arduinoSerialPort.pipe(new Readline({ delimiter: '\n' })); - -// serialParser.on('data', data =>{ -// console.log('got word from arduino:', data); -// }); - -app.set('view engine', 'pug') -app.use(express.static('assets')) +// Middleware +app.use(express.static('assets')); +// Routes app.get('/', (req, res) => { - // res.send('Hello World!') - // res.render('index', { title: 'Hey', message: 'Hello there PUG!' }) - res.sendFile('assets/main.html', { root : __dirname}); -}) - -io.on('connection', (socket) => { - console.log('a user connected'); - // let speed = 0.1; - // setInterval(() => { - // speed+=0.1; - // socket.emit('speed', speed); - // }, 2000); - - // Listening to arduino through serial port - const parser = arduinoSerialPort.pipe(new ReadlineParser({ delimiter: '\n' })) - parser.on('data', data => { - console.log('got word from arduino:', data); - const position = parseFloat(data); - if (!isNaN(position)) { - socket.emit('position', position); - } - }); - + res.sendFile('assets/main.html', { root: __dirname }); }); -server.listen(port, () => { - console.log(`Example app listening on port ${port}`) -}) \ No newline at end of file +// Socket.io +io.on('connection', (socket) => { + console.log('Un client s\'est connecté'); + + parser.on('data', (data) => { + const position = parseInt(data.trim(), 10); + if (isNaN(position)) return; + + socket.emit('position', position); // envoie au client pour l'animation + + const now = Date.now(); + if (lastPosition !== null && lastTime !== null) { + const deltaPos = position - lastPosition; + const deltaTime = (now - lastTime) / 1000; + const speed = deltaPos / deltaTime; + + clearTimeout(stopTimeout); + + if (Math.abs(speed) < 5) { + stopPlayback(); + return; + } + + if (speed < 0) { + stopPlayback(); // Rotation inverse = arrêt + } else { + // Rotation positive = jouer le son + const rate = Math.min(Math.max(0.5 + speed / 400, 0.5), 1.5); + startOrAdjustPlayback(rate); + } + } + + lastPosition = position; + lastTime = now; + + stopTimeout = setTimeout(() => { + stopPlayback(); + }, 300); + }); +}); + +// Fonctions de lecture audio +function startOrAdjustPlayback(speed = 1.0) { + if (mpg123Process === null) { + console.log(`⏯️ Lecture à ${speed.toFixed(2)}x`); + mpg123Process = spawn('mpg123', ['-k', '0', SOUND_FILE]); + + mpg123Process.on('exit', (code) => { + console.log(`🔇 mpg123 terminé (code ${code})`); + mpg123Process = null; + }); + } else { + console.log(`⚙️ (Note : mpg123 ne supporte pas le changement de vitesse à chaud)`); + // Pour changer la vitesse, il faudrait tuer et relancer mpg123 avec options spécifiques + } +} + +function stopPlayback() { + if (mpg123Process !== null) { + console.log('🛑 Arrêt de la lecture'); + mpg123Process.kill('SIGKILL'); + mpg123Process = null; + } +} + +server.listen(PORT, () => { + console.log(`Serveur en écoute sur http://localhost:${PORT}`); +});