Compare commits

...
57 Commits
Author SHA1 Message Date
el-yazide.mohamed 0352efbc34 sensi re 2025-06-08 10:55:22 +02:00
el-yazide.mohamed 911049a2fe rewind 2025-06-08 10:53:07 +02:00
el-yazide.mohamed 60bb918f54 d 2025-06-08 10:50:50 +02:00
el-yazide.mohamed 0f16a93a7e c 2025-06-08 10:32:20 +02:00
el-yazide.mohamed 8cde0ef01e b 2025-06-08 10:29:30 +02:00
el-yazide.mohamed 62cac7c459 web audio API 2025-06-08 10:25:31 +02:00
el-yazide.mohamed be551e8844 seuil 1 2025-06-08 09:54:33 +02:00
el-yazide.mohamed d56266d1f3 b2 2025-06-08 09:53:45 +02:00
el-yazide.mohamed c74daf7337 bis 2025-06-08 09:51:07 +02:00
el-yazide.mohamed a9808ba9d4 sensi + seuil 2025-06-08 09:46:21 +02:00
el-yazide.mohamed 303c76cbd6 anim css x 2025-06-07 21:11:51 +02:00
el-yazide.mohamed 8c1e56c3f9 html change 2025-06-07 21:05:22 +02:00
el-yazide.mohamed 82ce27c10d rewind encore 2025-06-07 20:59:01 +02:00
el-yazide.mohamed 10e8782798 parser 2025-06-07 20:55:18 +02:00
el-yazide.mohamed fe24e5aa23 bis 2025-06-07 20:43:37 +02:00
el-yazide.mohamed 702e428ee5 bis 2025-06-07 20:26:42 +02:00
el-yazide.mohamed f236665829 mpg123 2025-06-07 20:20:14 +02:00
el-yazide.mohamed 21f18d1b2a bis 2025-06-07 19:51:31 +02:00
el-yazide.mohamed daa0505504 rewind 2025-06-07 19:49:27 +02:00
el-yazide.mohamed 69b45e386f test son raspberry 2025-06-07 19:44:29 +02:00
el-yazide.mohamed 8accaf4ab2 son exterieur 1 2025-06-07 19:16:30 +02:00
el-yazide.mohamed cf8c4b0e47 - sensi reverse 2025-06-07 17:35:53 +02:00
el-yazide.mohamed 710cd0506d bis 2025-06-07 17:26:07 +02:00
el-yazide.mohamed 7a7c04dbe4 animation js 2025-06-07 17:18:25 +02:00
el-yazide.mohamed 1e04b86236 animation css 2025-06-07 17:14:30 +02:00
el-yazide.mohamed 6a8463fab5 css 2025-06-07 17:09:51 +02:00
el-yazide.mohamed 9cf7c74f9c bisbis 2025-06-07 17:04:57 +02:00
el-yazide.mohamed 825acfe48b bis 2025-06-07 16:56:27 +02:00
el-yazide.mohamed cadb42d693 reverse timeline 2025-06-07 16:53:59 +02:00
el-yazide.mohamed 024338d4dc Vitesse normalisée 2025-06-07 16:49:13 +02:00
el-yazide.mohamed a33466d6d9 speed 2025-06-07 16:38:15 +02:00
el-yazide.mohamed ebc97c8930 timeline rewind 2025-06-07 13:41:45 +02:00
el-yazide.mohamed 0e8efa0902 animation vinyle 2025-06-07 13:34:02 +02:00
el-yazide.mohamed 4eadf7dc7e bis 2025-06-07 13:20:10 +02:00
el-yazide.mohamed 9033c8ad20 audio src 2025-06-07 13:14:34 +02:00
el-yazide.mohamed ac89ce77e6 retour sensi - 2025-06-07 12:44:45 +02:00
el-yazide.mohamed 2b54c71eae test 2025-06-07 09:26:53 +02:00
el-yazide.mohamed e957de4d86 bisbis 2025-06-07 08:32:34 +02:00
el-yazide.mohamed 61f68ca41f bis 2025-06-07 08:19:34 +02:00
el-yazide.mohamed bdd82be393 audio back and forth 2025-06-07 08:06:05 +02:00
el-yazide.mohamed a9c1f21fe3 audio reverse add 2025-06-07 07:52:01 +02:00
el-yazide.mohamed 98f3a4a02f sensi - 2025-06-07 07:23:29 +02:00
el-yazide.mohamed 80002351ad sensi 2025-06-07 07:18:49 +02:00
el-yazide.mohamed 533cd1052e reverse 2025-06-07 07:00:55 +02:00
el-yazide.mohamed 3b7b46f25b position -> vitesse 2025-06-07 06:14:25 +02:00
el-yazide.mohamed 0252347f65 socket re 2025-06-07 05:52:58 +02:00
el-yazide.mohamed c3bf6811ea socket 2025-06-07 05:45:24 +02:00
el-yazide.mohamed b2f9e5abb5 server 2025-06-06 17:04:27 +02:00
el-yazide.mohamed 1088699977 socket library 2025-06-06 16:56:31 +02:00
el-yazide.mohamed 44ec586c1e socket 2025-06-06 16:51:21 +02:00
el-yazide.mohamed 82f4868f78 websocket.io 2025-06-06 16:43:11 +02:00
el-yazide.mohamed 41717509f8 web socket 2025-06-06 16:43:10 +02:00
el-yazide.mohamed f3c09a00ad web socket 2025-06-06 16:43:10 +02:00
el-yazide.mohamed cafeed83b5 ajout websocket 2025-06-06 16:43:10 +02:00
bach 0a3a79aca9 front from ely 2025-05-30 17:25:17 +02:00
bach f969bf638c added arduino data to front 2025-05-30 17:19:03 +02:00
bach 9250353c1c added arduino rotary encoder 2025-05-30 15:36:48 +02:00
46 changed files with 687 additions and 164 deletions
-14
View File
@@ -1,14 +0,0 @@
const socket = io();
var myAudio = document.createElement('audio');
myAudio.setAttribute('src','muddy_files.mp3');
socket.on('speed', (speed) => {
console.log('recieved speed', speed);
myAudio.playbackRate = speed;
});
myAudio.playbackRate = 0.1;
myAudio.play();
-93
View File
@@ -1,93 +0,0 @@
// 1. Sélection des éléments du DOM
const vinyl = document.getElementById('vinyl');
const audio = document.getElementById('audio');
const progress = document.getElementById('progress');
const currentTimeEl = document.getElementById('currentTime');
const durationEl = document.getElementById('duration');
const backwardBtn = document.getElementById('backward');
const forwardBtn = document.getElementById('forward');
const loopBtn = document.getElementById('loop');
// 2. Variables utiles
let isPlaying = false;
let isLooping = false;
// 3. Fonctions
// Fonction pour basculer la lecture
function togglePlay() {
if (isPlaying) {
audio.pause();
vinyl.style.animationPlayState = 'paused';
} else {
audio.play();
vinyl.style.animationPlayState = 'running';
}
isPlaying = !isPlaying;
}
// Mise à jour de la barre de progression
function updateProgress() {
const progressPercent = (audio.currentTime / audio.duration) * 100;
progress.value = progressPercent;
currentTimeEl.textContent = formatTime(audio.currentTime);
}
// Fonction pour formater le temps (min:sec)
function formatTime(time) {
const minutes = Math.floor(time / 60);
const seconds = Math.floor(time % 60);
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
}
// Fonction pour changer la position de lecture en cliquant sur la barre
function setProgress(e) {
const width = progress.clientWidth;
const clickX = e.offsetX;
const duration = audio.duration;
audio.currentTime = (clickX / width) * duration;
}
// 4. Événements
// Clique sur le vinyle pour basculer lecture
vinyl.addEventListener('click', togglePlay);
// Mise à jour de la barre de progression à chaque changement de temps
audio.addEventListener('timeupdate', updateProgress);
// Mise à jour de la durée du titre dès que l'audio est chargé
audio.addEventListener('loadedmetadata', () => {
durationEl.textContent = formatTime(audio.duration);
});
// Permet de cliquer sur la barre de progression
progress.addEventListener('click', setProgress);
// Bouton reculer de 10s
backwardBtn.addEventListener('click', () => {
audio.currentTime = Math.max(0, audio.currentTime - 10);
});
// Bouton avancer de 10s
forwardBtn.addEventListener('click', () => {
audio.currentTime = Math.min(audio.duration, audio.currentTime + 10);
});
// Bouton pour activer/désactiver la boucle (LOOP)
loopBtn.addEventListener('click', () => {
isLooping = !isLooping;
loopBtn.style.backgroundColor = isLooping ? 'white' : 'transparent';
loopBtn.style.color = isLooping ? '#18344b' : 'white';
});
// Lorsque l'audio est terminé, on répète si la boucle est activée
audio.addEventListener('ended', () => {
if (isLooping) {
audio.currentTime = 0;
audio.play();
} else {
vinyl.style.animationPlayState = 'paused';
isPlaying = false;
}
});

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Before

