Ejemplo Completo de Integración para Sensores
A continuación se presentan ejemplos completos de código que ilustran el flujo inicial de obtención del token (aprovisionamiento) y la conexión persistente por WebSockets.
💻 Ejemplo 1: Cliente Sensor en Node.js / JavaScript
import { io } from 'socket.io-client';
import fs from 'fs';
// Configuración del Dispositivo
const CONFIG = {
SERVER_URL: 'https://api.improvemeter.com',
USER_EMAIL: 'sensor.integracion@empresa.com',
USER_PASSWORD: 'TuPasswordSegura',
MACHINE_ID: 'TU_MACHINE_ID',
SENSOR_CODE: 'CODIGO_SENSOR_01',
TOKEN_FILE: './socket_token.json'
};
// ------------------------------------------------------------------
// Obtiene o reutiliza el token del socket (no caduca)
// ------------------------------------------------------------------
async function getOrFetchSocketToken() {
// Si ya existe el token guardado localmente, reutilizarlo directamente
if (fs.existsSync(CONFIG.TOKEN_FILE)) {
const saved = JSON.parse(fs.readFileSync(CONFIG.TOKEN_FILE, 'utf-8'));
if (saved.socketAuthToken) {
console.log('📦 Usando token de socket almacenado previamente.');
return saved.socketAuthToken;
}
}
console.log('🔑 Paso 1: Autenticando usuario...');
const loginRes = await fetch(`${CONFIG.SERVER_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: CONFIG.USER_EMAIL, password: CONFIG.USER_PASSWORD })
});
const loginData = await loginRes.json();
if (!loginData.success || !loginData.data?.token) {
throw new Error('Fallo en autenticación inicial del usuario');
}
const userToken = loginData.data.token;
const companyId = loginData.data.companies[0]?.id; // Primera empresa asignada
console.log('🔑 Paso 2: Generando token permanente para el socket...');
const socketRes = await fetch(`${CONFIG.SERVER_URL}/auth/login-for-socket`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${userToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ companyId })
});
const socketData = await socketRes.json();
if (!socketData.success || !socketData.data?.authToken) {
throw new Error('Fallo al obtener token de socket');
}
const socketAuthToken = socketData.data.authToken;
// Guardar token en disco (memoria no volátil del dispositivo)
fs.writeFileSync(CONFIG.TOKEN_FILE, JSON.stringify({ socketAuthToken }), 'utf-8');
console.log('💾 Token permanente de socket guardado localmente.');
return socketAuthToken;
}
// ------------------------------------------------------------------
// Bucle Principal de Conexión y Envío de Señales
// ------------------------------------------------------------------
async function startSensorClient() {
try {
const socketAuthToken = await getOrFetchSocketToken();
console.log('🌐 Conectando al WebSocket (/oee)...');
const socket = io(`${CONFIG.SERVER_URL}/oee`, {
auth: { token: socketAuthToken },
transports: ['websocket', 'polling']
});
socket.on('connect', () => {
console.log('✅ Conectado al servidor WebSocket:', socket.id);
// Suscribir el dispositivo como sensor
socket.emit('subscribeLiveOee', {
machineIds: [CONFIG.MACHINE_ID],
isSensor: true
});
});
socket.on('live-oee-subscribed', (data) => {
console.log('🎉 Dispositivo registrado correctamente:', data.message);
});
socket.on('sensorSignalResponse', (response) => {
if (response.status === 'success') {
console.log('✅ Señal procesada correctamente');
} else {
console.error('❌ Error enviando señal:', response.message);
}
});
socket.on('production-status', (payload) => {
const prod = payload.data?.production;
const product = payload.data?.product;
console.log(`📦 Producción Activa: ${product?.name || 'Sin Producto'} | Estado: ${prod?.status || 'N/A'}`);
});
// Simulación: Enviar pulso de producción cada 10s
setInterval(() => {
console.log('📤 Enviando pulso de producción...');
socket.emit('sendSensorSignal', {
sensorId: CONFIG.SENSOR_CODE,
signalValue: 1,
signalType: 'data'
});
}, 10000);
} catch (error) {
console.error('❌ Error en el cliente sensor:', error.message);
}
}
startSensorClient();