Skip to content

SoftwareDigitalTwin/tcp-connect

Repository files navigation

Servidor TCP con Autenticación y Forward HTTP

Servidor TCP en Node.js que recibe tramas de datos de twins (gemelos digitales), se autentica automáticamente con una API, y envía los datos a un endpoint HTTP POST.

Características

  • Servidor TCP que escucha conexiones entrantes
  • Autenticación automática con la API (login y gestión de tokens)
  • Cache inteligente de tokens con renovación automática
  • Procesamiento y validación de tramas JSON con datos de twins
  • Envío automático de datos a endpoint /v2/lectures/twin
  • Respuestas estandarizadas: status: 0 para éxito, status: 1 para error
  • Manejo robusto de errores con retry automático en caso de token expirado
  • Logs detallados para debugging
  • Cliente de prueba incluido

Estructura del Proyecto

servidor-tcp/
├── index.js           # Servidor TCP principal
├── httpClient.js      # Cliente HTTP con autenticación
├── test-client.js     # Cliente de prueba
├── package.json       # Dependencias
├── .env.example       # Ejemplo de configuración
└── README.md          # Este archivo

Requisitos

  • Node.js v14 o superior
  • npm o yarn

Instalación

  1. Instala las dependencias:
npm install
  1. Copia el archivo de configuración:
cp .env.example .env
  1. Edita el archivo .env con tu configuración:
# Configuración del Servidor TCP
TCP_PORT=8080
TCP_HOST=0.0.0.0

# Configuración de la API
API_BASE_URL=https://tu-api.com
HTTP_TIMEOUT=5000

# Credenciales de autenticación
LOGIN_EMAIL=tu@email.com
LOGIN_PASSWORD=tu_password

Uso

Iniciar el servidor

npm start

El servidor comenzará a escuchar en el puerto configurado (por defecto 8080).

Modo desarrollo (con auto-restart)

npm run dev

Formato de Datos del Twin

El servidor espera recibir un JSON con la siguiente estructura exacta (como viene del hardware):

{
  "idTwin": 205,
  "sensors": [
    {
      "idSensor": 3,
      "idLectureType": 1,
      "value": "21.22"
    },
    {
      "idSensor": 4,
      "idLectureType": 2,
      "value": "76.02"
    }
  ],
  "unixTime": 1761350213,
  "idWarehouse": 24
}

Campos Requeridos

  • idTwin (number): ID del twin
  • sensors (array): Array de sensores, cada uno con:
    • idSensor (number): ID del sensor
    • idLectureType (number): Tipo de lectura
    • value (string): Valor de la lectura
  • unixTime (number): Timestamp Unix en segundos
  • idWarehouse (number): ID del almacén

Flujo de Autenticación

  1. Al primer request, el servidor hace login automáticamente a /settings/loginUser
  2. Obtiene el tokenAuth de la respuesta
  3. Guarda el token en cache por 23 horas
  4. Usa el token para todas las peticiones a /v2/lectures/twin
  5. Si el token expira o es inválido (HTTP 401), automáticamente:
    • Hace login nuevamente
    • Obtiene un nuevo token
    • Reintenta la petición original

Pruebas Locales

Opción 1: Usando el cliente de prueba incluido

# En una terminal, inicia el servidor
npm start

# En otra terminal, ejecuta el cliente de prueba
npm run test-client

El cliente de prueba enviará datos de ejemplo de un twin y mostrará la respuesta.

Opción 2: Enviar datos personalizados

npm run test-client '{"idTwin":205,"sensors":[{"idSensor":3,"idLectureType":1,"value":"21.22"}],"unixTime":1761350213,"idWarehouse":24}'

Opción 3: Usando telnet

telnet localhost 8080

Luego escribe tu JSON:

{"idTwin":205,"sensors":[{"idSensor":3,"idLectureType":1,"value":"21.22"}],"unixTime":1761350213,"idWarehouse":24}

Opción 4: Usando netcat (nc)

echo '{"idTwin":205,"sensors":[{"idSensor":3,"idLectureType":1,"value":"21.22"}],"unixTime":1761350213,"idWarehouse":24}' | nc localhost 8080

Opción 5: Script Node.js personalizado

const net = require('net');

const client = net.createConnection({ port: 8080, host: 'localhost' }, () => {
  const twinData = {
    idTwin: 205,
    sensors: [
      {
        idSensor: 3,
        idLectureType: 1,
        value: "21.22"
      },
      {
        idSensor: 4,
        idLectureType: 2,
        value: "76.02"
      }
    ],
    unixTime: Math.floor(Date.now() / 1000), // Timestamp Unix en segundos
    idWarehouse: 24
  };

  client.write(JSON.stringify(twinData));
});

client.on('data', (data) => {
  console.log('Respuesta:', data.toString());
  client.end();
});

Formato de Respuestas

El servidor responde con un JSON:

Éxito (status: 0)

{
  "status": 0,
  "message": "OK",
  "detail": "Datos procesados y enviados correctamente",
  "timestamp": "2025-01-27T10:30:00.000Z"
}

Error (status: 1)

{
  "status": 1,
  "message": "ERROR",
  "detail": "Campos requeridos faltantes: unixTime",
  "timestamp": "2025-01-27T10:30:00.000Z"
}

Validaciones

El servidor valida estrictamente:

  • JSON válido
  • Presencia de campos requeridos: idTwin, sensors, unixTime, idWarehouse
  • sensors debe ser un array
  • Cada sensor debe tener: idSensor, idLectureType, value
  • Tipos de datos correctos:
    • idTwin: number
    • unixTime: number (timestamp Unix en segundos)
    • idWarehouse: number
    • idSensor: number
    • idLectureType: number
    • value: string