Width:  |  Height:  |  Size: 2.4 MiB

After

Width:  |  Height:  |  Size: 2.4 MiB

@@ -43,9 +43,12 @@
<button id="forward">10s +</button> <button id="forward">10s +</button>
</div> </div>
<audio id="audio" src="song to song v4.mp3"></audio> <audio id="audio"
src="song_to_song_v4.mp3"
data-reverse-src="song_to_song_v4_reverse.mp3"></audio>
</main> </main>
<script src="socket.io.min.js"></script>
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
</html> </html>

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

@@ -52,7 +52,7 @@
<!-- Ajoute autant de titres que nécessaire --> <!-- Ajoute autant de titres que nécessaire -->
</div> </div>
<script src="socket.io.min.js"></script>
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
+28
View File
@@ -0,0 +1,28 @@
const socket = io();
let last_position = null;
let speed = 1;
var myAudio = document.createElement('audio');
myAudio.setAttribute('src','muddy_files.mp3');
// socket.on('speed', (speed) => {
// console.log('recieved speed', speed);
// myAudio.playbackRate = speed;
// });
socket.on('position', (position) => {
console.log('recieved position', position);
// if(!last_position){
// last_position = position;
// }else{
// speed += position > last_position ? 0.1 : -0.1;
// }
// myAudio.playbackRate = speed;
});
myAudio.playbackRate = speed;
myAudio.play();

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

