Tracking de l'application VNode (moteur du jeu, services, broker.. etc
This commit is contained in:
161
VNode/services/buzzer/_a retravailler_test-buzzer-manager.js
Normal file
161
VNode/services/buzzer/_a retravailler_test-buzzer-manager.js
Normal file
@ -0,0 +1,161 @@
|
||||
// Import necessary modules
|
||||
const mqtt = require('mqtt');
|
||||
|
||||
// MQTT broker configuration
|
||||
const brokerUrl = 'mqtt://localhost'; // Broker URL (change if needed)
|
||||
const options = {
|
||||
clientId: 'test_buzzer_manager',
|
||||
clean: true
|
||||
};
|
||||
|
||||
// Set up MQTT client
|
||||
const client = mqtt.connect(brokerUrl, options);
|
||||
|
||||
// Variables for tracking test results
|
||||
let testResults = {
|
||||
buzzerActivity: false,
|
||||
confirmationReceived: false,
|
||||
statusBlocked: false,
|
||||
statusUnblocked: false,
|
||||
tiltAddConfirmed: false,
|
||||
tiltRemoveConfirmed: false,
|
||||
tiltIgnored: false,
|
||||
unlockConfirmation: false,
|
||||
tiltUpdateAdd: false,
|
||||
tiltUpdateRemove: false
|
||||
};
|
||||
|
||||
// Subscribe to topics to capture the responses from the buzzer manager
|
||||
client.on('connect', () => {
|
||||
console.log('[INFO] Connected to MQTT broker for testing');
|
||||
|
||||
// Subscribe to all topics related to the buzzer manager
|
||||
client.subscribe('vulture/buzzer/#', (err) => {
|
||||
if (err) console.error('[ERROR] Failed to subscribe to topics for testing');
|
||||
else console.log('[INFO] Subscribed to topics successfully');
|
||||
});
|
||||
|
||||
// Run the test sequence after a short delay
|
||||
setTimeout(runTestSequence, 500);
|
||||
});
|
||||
|
||||
// Capture and process incoming MQTT messages
|
||||
client.on('message', (topic, message) => {
|
||||
const payload = JSON.parse(message.toString());
|
||||
console.log(`[INFO] Message received on ${topic}: ${message.toString()}`);
|
||||
|
||||
// Track the test results based on the topics and payloads
|
||||
if (topic.startsWith('vulture/buzzer/activity') && payload.buzzer_id === 1) {
|
||||
testResults.buzzerActivity = true;
|
||||
}
|
||||
|
||||
if (topic.startsWith(`vulture/buzzer/confirmation/1`) && payload.status === "received") {
|
||||
testResults.confirmationReceived = true;
|
||||
}
|
||||
|
||||
if (topic === 'vulture/buzzer/status' && payload.status === "blocked") {
|
||||
testResults.statusBlocked = true;
|
||||
}
|
||||
|
||||
if (topic === 'vulture/buzzer/status' && payload.status === "unblocked") {
|
||||
testResults.statusUnblocked = true;
|
||||
}
|
||||
|
||||
if (topic.startsWith(`vulture/buzzer/tilt/confirmation/2`) && payload.status === "received" && payload.action === "add") {
|
||||
testResults.tiltAddConfirmed = true;
|
||||
}
|
||||
|
||||
if (topic.startsWith(`vulture/buzzer/tilt/confirmation/2`) && payload.status === "received" && payload.action === "remove") {
|
||||
testResults.tiltRemoveConfirmed = true;
|
||||
}
|
||||
|
||||
if (topic === `vulture/buzzer/tilt/ignored/2` && payload.status === "tilt_ignored") {
|
||||
testResults.tiltIgnored = true;
|
||||
}
|
||||
|
||||
if (topic === 'vulture/buzzer/status' && payload.status === "tilt_update") {
|
||||
// Check for tilt update with added buzzer
|
||||
if (payload.tilt_buzzers.includes(2) && payload.message.includes("added")) {
|
||||
testResults.tiltUpdateAdd = true;
|
||||
}
|
||||
|
||||
// Check for tilt update with removed buzzer
|
||||
if (!payload.tilt_buzzers.includes(2) && payload.message.includes("removed")) {
|
||||
testResults.tiltUpdateRemove = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (topic === 'vulture/buzzer/unlock/confirmation' && payload.status === "received") {
|
||||
testResults.unlockConfirmation = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Function to run the complete test sequence
|
||||
function runTestSequence() {
|
||||
console.log('[INFO] Starting test sequence...');
|
||||
|
||||
// 1. Simulate a buzzer press (buzzer 1, color red)
|
||||
console.log('[TEST] Simulating buzzer press (ID 1, color #FF0000)...');
|
||||
client.publish('vulture/buzzer/pressed/1', JSON.stringify({
|
||||
buzzer_id: 1,
|
||||
color: "#FF0000"
|
||||
}));
|
||||
|
||||
// 2. Simulate a second buzzer press (buzzer 2, color blue) to check blocking
|
||||
setTimeout(() => {
|
||||
console.log('[TEST] Simulating second buzzer press (ID 2, color #0000FF)...');
|
||||
client.publish('vulture/buzzer/pressed/2', JSON.stringify({
|
||||
buzzer_id: 2,
|
||||
color: "#0000FF"
|
||||
}));
|
||||
}, 1000);
|
||||
|
||||
// 3. Simulate adding a buzzer to tilt mode (buzzer 2)
|
||||
setTimeout(() => {
|
||||
console.log('[TEST] Adding buzzer ID 2 to tilt mode...');
|
||||
client.publish('vulture/buzzer/tilt', JSON.stringify({
|
||||
buzzer_id: 2,
|
||||
status: "add"
|
||||
}));
|
||||
}, 1500);
|
||||
|
||||
// 4. Simulate pressing a buzzer in tilt mode (should be ignored)
|
||||
setTimeout(() => {
|
||||
console.log('[TEST] Simulating tilt buzzer press (ID 2, color #0000FF)...');
|
||||
client.publish('vulture/buzzer/pressed/2', JSON.stringify({
|
||||
buzzer_id: 2,
|
||||
color: "#0000FF"
|
||||
}));
|
||||
}, 2000);
|
||||
|
||||
// 5. Remove tilt mode from buzzer 2
|
||||
setTimeout(() => {
|
||||
console.log('[TEST] Removing tilt mode for buzzer ID 2...');
|
||||
client.publish('vulture/buzzer/tilt', JSON.stringify({
|
||||
buzzer_id: 2,
|
||||
status: "remove"
|
||||
}));
|
||||
}, 2500);
|
||||
|
||||
// 6. Unlock buzzers to reset state
|
||||
setTimeout(() => {
|
||||
console.log('[TEST] Unlocking buzzers...');
|
||||
client.publish('vulture/buzzer/unlock', '{}');
|
||||
}, 3000);
|
||||
|
||||
// 7. Display results
|
||||
setTimeout(() => {
|
||||
console.log('[INFO] Test sequence complete. Results:');
|
||||
console.log(`1. Buzzer activity detected for buzzer 1: ${testResults.buzzerActivity ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`2. Confirmation received for buzzer 1: ${testResults.confirmationReceived ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`3. Buzzer 1 status set to "blocked": ${testResults.statusBlocked ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`4. Buzzer status set to "unblocked": ${testResults.statusUnblocked ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`5. Tilt mode add confirmed for buzzer 2: ${testResults.tiltAddConfirmed ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`6. Tilted buzzer press ignored: ${testResults.tiltIgnored ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`7. Tilt status update sent (add): ${testResults.tiltUpdateAdd ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`8. Tilt mode remove confirmed for buzzer 2: ${testResults.tiltRemoveConfirmed ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`9. Tilt status update sent (remove): ${testResults.tiltUpdateRemove ? 'PASSED' : 'FAILED'}`);
|
||||
console.log(`10. Unlock confirmation received: ${testResults.unlockConfirmation ? 'PASSED' : 'FAILED'}`);
|
||||
client.end(); // End the MQTT connection
|
||||
}, 4000);
|
||||
}
|
223
VNode/services/buzzer/buzzer-manager.js
Normal file
223
VNode/services/buzzer/buzzer-manager.js
Normal file
@ -0,0 +1,223 @@
|
||||
// Import necessary modules
|
||||
const mqtt = require('mqtt');
|
||||
|
||||
// MQTT broker configuration
|
||||
const brokerUrl = 'mqtt://localhost'; // Broker URL (change if needed)
|
||||
const clientId = 'buzzer_manager';
|
||||
const options = {
|
||||
clientId,
|
||||
clean: true
|
||||
};
|
||||
|
||||
// State variables
|
||||
let buzzerActive = false; // Indicates if buzzers are blocked
|
||||
let buzzerThatPressed = null; // Stores the ID of the buzzer that pressed first
|
||||
let tiltBuzzers = new Set(); // List of buzzer IDs currently in "tilt" mode
|
||||
|
||||
// Connect to the MQTT broker
|
||||
const client = mqtt.connect(brokerUrl, options);
|
||||
|
||||
client.on('connect', () => {
|
||||
console.log(`[INFO] Connected to MQTT broker ${brokerUrl} with ID ${clientId}`);
|
||||
|
||||
// Subscribe to topics related to buzzer presses, unlocking, and tilt management
|
||||
client.subscribe('vulture/buzzer/pressed/#', (err) => {
|
||||
if (err) console.error('[ERROR] Failed to subscribe to buzzer presses');
|
||||
else console.log('[INFO] Successfully subscribed to buzzer presses');
|
||||
});
|
||||
|
||||
client.subscribe('vulture/buzzer/unlock', (err) => {
|
||||
if (err) console.error('[ERROR] Failed to subscribe to buzzer unlock');
|
||||
else console.log('[INFO] Successfully subscribed to buzzer unlock');
|
||||
});
|
||||
|
||||
client.subscribe('vulture/buzzer/tilt', (err) => {
|
||||
if (err) console.error('[ERROR] Failed to subscribe to tilt management');
|
||||
else console.log('[INFO] Successfully subscribed to tilt management');
|
||||
});
|
||||
});
|
||||
|
||||
// Validate buzzer payload
|
||||
function validateBuzzerPayload(payload) {
|
||||
const { buzzer_id, color } = payload;
|
||||
|
||||
// Validate buzzer ID (should be a positive integer)
|
||||
if (typeof buzzer_id !== 'number' || buzzer_id <= 0) {
|
||||
console.error(`[ERROR] Invalid buzzer ID: ${buzzer_id}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate color (should be in the format #RRGGBB)
|
||||
const validColor = /^#[0-9A-F]{6}$/i.test(color);
|
||||
if (!validColor) {
|
||||
console.error(`[ERROR] Invalid color: ${color}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Send updated tilt status
|
||||
function sendTiltStatus(action, buzzerId) {
|
||||
const tiltList = Array.from(tiltBuzzers); // Convert Set to Array
|
||||
|
||||
client.publish('vulture/buzzer/status', JSON.stringify({
|
||||
status: "tilt_update",
|
||||
tilt_buzzers: tiltList,
|
||||
message: `Buzzer ID ${buzzerId} ${action} to tilt mode`,
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
|
||||
console.log(`[INFO] Tilt status updated: ${tiltList.length} buzzers in tilt mode`);
|
||||
}
|
||||
|
||||
// Handle incoming messages
|
||||
client.on('message', (topic, message) => {
|
||||
let payload;
|
||||
|
||||
// Parse the incoming message
|
||||
try {
|
||||
payload = JSON.parse(message.toString());
|
||||
} catch (e) {
|
||||
console.error(`[ERROR] Invalid JSON message received on topic ${topic}: ${message.toString()}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Manage tilt mode for buzzers
|
||||
if (topic === 'vulture/buzzer/tilt') {
|
||||
const { buzzer_id, status } = payload;
|
||||
|
||||
if (typeof buzzer_id !== 'number' || !['add', 'remove'].includes(status)) {
|
||||
console.error('[ERROR] Invalid tilt payload, message ignored.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Update tilt status based on the command
|
||||
if (status === 'add') {
|
||||
tiltBuzzers.add(buzzer_id);
|
||||
console.log(`[INFO] Buzzer ID ${buzzer_id} added to tilt mode`);
|
||||
} else if (status === 'remove') {
|
||||
tiltBuzzers.delete(buzzer_id);
|
||||
console.log(`[INFO] Buzzer ID ${buzzer_id} removed from tilt mode`);
|
||||
}
|
||||
|
||||
// Confirm that the tilt command has been received
|
||||
client.publish(`vulture/buzzer/tilt/confirmation/${buzzer_id}`, JSON.stringify({
|
||||
status: "received",
|
||||
action: status,
|
||||
buzzer_id: buzzer_id,
|
||||
message: `Tilt command '${status}' received for buzzer ID ${buzzer_id}`,
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
|
||||
// Send the updated tilt status to all components
|
||||
sendTiltStatus(status === 'add' ? 'added' : 'removed', buzzer_id);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Detect a buzzer press
|
||||
if (topic.startsWith('vulture/buzzer/pressed/')) {
|
||||
// Validate buzzer payload
|
||||
if (!validateBuzzerPayload(payload)) {
|
||||
console.error('[ERROR] Invalid buzzer payload, message ignored.');
|
||||
return;
|
||||
}
|
||||
|
||||
const buzzerId = payload.buzzer_id; // Unique buzzer ID
|
||||
const color = payload.color; // Associated hex color
|
||||
|
||||
// Always send a confirmation, even if the buzzer is in tilt mode
|
||||
client.publish(`vulture/buzzer/confirmation/${buzzerId}`, JSON.stringify({
|
||||
status: "received",
|
||||
buzzer_id: buzzerId,
|
||||
message: `Buzzer ID ${buzzerId} received (Color: ${color})`,
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
|
||||
// Ignore if the buzzer is in tilt mode, but notify this event
|
||||
if (tiltBuzzers.has(buzzerId)) {
|
||||
console.log(`[INFO] Buzzer ID ${buzzerId} ignored (Tilt mode active)`);
|
||||
|
||||
// Notify that the buzzer is in tilt mode and ignored
|
||||
client.publish(`vulture/buzzer/tilt/ignored/${buzzerId}`, JSON.stringify({
|
||||
status: "tilt_ignored",
|
||||
buzzer_id: buzzerId,
|
||||
message: `Buzzer ID ${buzzerId} is in tilt mode and ignored.`,
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify activity even if buzzers are blocked
|
||||
client.publish('vulture/buzzer/activity', JSON.stringify({
|
||||
buzzer_id: buzzerId,
|
||||
color: color,
|
||||
status: buzzerActive ? "blocked" : "free",
|
||||
message: `Activity detected on buzzer ID ${buzzerId} (Color: ${color})`,
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
|
||||
if (!buzzerActive) {
|
||||
// Block further buzzers and record the first pressed ID
|
||||
buzzerActive = true;
|
||||
buzzerThatPressed = buzzerId;
|
||||
|
||||
console.log(`[INFO] Buzzer activated by ID: ${buzzerId} (Color: ${color})`);
|
||||
|
||||
// Notify the light manager to change to the team's color
|
||||
client.publish('vulture/light/change', JSON.stringify({
|
||||
color: color,
|
||||
effect: 'full_color'
|
||||
}));
|
||||
|
||||
// Notify all components of buzzer blocking
|
||||
client.publish('vulture/buzzer/status', JSON.stringify({
|
||||
status: "blocked",
|
||||
buzzer_id: buzzerId,
|
||||
color: color,
|
||||
message: `Buzzer activated by ID ${buzzerId} (Color: ${color})`,
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
|
||||
console.log(`[INFO] Buzzers blocked and notification sent`);
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock buzzers
|
||||
if (topic === 'vulture/buzzer/unlock') {
|
||||
console.log('[INFO] Buzzer unlock requested');
|
||||
|
||||
// Confirm receipt of unlock command
|
||||
client.publish('vulture/buzzer/unlock/confirmation', JSON.stringify({
|
||||
status: "received",
|
||||
message: "Buzzer unlock command received.",
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
// Notify the light manager to change to the team's color
|
||||
client.publish('vulture/light/change', JSON.stringify({
|
||||
color: "#FFFFFF",
|
||||
effect: 'rainbow'
|
||||
}));
|
||||
|
||||
|
||||
// Reset buzzer manager state
|
||||
buzzerActive = false;
|
||||
buzzerThatPressed = null;
|
||||
|
||||
// Notify all components of buzzer unlock
|
||||
client.publish('vulture/buzzer/status', JSON.stringify({
|
||||
status: "unblocked",
|
||||
message: "Buzzers unblocked and ready for activation.",
|
||||
timestamp: new Date().toISOString()
|
||||
}));
|
||||
|
||||
console.log('[INFO] Buzzers unblocked and notification sent');
|
||||
}
|
||||
});
|
||||
|
||||
client.on('error', (err) => {
|
||||
console.error(`[ERROR] Error connecting to broker: ${err}`);
|
||||
});
|
||||
|
||||
console.log('[INFO] Buzzer manager started...');
|
39
VNode/services/buzzer/buzzer-watcher.js
Normal file
39
VNode/services/buzzer/buzzer-watcher.js
Normal file
@ -0,0 +1,39 @@
|
||||
const ping = require('ping');
|
||||
const mqtt = require('mqtt');
|
||||
const fs = require('fs');
|
||||
|
||||
// Lecture du fichier de configuration
|
||||
const config = JSON.parse(fs.readFileSync('\services\\config\\config_network.json', 'utf8'));
|
||||
|
||||
// Extraction des informations de config
|
||||
const { hosts: { buzzers: { IP: buzzerIPs, MQTTconfig: { mqttHost, mqttTopic } } } } = config;
|
||||
|
||||
// Connexion au broker MQTT
|
||||
const client = mqtt.connect(mqttHost);
|
||||
|
||||
client.on('connect', () => {
|
||||
console.log(`Connecté au broker MQTT à ${mqttHost}`);
|
||||
|
||||
// Fonction pour pinger les buzzers et publier l'état
|
||||
const pingAndPublish = async () => {
|
||||
for (const [buzzerName, ip] of Object.entries(buzzerIPs)) {
|
||||
try {
|
||||
const res = await ping.promise.probe(ip);
|
||||
const status = res.alive ? 'online' : 'offline';
|
||||
|
||||
// Publication du statut dans le topic MQTT
|
||||
client.publish(`${mqttTopic}`, JSON.stringify({ buzzer: buzzerName, ip, status }));
|
||||
console.log(`Ping ${buzzerName} (${ip}) - Status: ${status}`);
|
||||
} catch (error) {
|
||||
console.error(`Erreur avec le buzzer ${buzzerName} (${ip}):`, error.message);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Pinger toutes les 5 secondes
|
||||
setInterval(pingAndPublish, 3000);
|
||||
});
|
||||
|
||||
client.on('error', (error) => {
|
||||
console.error('Erreur de connexion au broker MQTT:', error.message);
|
||||
});
|
18
VNode/services/config/config_game.json
Normal file
18
VNode/services/config/config_game.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"services": {
|
||||
"mqttHost": "mqtt://192.168.1.30",
|
||||
"score":{
|
||||
"MQTTconfig":{
|
||||
"mqttScoreTopic": "game/score",
|
||||
"mqttScoreChangeTopic": "game/score/update"
|
||||
}
|
||||
},
|
||||
"quizzcollector":{
|
||||
"MQTTconfig":{
|
||||
"mqttQuizzCollectorListTopic": "game/quizz-collector/list",
|
||||
"mqttQuizzCollectorCmdTopic": "game/quizz-collector/cmd"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
17
VNode/services/config/config_network.json
Normal file
17
VNode/services/config/config_network.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"hosts": {
|
||||
"buzzers":{
|
||||
"IP":{
|
||||
"redBuzzerIP": "8.8.8.6",
|
||||
"blueBuzzerIP": "8.8.8.8",
|
||||
"greenBuzzerIP": "8.8.8.8",
|
||||
"yellowBuzzerIP": "8.8.8.8"
|
||||
},
|
||||
"MQTTconfig":{
|
||||
"mqttHost": "mqtt://192.168.1.28",
|
||||
"mqttTopic": "buzzer/watcher"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
52
VNode/services/game/quizz-collector.js
Normal file
52
VNode/services/game/quizz-collector.js
Normal file
@ -0,0 +1,52 @@
|
||||
const fs = require('fs');
|
||||
const mqtt = require('mqtt');
|
||||
|
||||
// Lecture du fichier de configuration
|
||||
const config = JSON.parse(fs.readFileSync('\services\\config\\config_game.json', 'utf8'));
|
||||
|
||||
// Extraction des informations de config
|
||||
const { services: { mqttHost, quizzcollector: { MQTTconfig: { mqttQuizzCollectorListTopic, mqttQuizzCollectorCmdTopic } } } } = config;
|
||||
|
||||
// Configuration
|
||||
const folderPath = 'quizz'; // Remplace par le chemin de ton dossier
|
||||
|
||||
// Connexion au broker MQTT
|
||||
const client = mqtt.connect(mqttHost);
|
||||
|
||||
client.on('connect', () => {
|
||||
console.log('Connecté au broker MQTT');
|
||||
client.subscribe(mqttQuizzCollectorCmdTopic, (err) => {
|
||||
if (err) {
|
||||
console.error("Erreur lors de l'abonnement au topic de commande:", err);
|
||||
} else {
|
||||
console.log(`Abonné au topic ${mqttQuizzCollectorCmdTopic}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
client.on('message', (topic, message) => {
|
||||
if (topic === mqttQuizzCollectorCmdTopic) {
|
||||
console.log('Commande reçue, lecture du dossier en cours...');
|
||||
Collect();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function Collect() {
|
||||
fs.readdir(folderPath, (err, files) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de la lecture du dossier:', err);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Dossiers trouvés:', files);
|
||||
const message = JSON.stringify( files );
|
||||
client.publish(mqttQuizzCollectorListTopic, message, { qos: 1 }, (err) => {
|
||||
if (err) {
|
||||
console.error('Erreur lors de la publication MQTT:', err);
|
||||
} else {
|
||||
console.log('Liste des fichiers publiée sur MQTT');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
232
VNode/services/game/score-manager.js
Normal file
232
VNode/services/game/score-manager.js
Normal file
@ -0,0 +1,232 @@
|
||||
const args = process.argv;
|
||||
|
||||
// Vérification si un paramètre est passé, si c'est le cas c'est qu'on fournis un fichier de score pour reprendre le jeu la ou il était
|
||||
if (args[2] !== undefined){
|
||||
global.ScoreFile = args[2]
|
||||
}else{
|
||||
global.ScoreFile = "XXX.json"
|
||||
}
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const mqtt = require('mqtt');
|
||||
|
||||
// Fonction pour générer un nom de fichier unique
|
||||
function generateUniqueFileName(baseName) {
|
||||
const now = new Date();
|
||||
const timestamp = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}_${String(now.getHours()).padStart(2, '0')}H${String(now.getMinutes()).padStart(2, '0')}`;
|
||||
return `${baseName}_${timestamp}.json`;
|
||||
}
|
||||
|
||||
// Chemin vers le dossier "score" et le fichier
|
||||
global.scoreDir = path.join(__dirname, 'score');
|
||||
global.filePath = path.join(scoreDir, ScoreFile); // Remplace "XX.json" par le nom de ton fichier JSON
|
||||
|
||||
// Vérifie si le dossier "score" existe, sinon le crée
|
||||
if (!fs.existsSync(scoreDir)) {
|
||||
fs.mkdirSync(scoreDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Vérifie si le fichier existe dans le dossier "score"
|
||||
fs.access(filePath, fs.constants.F_OK, (err) => {
|
||||
if (!err) {
|
||||
// Le fichier existe, on le lit et on le parse en JSON
|
||||
fs.readFile(filePath, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error("Erreur de lecture du fichier :", err);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
global.jsonData = JSON.parse(data);
|
||||
console.log("Propriétés importées depuis le fichier JSON :");
|
||||
} catch (parseErr) {
|
||||
console.error("Erreur de parsing JSON :", parseErr);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Le fichier n'existe pas, on en crée un nouveau avec un nom unique dans "score"
|
||||
const newFileName = generateUniqueFileName('Score');
|
||||
const newFilePath = path.join(scoreDir, newFileName);
|
||||
const initialContent = {
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fs.writeFile(newFilePath, JSON.stringify(initialContent, null, 2), (err) => {
|
||||
if (err) {
|
||||
console.error("Erreur de création du fichier :", err);
|
||||
return;
|
||||
}
|
||||
console.log(`Fichier JSON créé avec succès : ${newFilePath}`);
|
||||
// Mettre à jour ScoreFile et filePath
|
||||
|
||||
// Charger les données initiales si nécessaire
|
||||
global.jsonData = initialContent;
|
||||
global.filePath = newFilePath
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Fonction pour mettre à jour le score d'une équipe
|
||||
function updateTeamTotalScore(teamColor, points) {
|
||||
fs.readFile(filePath, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error("Erreur de lecture du fichier :", err);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const jsonData = JSON.parse(data);
|
||||
// Vérifier si l'équipe existe
|
||||
if (!jsonData.TEAM.hasOwnProperty(teamColor)) {
|
||||
console.error(`L'équipe ${teamColor} n'existe pas.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const change = parseInt(points, 10);
|
||||
|
||||
// Mettre à jour le score
|
||||
jsonData.TEAM[teamColor].TotalScore += points;
|
||||
console.log(`Le score total pour l'équipe ${teamColor} est de ${jsonData.TEAM[teamColor].TotalScore} points !`)
|
||||
// Enregistrer les modifications dans le fichier
|
||||
client.publish(mqttScoreTopic, JSON.stringify(jsonData));
|
||||
fs.writeFile(filePath, JSON.stringify(jsonData, null, 2), (err) => {
|
||||
if (err) {
|
||||
console.error("Erreur lors de l'écriture du fichier :", err);
|
||||
} else {
|
||||
console.log(`Le score total de l'équipe ${teamColor} a été mis à jour avec succès dans le fichier json !`);
|
||||
}
|
||||
});
|
||||
} catch (parseErr) {
|
||||
console.error("Erreur de parsing JSON :", parseErr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Lecture du fichier de configuration
|
||||
const config = JSON.parse(fs.readFileSync('\services\\config\\config_game.json', 'utf8'));
|
||||
|
||||
// Extraction des informations de config
|
||||
const { services: { mqttHost, score: { MQTTconfig: { mqttScoreTopic, mqttScoreChangeTopic } } } } = config;
|
||||
console.log(mqttScoreChangeTopic)
|
||||
// Connexion au broker MQTT
|
||||
const client = mqtt.connect(mqttHost);
|
||||
|
||||
client.on('connect', () => {
|
||||
console.log(`Connecté au broker MQTT à ${mqttHost}`);
|
||||
|
||||
client.subscribe(mqttScoreChangeTopic, (err) => {
|
||||
if (err) console.error('[ERROR] impossible de souscrire au topic de gestion du score total');
|
||||
else console.log(`[INFO] Souscription réalisée avec succès au topic ${mqttScoreChangeTopic}]`);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Gestion des messages entrants
|
||||
client.on('message', (topic, message) => {
|
||||
let payload;
|
||||
let process;
|
||||
let Team;
|
||||
let Action;
|
||||
|
||||
try {
|
||||
// Analyse du message reçu
|
||||
payload = JSON.parse(message.toString());
|
||||
} catch (e) {
|
||||
console.error(`[ERROR] Invalid JSON message received on topic ${topic}: ${message.toString()}`);
|
||||
return;
|
||||
}
|
||||
// Vérifie que le payload est bien un objet
|
||||
if (payload && typeof payload === 'object') {
|
||||
// Extraire la clé (la couleur) et la valeur associée
|
||||
Team = Object.keys(payload)[0]; // La première (et unique) clé
|
||||
Action = payload[Team]; // La valeur associée
|
||||
//console.log(`Team: ${Team}, Action: ${Action}`);
|
||||
process = true;
|
||||
} else {
|
||||
console.error(typeof payload);
|
||||
process = false;
|
||||
}
|
||||
|
||||
if (process === true){
|
||||
let currentScore = 0;
|
||||
let change = 0 ;
|
||||
switch (Team){
|
||||
case "Red":
|
||||
change = parseInt(Action, 10); // Convertit 'action' en entier
|
||||
if (!isNaN(change)) {
|
||||
updateTeamTotalScore("Red", change)
|
||||
} else {
|
||||
console.error(`Action invalide : ${action}`);
|
||||
}
|
||||
break;
|
||||
case "Blue":
|
||||
change = parseInt(Action, 10); // Convertit 'action' en entier
|
||||
if (!isNaN(change)) {
|
||||
updateTeamTotalScore("Blue", change)
|
||||
} else {
|
||||
console.error(`Action invalide : ${action}`);
|
||||
}
|
||||
break;
|
||||
case "Green":
|
||||
change = parseInt(Action, 10); // Convertit 'action' en entier
|
||||
if (!isNaN(change)) {
|
||||
updateTeamTotalScore("Green", change)
|
||||
} else {
|
||||
console.error(`Action invalide : ${action}`);
|
||||
}
|
||||
break;
|
||||
case "Yellow":
|
||||
change = parseInt(Action, 10); // Convertit 'action' en entier
|
||||
if (!isNaN(change)) {
|
||||
updateTeamTotalScore("Yellow", change)
|
||||
} else {
|
||||
console.error(`Action invalide : ${action}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
(async () => {
|
||||
while (true) {
|
||||
console.log("Boucle en arrière-plan");
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000)); // Pause de 2 secondes
|
||||
//client.publish(mqttScoreTopic, JSON.stringify(global.jsonData));
|
||||
}
|
||||
})();
|
||||
|
||||
client.on('error', (error) => {
|
||||
console.error('Erreur de connexion au broker MQTT:', error.message);
|
||||
});
|
||||
|
28
VNode/services/game/score/Score_2024-11-18_19H39.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_19H39.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_19H48.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_19H48.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_19H54.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_19H54.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_19H55.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_19H55.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H35.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H35.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H42.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H42.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H43.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H43.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H44.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H44.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H45.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H45.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H46.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H46.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H47.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H47.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H49.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H49.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
28
VNode/services/game/score/Score_2024-11-18_21H50.json
Normal file
28
VNode/services/game/score/Score_2024-11-18_21H50.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"Score": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
32
VNode/services/game/score/Score_2024-11-18_21H51.json
Normal file
32
VNode/services/game/score/Score_2024-11-18_21H51.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 22,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 63,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 26,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 15,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
32
VNode/services/game/score/Score_2025-02-02_20H09.json
Normal file
32
VNode/services/game/score/Score_2025-02-02_20H09.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
32
VNode/services/game/score/Score_2025-02-02_20H11.json
Normal file
32
VNode/services/game/score/Score_2025-02-02_20H11.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 20,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
32
VNode/services/game/score/Score_2025-02-02_20H14.json
Normal file
32
VNode/services/game/score/Score_2025-02-02_20H14.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"TEAM": {
|
||||
"Red": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 1,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Blue": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Yellow": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
},
|
||||
"Green": {
|
||||
"Name": "XXX",
|
||||
"TotalScore": 0,
|
||||
"RoundScore": 0,
|
||||
"Penality": 0,
|
||||
"MasterPoint": 0
|
||||
}
|
||||
}
|
||||
}
|
138
VNode/services/light/light-manager.js
Normal file
138
VNode/services/light/light-manager.js
Normal file
@ -0,0 +1,138 @@
|
||||
// Import du module MQTT
|
||||
const mqtt = require('mqtt');
|
||||
|
||||
// Configuration du broker MQTT et de WLED
|
||||
const brokerUrl = 'mqtt://localhost'; // Change ce lien si nécessaire
|
||||
const clientId = 'light_manager_wled';
|
||||
const wledTopicBase = 'wled/all'; // Le topic de base pour ton ruban WLED
|
||||
const options = {
|
||||
clientId,
|
||||
clean: true
|
||||
};
|
||||
|
||||
// État des lumières
|
||||
let currentColor = '#FFFFFF'; // Couleur par défaut (blanc)
|
||||
let currentEffect = 'none'; // Pas d'effet par défaut
|
||||
|
||||
// Connexion au broker MQTT
|
||||
const client = mqtt.connect(brokerUrl, options);
|
||||
|
||||
client.on('connect', () => {
|
||||
console.log(`[INFO] Connected to MQTT broker ${brokerUrl} as ${clientId}`);
|
||||
|
||||
// Souscription aux topics de gestion de lumière
|
||||
client.subscribe('vulture/light/#', (err) => {
|
||||
if (err) console.error('[ERROR] Subscription to light topics failed');
|
||||
else console.log('[INFO] Successfully subscribed to light topics');
|
||||
});
|
||||
});
|
||||
|
||||
// Fonction pour envoyer un message au ruban WLED
|
||||
function sendToWLED(topicSuffix, message) {
|
||||
const wledTopic = `${wledTopicBase}/${topicSuffix}`;
|
||||
client.publish(wledTopic, message, { qos: 1 }, (err) => {
|
||||
if (err) console.error(`[ERROR] Failed to send message to WLED topic: ${wledTopic}`);
|
||||
else console.log(`[INFO] Sent to WLED (${wledTopic}): ${message}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Fonction pour appliquer un changement de lumière
|
||||
function applyLightChange(color, effect, intensity) {
|
||||
currentColor = color || currentColor;
|
||||
currentEffect = effect || currentEffect;
|
||||
|
||||
console.log(`[INFO] Applying light change: Color=${currentColor}, Effect=${currentEffect}, Intensity=${intensity}`);
|
||||
|
||||
// Envoyer la couleur au ruban WLED
|
||||
sendToWLED('col', currentColor);
|
||||
|
||||
// Appliquer l'effet si défini
|
||||
if (currentEffect !== 'none') {
|
||||
const effectId = getWLEDEffectId(currentEffect);
|
||||
sendToWLED('api', "FX=" + effectId.toString());
|
||||
}
|
||||
|
||||
// Régler l'intensité si spécifiée
|
||||
if (intensity) {
|
||||
sendToWLED('api', intensity.toString());
|
||||
}
|
||||
|
||||
// Envoi de l'état mis à jour
|
||||
sendLightStatus();
|
||||
}
|
||||
|
||||
// Fonction pour obtenir l'ID d'effet WLED correspondant à un effet donné
|
||||
function getWLEDEffectId(effect) {
|
||||
const effectsMap = {
|
||||
'none': 0,
|
||||
'blink': 1, // Effet de fondu
|
||||
'fade': 12, // Clignotement
|
||||
'rainbow': 9 // Effet arc-en-ciel
|
||||
};
|
||||
return effectsMap[effect] || 0; // Par défaut, aucun effet
|
||||
}
|
||||
|
||||
// Fonction pour envoyer l'état actuel des lumières sur le topic de réponse
|
||||
function sendLightStatus() {
|
||||
const statusMessage = JSON.stringify({
|
||||
status: "updated",
|
||||
color: currentColor,
|
||||
effect: currentEffect,
|
||||
message: `Current light state: Color=${currentColor}, Effect=${currentEffect}`,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// Envoi de l'état à tous les clients intéressés
|
||||
client.publish('vulture/light/status/response', statusMessage);
|
||||
|
||||
console.log('[INFO] Light status sent to vulture/light/status/response');
|
||||
}
|
||||
|
||||
// Gestion des messages entrants
|
||||
client.on('message', (topic, message) => {
|
||||
let payload;
|
||||
|
||||
try {
|
||||
// Analyse du message reçu
|
||||
payload = JSON.parse(message.toString());
|
||||
} catch (e) {
|
||||
console.error(`[ERROR] Invalid JSON message received on topic ${topic}: ${message.toString()}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Changement de lumière
|
||||
if (topic === 'vulture/light/change') {
|
||||
const { color, effect, intensity } = payload;
|
||||
|
||||
// Valider la couleur et l'effet
|
||||
if (!/^#[0-9A-F]{6}$/i.test(color)) {
|
||||
console.error('[ERROR] Invalid color format');
|
||||
return;
|
||||
}
|
||||
|
||||
// Appliquer le changement de lumière
|
||||
applyLightChange(color, effect, intensity);
|
||||
|
||||
} else if (topic === 'vulture/light/reset') {
|
||||
// Réinitialisation des lumières à la couleur et l'effet par défaut
|
||||
console.log('[INFO] Resetting lights to default state');
|
||||
applyLightChange('#FFFFFF', 'reset', 255);
|
||||
|
||||
} else if (topic === 'vulture/light/status/request') {
|
||||
// Répondre à la requête de statut
|
||||
console.log('[INFO] Light status request received');
|
||||
sendLightStatus();
|
||||
} else if (topic === 'vulture/light/status/response') {
|
||||
// Répondre à la requête de statut
|
||||
console.log('[INFO] Light status response received');
|
||||
} else {
|
||||
console.error(`[ERROR] Unrecognized topic: ${topic}`);
|
||||
}
|
||||
});
|
||||
|
||||
// Gestion des erreurs de connexion
|
||||
client.on('error', (err) => {
|
||||
console.error(`[ERROR] Error connecting to broker: ${err}`);
|
||||
});
|
||||
|
||||
console.log('[INFO] Light Manager with WLED support and status handling started...');
|
132
VNode/services/readme.md
Normal file
132
VNode/services/readme.md
Normal file
@ -0,0 +1,132 @@
|
||||
# Présentation des divers services liés à Vulture.
|
||||
|
||||
## 📟 Gestionnaire de Buzzer pour Vulture (*`Buzzer-Manager.js`*)
|
||||
|
||||
Ce script Node.js gère les buzzers du jeu **Vulture** en utilisant MQTT pour la communication entre les buzzers et les autres composants du système.
|
||||
|
||||
### 🚀 Fonctionnalités Principales
|
||||
* **Connexion au Broker MQTT** : Se connecte à un broker MQTT (*`mqtt://localhost`* par défaut) pour envoyer et recevoir des messages.
|
||||
* **Gestion des Buzzers** :
|
||||
* **Blocage/Déblocage** : Bloque les buzzers lorsqu'un est activé pour empêcher les autres de répondre, et les débloque sur demande.
|
||||
* **Mode Tilt** : Permet d'ignorer certains buzzers en les ajoutant au mode "tilt".
|
||||
* **Validation des Données** : Vérifie que les informations reçues des buzzers sont valides (ID du buzzer, couleur, etc.).
|
||||
* **Intégration Lumineuse** : Contrôle les effets lumineux en fonction des actions des buzzers via le gestionnaire de lumières.
|
||||
|
||||
|
||||
### 🛠️ Configuration et Utilisation
|
||||
|
||||
* **Installation des Dépendances** :
|
||||
```bash
|
||||
npm install mqtt
|
||||
```
|
||||
* **Configuration** :
|
||||
|
||||
* Modifier l'URL du broker MQTT et le client ID si nécessaire dans le script :
|
||||
|
||||
```javascript
|
||||
// Configuration du broker MQTT
|
||||
const brokerUrl = 'mqtt://votre-broker';
|
||||
const clientId = 'buzzer_manager';
|
||||
```
|
||||
|
||||
* **Lancement du Script** :
|
||||
```bash
|
||||
node buzzer-manager.js
|
||||
```
|
||||
|
||||
### 📡 Sujets MQTT Utilisés
|
||||
* **Souscriptions** :
|
||||
* `Vulture/buzzer/pressed/#` : Détecte lorsqu'un buzzer est pressé.
|
||||
* `Vulture/buzzer/unlock` : Gère les demandes de déblocage des buzzers.
|
||||
* `Vulture/buzzer/tilt` : Gère l'ajout ou le retrait des buzzers en mode tilt.
|
||||
* **Publications** :
|
||||
* `Vulture/buzzer/confirmation/{buzzer_id}` : Confirme la réception des actions des buzzers.
|
||||
* `Vulture/buzzer/status` : Informe sur l'état actuel des buzzers (bloqués, débloqués, tilt).
|
||||
* `Vulture/light/change` : Demande des changements d'effets lumineux au gestionnaire de lumières.
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ Moniteur de Statut des Buzzers pour Vulture (*`BuzzerWatcher.js`*)
|
||||
|
||||
Ce script Node.js surveille l'état des buzzers du jeu **Vulture** en les pingant régulièrement et en publiant leur statut (en ligne/hors ligne) sur un broker MQTT.
|
||||
|
||||
### 🚀 Fonctionnalités Principales
|
||||
|
||||
* **Surveillance des Buzzers** : Pinge chaque buzzer à intervalles réguliers pour vérifier s'il est en ligne.
|
||||
* **Publication MQTT** : Envoie le statut (`online` ou `offline`) de chaque buzzer sur un topic MQTT spécifié, permettant aux autres composants du système de réagir en conséquence.
|
||||
* **Configuration Flexible** : Charge dynamiquement les adresses IP des buzzers et les paramètres MQTT depuis un fichier `config.json`.
|
||||
|
||||
### 🛠️ Installation et Configuration
|
||||
#### Prérequis
|
||||
|
||||
* **Node.js** installé sur votre machine.
|
||||
* Modules NPM requis : `ping` et `mqtt`.
|
||||
|
||||
#### Installation des Dépendances
|
||||
```bash
|
||||
npm install ping mqtt
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
1. **Fichier de Configuration** : Créez un fichier `config.json` dans le répertoire `\services\config\` avec le contenu suivant :
|
||||
|
||||
```json
|
||||
{
|
||||
"hosts": {
|
||||
"buzzers": {
|
||||
"IP": {
|
||||
"buzzer1": "192.168.1.10",
|
||||
"buzzer2": "192.168.1.11"
|
||||
},
|
||||
"MQTTconfig": {
|
||||
"mqttHost": "mqtt://localhost",
|
||||
"mqttTopic": "Vulture/buzzers/status"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* **Adresses IP des Buzzers** : Remplacez par les adresses IP de vos buzzers.
|
||||
* **Configuration MQTT** :
|
||||
* `mqttHost` : L'adresse de votre broker MQTT.
|
||||
* `mqttTopic` : Le topic sur lequel publier le statut des buzzers.
|
||||
|
||||
2. **Chemin du Fichier de Configuration** : Assurez-vous que le chemin vers `config.json` dans le script est correct :
|
||||
|
||||
```javascript
|
||||
const config = JSON.parse(fs.readFileSync('\\services\\config\\config.json', 'utf8'));
|
||||
```
|
||||
|
||||
### ▶️ Utilisation
|
||||
|
||||
* **Lancement du Script** :
|
||||
```bash
|
||||
node BuzzerWatcher.js
|
||||
```
|
||||
|
||||
Le script va :
|
||||
|
||||
* Se connecter au broker MQTT spécifié.
|
||||
* Pinger chaque buzzer toutes les 3 secondes.
|
||||
* Publier le statut de chaque buzzer sur le topic MQTT configuré.
|
||||
|
||||
### 📡 Topic MQTT Utilisés
|
||||
|
||||
* **Publication** :
|
||||
* **Topic** : `Vulture/buzzers`
|
||||
* **Payload Exemple** :
|
||||
|
||||
```json
|
||||
{
|
||||
"buzzer": "buzzer1",
|
||||
"ip": "192.168.1.10",
|
||||
"status": "online"
|
||||
}
|
||||
```
|
||||
|
||||
### 💡 Notes
|
||||
* **Personnalisation de l'Intervalle** : Vous pouvez modifier l'intervalle de ping en changeant la valeur dans `setInterval(pingAndPublish, 3000);` (valeur en millisecondes).
|
||||
* **Extensibilité** : Pour ajouter plus de buzzers, il suffit d'ajouter leurs adresses IP dans le fichier `config.json`.
|
||||
|
||||
---
|
Reference in New Issue
Block a user