Si alguna validación falla, responde con status: 1 y un mensaje descriptivo del error.

Flujo de Operación Completo

  1. Cliente TCP se conecta al servidor
  2. Cliente envía trama JSON con datos del twin
  3. Servidor valida el formato y los datos
  4. Servidor verifica si tiene un token válido:
    • Si no tiene o está expirado: hace login
    • Si tiene: lo usa directamente
  5. Servidor envía datos a POST /v2/lectures/twin con el token
  6. Si el endpoint responde con 401:
    • Renueva el token
    • Reintenta la petición
  7. Servidor responde al cliente TCP:
    • status: 0 si todo fue exitoso
    • status: 1 si hubo algún error

Logs del Servidor

El servidor genera logs detallados:

  • [INFO] - Información general (conexiones, tramas recibidas)
  • [SUCCESS] - Operaciones exitosas
  • [ERROR] - Errores
  • [AUTH] - Operaciones de autenticación
  • [HTTP] - Peticiones HTTP

Ejemplo de logs:

==================================================
[INFO] Servidor TCP iniciado
[INFO] Escuchando en 0.0.0.0:8080
==================================================
[INFO] Cliente conectado: ::ffff:127.0.0.1:52341
[INFO] Datos recibidos de ::ffff:127.0.0.1:52341
[INFO] Trama recibida: {"idTwin":123,"sensors":[...],"unixTime":1738034192,"idWarehouse":24}
[INFO] Trama validada correctamente
[INFO] Twin ID: 123
[INFO] Warehouse ID: 24
[INFO] Sensores: 3
[INFO] Enviando datos del twin al endpoint HTTP...
[AUTH] Token no disponible o expirado, obteniendo nuevo token...
[AUTH] Iniciando autenticación...
[AUTH] Autenticación exitosa
[AUTH] Usuario: Hardware
[AUTH] ID Usuario: 4
[AUTH] Token válido hasta: 2025-01-28T09:30:00.000Z
[HTTP] Enviando a: https://api.ejemplo.com/v2/lectures/twin
[HTTP] Respuesta exitosa: 200
[SUCCESS] Datos del twin enviados correctamente
[INFO] Cliente desconectado: ::ffff:127.0.0.1:52341

Despliegue en Servidor Linux

Opción 1: Usando PM2 (Recomendado)

# Instala PM2 globalmente
npm install -g pm2

# Inicia el servidor
pm2 start index.js --name servidor-tcp

# Configura para que inicie automáticamente
pm2 startup
pm2 save

# Ver logs en tiempo real
pm2 logs servidor-tcp

# Ver estado
pm2 status

# Reiniciar
pm2 restart servidor-tcp

# Detener
pm2 stop servidor-tcp

Opción 2: Usando systemd

Crea un archivo /etc/systemd/system/servidor-tcp.service:

[Unit]
Description=Servidor TCP con Forward HTTP
After=network.target

[Service]
Type=simple
User=tu-usuario
WorkingDirectory=/ruta/a/servidor-tcp
ExecStart=/usr/bin/node index.js
Restart=always
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

Luego:

sudo systemctl daemon-reload
sudo systemctl enable servidor-tcp
sudo systemctl start servidor-tcp
sudo systemctl status servidor-tcp

# Ver logs
sudo journalctl -u servidor-tcp -f

Opción 3: Usando Docker

Crea un Dockerfile:

FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 8080
CMD ["node", "index.js"]

Construye y ejecuta:

docker build -t servidor-tcp .
docker run -d -p 8080:8080 --env-file .env --name servidor-tcp --restart unless-stopped servidor-tcp

# Ver logs
docker logs -f servidor-tcp

Configuración del Firewall

Si usas firewall en Linux, abre el puerto:

# UFW
sudo ufw allow 8080/tcp

# iptables
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
sudo iptables-save > /etc/iptables/rules.v4

Troubleshooting

El servidor no inicia

  • Verifica que el puerto no esté en uso: lsof -i :8080
  • Verifica los permisos del archivo
  • Revisa los logs del servidor

No puedo conectarme desde otra máquina

  • Verifica que TCP_HOST=0.0.0.0 en .env
  • Revisa la configuración del firewall
  • Verifica que el servidor esté escuchando: netstat -tulpn | grep 8080

Error: "Campos requeridos faltantes"

  • Verifica que tu trama JSON contenga todos los campos requeridos: idTwin, sensors, unixTime, idWarehouse
  • Verifica que cada sensor tenga: idSensor, idLectureType, value

Error: "Login falló" o "Credenciales inválidas"

  • Verifica que LOGIN_EMAIL y LOGIN_PASSWORD sean correctos en .env
  • Verifica que la URL base de la API sea correcta
  • Prueba las credenciales manualmente con curl:
curl -X POST https://tu-api.com/settings/loginUser \
  -H "Content-Type: application/json" \
  -d '{"email": "tu@email.com", "password": "tu_password"}'

Error HTTP 401 persistente

  • El servidor intenta renovar automáticamente el token
  • Si persiste, verifica que las credenciales sigan siendo válidas
  • Revisa que el endpoint de login no haya cambiado

No se recibe respuesta del endpoint HTTP

  • Verifica que API_BASE_URL sea correcto en .env
  • Verifica la conectividad con la API
  • Aumenta el timeout en .env: HTTP_TIMEOUT=10000

Seguridad

  • NUNCA subas el archivo .env al repositorio
  • Usa contraseñas seguras y cámbialas regularmente
  • El token se renueva automáticamente cada 23 horas
  • En producción, considera usar variables de entorno del sistema en lugar de .env
  • Implementa rate limiting si es necesario para prevenir abuso
  • Valida y sanitiza todas las entradas

Licencia

ISC

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published