@@ -43,9 +43,12 @@
<button id="forward">10s +</button> <button id="forward">10s +</button>
</div> </div>
<audio id="audio" src="paradisev2.mp3"></audio> <audio id="audio"
src="paradisev2.mp3"
data-reverse-src="paradisev2_reverse.mp3"></audio>
</main> </main>
<script src="socket.io.min.js"></script>
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
</html> </html>

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

@@ -28,7 +28,7 @@
</h2> </h2>
<div class="progress-container"> <div class="progress-container">
<input type="range" id="progress" value="0" /> <input type="range" id="progress" value="0" max="100" />
<div class="time-wrapper"> <div class="time-wrapper">
<div id="currentTime" class="time">0:00</div> <div id="currentTime" class="time">0:00</div>
@@ -43,9 +43,14 @@
<button id="forward">10s +</button> <button id="forward">10s +</button>
</div> </div>
<audio id="audio" src="muddy_files.mp3"></audio> <audio id="audio"
src="muddy_files.mp3"
data-reverse-src="muddy_files_reverse.mp3"></audio>
</main> </main>
<script src="socket.io.min.js"></script>
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
</html> </html>
Binary file not shown.
Binary file not shown.
+151
View File
@@ -0,0 +1,151 @@
// 1. Sélection des éléments DOM
const vinyl = document.getElementById('vinyl');
const audio = document.getElementById('audio');
const progress = document.getElementById('progress');
const currentTimeEl = document.getElementById('currentTime');
const durationEl = document.getElementById('duration');
const backwardBtn = document.getElementById('backward');
const forwardBtn = document.getElementById('forward');
const loopBtn = document.getElementById('loop');
// 2. Variables utiles
let isPlaying = false;
let isLooping = false;
let idleTimeout = null;
let lastPosition = null;
let lastTime = null;
const rotationsPerTrack = 3; // tours complets du vinyle sur toute la durée
let currentRotation = 0; // rotation en degrés actuelle du vinyle
// 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; // vitesse de rotation
clearTimeout(idleTimeout);
// Seuil de mouvement pour arrêt
if (Math.abs(speed) < 1) {
stopPlayback();
return;
}
if (speed < 0) {
// Rotation inverse : on recule la timeline
audio.pause();
isPlaying = false;
// recule proportionnellement à la vitesse (sensibilité ajustable)
audio.currentTime = Math.max(0, audio.currentTime + speed * 0.0025);
} else {
// Rotation avant : jouer la piste et ajuster vitesse
if (!isPlaying) {
audio.play();
isPlaying = true;
}
// SENSIBILITÉ : le facteur diviseur est plus grand → plus doux
let playbackSpeed = 0.5 + speed / 600;
playbackSpeed = Math.min(Math.max(playbackSpeed, 0.5), 1.1); // plage limitée à x1 max
audio.playbackRate = playbackSpeed;
}
}
lastPosition = position;
lastTime = now;
// Détection d'inactivité
idleTimeout = setTimeout(() => {
stopPlayback();
}, 300);
});
// 4. Fonctions
function togglePlay() {
if (isPlaying) {
audio.pause();
} else {
audio.play();
}
isPlaying = !isPlaying;
}
function updateProgress() {
if (!isNaN(audio.duration)) {
const progressPercent = (audio.currentTime / audio.duration) * 100;
progress.value = progressPercent;
currentTimeEl.textContent = formatTime(audio.currentTime);
durationEl.textContent = formatTime(audio.duration);
updateVinylRotation();
}
}
function formatTime(time) {
const minutes = Math.floor(time / 60);
const seconds = Math.floor(time % 60);
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
}
function setProgress(e) {
const width = progress.clientWidth;
const clickX = e.offsetX;
const duration = audio.duration;
audio.currentTime = (clickX / width) * duration;
}
function stopPlayback() {
audio.pause();
isPlaying = false;
audio.playbackRate = 1;
}
// La rotation est synchronisée avec la timeline audio
function updateVinylRotation() {
if (audio.duration && audio.currentTime >= 0) {
// Rotation proportionnelle au temps courant
currentRotation = (audio.currentTime / audio.duration) * 360 * rotationsPerTrack;
vinyl.style.transform = `rotate(${currentRotation}deg)`;
console.log('Rotation:', currentRotation); // Debug
}
}
// 5. Événements
vinyl.addEventListener('click', togglePlay);
audio.addEventListener('timeupdate', updateProgress);
audio.addEventListener('loadedmetadata', () => {
durationEl.textContent = formatTime(audio.duration);
console.log('Audio duration:', audio.duration);
});
progress.addEventListener('click', setProgress);
backwardBtn.addEventListener('click', () => {
audio.currentTime = Math.max(0, audio.currentTime - 10);
});
forwardBtn.addEventListener('click', () => {
audio.currentTime = Math.min(audio.duration, audio.currentTime + 10);
});
loopBtn.addEventListener('click', () => {
isLooping = !isLooping;
loopBtn.style.backgroundColor = isLooping ? 'white' : 'transparent';
loopBtn.style.color = isLooping ? '#18344b' : 'white';
});
audio.addEventListener('ended', () => {
if (isLooping) {
audio.currentTime = 0;
audio.play();
} else {
isPlaying = false;
}
});
Binary file not shown.
Binary file not shown.
@@ -43,9 +43,12 @@
<button id="forward">10s +</button> <button id="forward">10s +</button>
</div> </div>
<audio id="audio" src="stamina-v17.mp3"></audio> <audio id="audio"
src="stamina-v17.mp3"
data-reverse-src="stamina-v17_reverse.mp3"></audio>
</main> </main>
<script src="socket.io.min.js"></script>
<script src="script.js"></script> <script src="script.js"></script>
</body> </body>
</html> </html>
@@ -78,7 +78,7 @@ body {
height: 600px; height: 600px;
border-radius: 50%; border-radius: 50%;
background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%); background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%);
animation: spin 5s linear infinite paused; /*animation: spin 5s linear infinite paused;*/
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -87,6 +87,10 @@ body {
margin: 20px 0; margin: 20px 0;
} }
.vinyl.reverse {
animation: spin-reverse 4s linear infinite;
}
.vinyl img { .vinyl img {
width: 40%; width: 40%;
border-radius: 50%; border-radius: 50%;
@@ -78,15 +78,22 @@ body {
height: 600px; height: 600px;
border-radius: 50%; border-radius: 50%;
background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%); background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%);
animation: spin 5s linear infinite paused; /*animation: spin 4s linear infinite;
animation-play-state: paused;*/
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
overflow: hidden; overflow: hidden;
transition: transform 0.3s linear;
cursor: pointer; cursor: pointer;
margin: 20px 0; margin: 20px 0;
} }
.vinyl.reverse {
animation: spin-reverse 4s linear infinite;
}
.vinyl img { .vinyl img {
width: 40%; width: 40%;
border-radius: 50%; border-radius: 50%;
@@ -166,12 +173,13 @@ body {
@keyframes spin { @keyframes spin {
from { from { transform: rotate(0deg); }
transform: rotate(0deg); to { transform: rotate(360deg); }
}
to {
transform: rotate(360deg);
} }
@keyframes spin-reverse {
from { transform: rotate(0deg); }
to { transform: rotate(-360deg); }
} }
@media (max-width: 768px) { @media (max-width: 768px) {
@@ -78,7 +78,7 @@ body {
height: 600px; height: 600px;
border-radius: 50%; border-radius: 50%;
background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%); background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%);
animation: spin 5s linear infinite paused; /*animation: spin 5s linear infinite paused;*/
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -87,6 +87,10 @@ body {
margin: 20px 0; margin: 20px 0;
} }
.vinyl.reverse {
animation: spin-reverse 4s linear infinite;
}
.vinyl img { .vinyl img {
width: 40%; width: 40%;
border-radius: 50%; border-radius: 50%;
@@ -78,7 +78,7 @@ body {
height: 600px; height: 600px;
border-radius: 50%; border-radius: 50%;
background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%); background: radial-gradient(circle at center, #444 0%, #111 60%, #000 100%);
animation: spin 5s linear infinite paused; /*animation: spin 5s linear infinite paused;*/
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@@ -87,6 +87,10 @@ body {
margin: 20px 0; margin: 20px 0;
} }
.vinyl.reverse {
animation: spin-reverse 4s linear infinite;
}
.vinyl img { .vinyl img {
width: 40%; width: 40%;
border-radius: 50%; border-radius: 50%;
+346
View File
@@ -11,6 +11,7 @@
"dependencies": { "dependencies": {
"express": "^4.21.2", "express": "^4.21.2",
"pug": "^3.0.3", "pug": "^3.0.3",
"serialport": "^13.0.0",
"socket.io": "^4.8.1" "socket.io": "^4.8.1"
} }
}, },
@@ -60,6 +61,280 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@serialport/binding-mock": {
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz",
"integrity": "sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==",
"license": "MIT",
"dependencies": {
"@serialport/bindings-interface": "^1.2.1",
"debug": "^4.3.3"
},
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/@serialport/binding-mock/node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@serialport/binding-mock/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/@serialport/bindings-cpp": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/bindings-cpp/-/bindings-cpp-13.0.0.tgz",
"integrity": "sha512-r25o4Bk/vaO1LyUfY/ulR6hCg/aWiN6Wo2ljVlb4Pj5bqWGcSRC4Vse4a9AcapuAu/FeBzHCbKMvRQeCuKjzIQ==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@serialport/bindings-interface": "1.2.2",
"@serialport/parser-readline": "12.0.0",
"debug": "4.4.0",
"node-addon-api": "8.3.0",
"node-gyp-build": "4.8.4"
},
"engines": {
"node": ">=18.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-delimiter": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-12.0.0.tgz",
"integrity": "sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==",
"license": "MIT",
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-readline": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-12.0.0.tgz",
"integrity": "sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==",
"license": "MIT",
"dependencies": {
"@serialport/parser-delimiter": "12.0.0"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/bindings-cpp/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@serialport/bindings-cpp/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/@serialport/bindings-interface": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@serialport/bindings-interface/-/bindings-interface-1.2.2.tgz",
"integrity": "sha512-CJaUd5bLvtM9c5dmO9rPBHPXTa9R2UwpkJ0wdh9JCYcbrPWsKz+ErvR0hBLeo7NPeiFdjFO4sonRljiw4d2XiA==",
"license": "MIT",
"engines": {
"node": "^12.22 || ^14.13 || >=16"
}
},
"node_modules/@serialport/parser-byte-length": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-13.0.0.tgz",
"integrity": "sha512-32yvqeTAqJzAEtX5zCrN1Mej56GJ5h/cVFsCDPbF9S1ZSC9FWjOqNAgtByseHfFTSTs/4ZBQZZcZBpolt8sUng==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/parser-cctalk": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-13.0.0.tgz",
"integrity": "sha512-RErAe57g9gvnlieVYGIn1xymb1bzNXb2QtUQd14FpmbQQYlcrmuRnJwKa1BgTCujoCkhtaTtgHlbBWOxm8U2uA==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/parser-delimiter": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-13.0.0.tgz",
"integrity": "sha512-Qqyb0FX1avs3XabQqNaZSivyVbl/yl0jywImp7ePvfZKLwx7jBZjvL+Hawt9wIG6tfq6zbFM24vzCCK7REMUig==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/parser-inter-byte-timeout": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-13.0.0.tgz",
"integrity": "sha512-a0w0WecTW7bD2YHWrpTz1uyiWA2fDNym0kjmPeNSwZ2XCP+JbirZt31l43m2ey6qXItTYVuQBthm75sPVeHnGA==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/parser-packet-length": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-packet-length/-/parser-packet-length-13.0.0.tgz",
"integrity": "sha512-60ZDDIqYRi0Xs2SPZUo4Jr5LLIjtb+rvzPKMJCohrO6tAqSDponcNpcB1O4W21mKTxYjqInSz+eMrtk0LLfZIg==",
"license": "MIT",
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/@serialport/parser-readline": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-13.0.0.tgz",
"integrity": "sha512-dov3zYoyf0dt1Sudd1q42VVYQ4WlliF0MYvAMA3MOyiU1IeG4hl0J6buBA2w4gl3DOCC05tGgLDN/3yIL81gsA==",
"license": "MIT",
"dependencies": {
"@serialport/parser-delimiter": "13.0.0"
},
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/parser-ready": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-13.0.0.tgz",
"integrity": "sha512-JNUQA+y2Rfs4bU+cGYNqOPnNMAcayhhW+XJZihSLQXOHcZsFnOa2F9YtMg9VXRWIcnHldHYtisp62Etjlw24bw==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/parser-regex": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-13.0.0.tgz",
"integrity": "sha512-m7HpIf56G5XcuDdA3DB34Z0pJiwxNRakThEHjSa4mG05OnWYv0IG8l2oUyYfuGMowQWaVnQ+8r+brlPxGVH+eA==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/parser-slip-encoder": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-slip-encoder/-/parser-slip-encoder-13.0.0.tgz",
"integrity": "sha512-fUHZEExm6izJ7rg0A1yjXwu4sOzeBkPAjDZPfb+XQoqgtKAk+s+HfICiYn7N2QU9gyaeCO8VKgWwi+b/DowYOg==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/parser-spacepacket": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/parser-spacepacket/-/parser-spacepacket-13.0.0.tgz",
"integrity": "sha512-DoXJ3mFYmyD8X/8931agJvrBPxqTaYDsPoly9/cwQSeh/q4EjQND9ySXBxpWz5WcpyCU4jOuusqCSAPsbB30Eg==",
"license": "MIT",
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/stream": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-13.0.0.tgz",
"integrity": "sha512-F7xLJKsjGo2WuEWMSEO1SimRcOA+WtWICsY13r0ahx8s2SecPQH06338g28OT7cW7uRXI7oEQAk62qh5gHJW3g==",
"license": "MIT",
"dependencies": {
"@serialport/bindings-interface": "1.2.2",
"debug": "4.4.0"
},
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/@serialport/stream/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@serialport/stream/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/@socket.io/component-emitter": { "node_modules/@socket.io/component-emitter": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
@@ -818,6 +1093,26 @@
"node": ">= 0.6" "node": ">= 0.6"
} }
}, },
"node_modules/node-addon-api": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz",
"integrity": "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==",
"license": "MIT",
"engines": {
"node": "^18 || ^20 || >= 21"
}
},
"node_modules/node-gyp-build": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
"license": "MIT",
"bin": {
"node-gyp-build": "bin.js",
"node-gyp-build-optional": "optional.js",
"node-gyp-build-test": "build-test.js"
}
},
"node_modules/object-assign": { "node_modules/object-assign": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -1142,6 +1437,57 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/serialport": {
"version": "13.0.0",
"resolved": "https://registry.npmjs.org/serialport/-/serialport-13.0.0.tgz",
"integrity": "sha512-PHpnTd8isMGPfFTZNCzOZp9m4mAJSNWle9Jxu6BPTcWq7YXl5qN7tp8Sgn0h+WIGcD6JFz5QDgixC2s4VW7vzg==",
"license": "MIT",
"dependencies": {
"@serialport/binding-mock": "10.2.2",
"@serialport/bindings-cpp": "13.0.0",
"@serialport/parser-byte-length": "13.0.0",
"@serialport/parser-cctalk": "13.0.0",
"@serialport/parser-delimiter": "13.0.0",
"@serialport/parser-inter-byte-timeout": "13.0.0",
"@serialport/parser-packet-length": "13.0.0",
"@serialport/parser-readline": "13.0.0",
"@serialport/parser-ready": "13.0.0",
"@serialport/parser-regex": "13.0.0",
"@serialport/parser-slip-encoder": "13.0.0",
"@serialport/parser-spacepacket": "13.0.0",
"@serialport/stream": "13.0.0",
"debug": "4.4.0"
},
"engines": {
"node": ">=20.0.0"
},
"funding": {
"url": "https://opencollective.com/serialport/donate"
}
},
"node_modules/serialport/node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/serialport/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/serve-static": { "node_modules/serve-static": {
"version": "1.16.2", "version": "1.16.2",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
@@ -12,6 +12,7 @@
"dependencies": { "dependencies": {
"express": "^4.21.2", "express": "^4.21.2",
"pug": "^3.0.3", "pug": "^3.0.3",
"serialport": "^13.0.0",
"socket.io": "^4.8.1" "socket.io": "^4.8.1"
} }
} }
+10
View File
@@ -0,0 +1,10 @@
loop
====
```shell
git clone
npm install
node server.js
```
https://serialport.io/docs/guide-usage
+72
View File
@@ -0,0 +1,72 @@
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 app = express();
const server = createServer(app);
const io = new Server(server);
const port = 3000
// https://serialport.io/docs/guide-usage
var arduinoCOMPort = "/dev/ttyUSB0";
var arduinoSerialPort = new SerialPort({
path: arduinoCOMPort,
baudRate: 9600
});
arduinoSerialPort.on('open',function() {
console.log('Serial Port ' + arduinoCOMPort + ' is opened.');
});
// // 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'))
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);
socket.emit('position', data);
})
});
server.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+8 -6
View File
@@ -1,7 +1,9 @@
loop Loop
==== ====
```shell
git clone # Node
npm install https://gitea.esadhar.fr/el-yazide.mohamed/loop
node server.js
``` # Arduino
https://arduinogetstarted.com/tutorials/arduino-dc-motor
-33
View File
@@ -1,33 +0,0 @@
const express = require('express');
const { createServer } = require('node:http');
const { Server } = require('socket.io');
const app = express();
const server = createServer(app);
const io = new Server(server);
const port = 3000
app.set('view engine', 'pug')
app.use(express.static('assets'))
app.get('/', (req, res) => {
// res.send('Hello World!')
// res.render('index', { title: 'Hey', message: 'Hello there PUG!' })
res.sendFile('main.html');
})
io.on('connection', (socket) => {
console.log('a user connected');
let speed = 0.1;
setInterval(() => {
speed+=0.1;
socket.emit('speed', speed);
}, 2000);
});
server.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
+1
View File
@@ -0,0 +1 @@
.vscode
+18
View File
@@ -0,0 +1,18 @@
#include <Encoder.h>
long last_position = 0;
Encoder myEnc(2, 3); // pins for A and B
void setup() {
Serial.begin(9600);
}
void loop() {
long position = myEnc.read();
if(position != last_position){
last_position = position;
Serial.println(position);
}
delay(100);
}