/** * Archivo Core de EMA Libre Cliente (Carpincho). * * Archivo que se ejecuta en segundo plano y es el encargado, de obtener, registrar, * calcular y publicar los registros, incluyendo los modulos necesarios para realizar * estas tareas. * * LICENSE: This file is part of EMA Libre. * EMA Libre is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * EMA Libre is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with EMA Libre. If not, see . * * @copyright Copyright (c) 2019 GUGLER (https://www.gugler.com.ar) * @license https://www.gnu.org/licenses/gpl-3.0.html GPL License * @version 3.0 * @link https://www.gugler.com.ar * @since File available since Release 3.0 */ /************************************** *** DECLARACIONES INICIALES ****** **************************************/ var configGeneralEMA = require('./../conf/ConfiguracionGeneral.js'); // Configuracion General const configGlobalEMA = require('./../conf/ConfiguracionGlobal.js'); // Configuracion Global const Correo = require('./mail.js'); // Envio de correo. var recolector = require('./recolector.js'); // Recolector de informacion USB. const Redes = require('./redes_meteorologicas.js'); // Redes Meteorologicas disponibles. const Validador = require('./validaciones.js'); // Validador de registros. const fs = require('fs'); // Libreria fs para el manejo de archivos. const util = require('util'); // Utilidades. var Guardar = []; // Tanque diario de registros leidos (para acumulados). var versionEMA = configGlobalEMA.ConfGlobal.Nombre + ' v' + configGlobalEMA.ConfGlobal.Version; const http = require('http'); const https = require('https'); var DatosRecolectadosAnterior = []; // Datos recolectados de la estacion meteorologica. APP = module.exports = { Configuracion: { Modo: configGeneralEMA.ConfGeneral.Modo, // Modo de funcionamiento de EMA. Puerto: configGeneralEMA.ConfGeneral.Puerto, // Puerto de comunicacion. IP: configGeneralEMA.ConfGeneral.IP, // IP de comunicacion. Patch: configGeneralEMA.ConfGeneral.Ruta, // Ruta de comunicacion. debug: configGeneralEMA.ConfGeneral.debug, // Se obtiene el nivel de debug del archivo de Conf General. utc: configGeneralEMA.ConfGeneral.UTC, // Se obtiene la fecha en formato UTC del archivo de Conf General. Errores: '', // Errores detectado en el funcionamiento de EMA. TiempoContinuo: 0, // Tiempo en segundos(s) de recoleccion. Cantidad_No_Lectura: 99999, // Cantidad de lecturas falsas admitidas. Repeticiones: 0, // Contador de repeticiones. No parametrizable, siempre 0. RepeticionesConError: 0, // Contador de repeticiones. No parametrizable, siempre 0. TiempoMaximo: 0, // Contador de repeticiones. No parametrizable, siempre 0. TiempoFueraDeLinea: 0, // Contador de tiempo fuera de linea.. No parametrizable, siempre 0. TiempoMaximoFueraDeLinea: 300, // Tiempo en segundo fuera de linea para el envio de mail (default:3600 = 2hs). IdsSetTimeouts: [], // Id del TimeOut del blucle continuo. EstadoSensores: [], // Solo estado Sensores Estado_Val_Ant: 0, // Solo estado Sensores del registro anterior para almacenar errores, ya que no se almacenan. FechaLanzadoTimeout: 0, // fecha real de lanzamiento del TimeOut para el blucle continuo. Run: 0, // Variable que indica que esta encendida EMA. RunTime: 0, // Variable que indica que esta ejecutandose el Recolector. BanderaPendientes: 0, // Bandera de Tanque enviando CantidadPendientes: 0, // Tanque Pendientes TanquePendiente: [], // Tanque Pendientes UltimoRegistro: '', // Ultimo Registro Recolectado con datos de los sensores. UltimoPublicado: [], // Ultimo Registro de las Redes Publicadas. tempAlmacenadoPendientes: [] // Ultimo Registro de las Redes Publicadas. }, RegistrarLog: function (reg, depurar) { let nivel = reg.split('|')[0]; // Si el nivel de debug es mayor o igual al configurado, se registra. if(APP.Configuracion.debug >= nivel) { if (typeof depurar !== 'undefined') { depurar = false; } // se convierte la fecha a la UTC parametrizada var d = new Date(); var utc = d.getTime() + (d.getTimezoneOffset() * 60000); var fechaHora = new Date(utc + (3600000 * (APP.Configuracion.utc))); var horas = fechaHora.getHours(); var minutos = fechaHora.getMinutes(); var segundos = fechaHora.getSeconds(); var mes = fechaHora.getMonth() + 1; var dia = fechaHora.getDate(); if (dia <= 9) { dia = '0' + dia; } if (mes <= 9) { mes = '0' + mes; } if (horas < 10) { horas = '0' + horas; } if (minutos < 10) { minutos = '0' + minutos; } if (segundos < 10) { segundos = '0' + segundos; } var fecha = dia + '/' + mes + '/' + fechaHora.getFullYear() + ' ' + horas + ':' + minutos + ':' + segundos; var registrologs = fecha + ' - ' + util.format(reg) + '\n'; // SE CONTROLA EL TAMAÑO DEL LOG SEGUN PARAMETRIA var estadoarchivoD = fs.statSync("logs/debug.log"); var TamanioenMegaD = (estadoarchivoD.size)/ 1000000.0; if (depurar || (TamanioenMegaD >= configGeneralEMA.ConfGeneral.debugTamanio)) { // SE DEPURA EL ARCHIVO DE REGISTROS DE LOGS fs.writeFile('./logs/debug.log', '', { encoding: 'utf8', autoClose: true }, function (err) { if (err) { APP.RegistrarLog('0|ERROR|🔴 Depurando archivo registro de logs :' + err); } APP.RegistrarLog('0|PURGADO|🔴 Depurando automaticamente archivo registro de logs.'); }); } else { // GUARDA LOS REGISTROS DE LOGS fs.appendFile('./logs/debug.log', registrologs, { encoding: 'utf8', autoClose: true }, function (err) { if (err) { APP.RegistrarLog('0|ERROR|🔴 Guardando registro de logs en archivo :' + err); } }); } registrologs=null;fecha=null;dia=null;mes=null;segundos=null;minutos=null;horas=null;fechaHora=null;utc=null;d=null; } }, RepeticionesConError: function () { return APP.Configuracion.RepeticionesConError; }, Estado: function () { if (APP.Configuracion.Run === 0 && APP.Configuracion.RunTime === 0) { return [false, APP.Configuracion.Errores]; } if (APP.Configuracion.Run === 1 && APP.Configuracion.RunTime === 0) { return [false, APP.Configuracion.Errores]; } if (APP.Configuracion.Run === 1 && APP.Configuracion.RunTime === 1) { return [true, '']; } }, EstadoUSB: function (callback) { try{ callback(recolector.status()); }catch(e){APP.RegistrarLog('0|CORE|🔴 Error: '+e);return false;} }, Salir: function () { APP.RegistrarLog('0|CORE|🔚 SALIR: Se cerro el core de EMA LIBRE. Hasta luego!!!.'); if (configGeneralEMA.ConfEmail.ActivarCorreos === true) Correo.EnviarEmail(configGeneralEMA,'EMA - OFFLINE', 'Estimado,

Le informamos que la estación ' + configGeneralEMA.ConfGeneral.NombreEstacion + ' se detuvo y se cerro el software EMA LIBRE.

Saludos Cordiales.'); APP.Configuracion.Errores = 'Se Salio del Recolector'; }, Detener: function () { APP.RegistrarLog('0|CORE|🔴 Se detiene el recolector de EMA LIBRE.'); APP.Configuracion.RunTime = 0; APP.Configuracion.Errores = 'Se detuvo manualmente el Recolector'; APP.Configuracion.RepeticionesConError = 0; APP.LimpiarM(); if(APP.Configuracion.Modo === 'Recolector_IP') { let PORT = APP.Configuracion.Puerto; let HOST = APP.Configuracion.IP; http.get(`http://${HOST}:${PORT}/detener_servidor`, (res) => { res.on('data', (chunk) => { }); res.on('end', () => { APP.RegistrarLog('0|CORE|🔴 Petición de apagado enviada correctamente.'); }); }).on('error', (err) => { APP.RegistrarLog('0|CORE|❌ Error al enviar petición'); }); } }, Reconfigurar: function () { APP.RegistrarLog('0|CORE|⚙️ RECONFIGURANDO: Se reconfigura el recolectorde EMA LIBRE.'); if (configGeneralEMA.ConfEmail.ActivarCorreos === true) Correo.EnviarEmail(configGeneralEMA,'EMA - CONFIG', 'Estimado,

Le informamos que se modificó la configuración de la estación ' + configGeneralEMA.ConfGeneral.NombreEstacion + '.

Saludos Cordiales.'); APP.Configuracion.TiempoContinuo = configGeneralEMA.ConfGeneral.Tiempo_de_Recoleccion; APP.Configuracion.debug = configGeneralEMA.ConfGeneral.debug; recolector.conf.debug = configGeneralEMA.ConfGeneral.debug; APP.Configuracion.Puerto = configGeneralEMA.ConfGeneral.Puerto; APP.Configuracion.IP = configGeneralEMA.ConfGeneral.IP; APP.Configuracion.Patch = configGeneralEMA.ConfGeneral.Ruta; }, Iniciar: function () { if (APP.Configuracion.Run === 1 && APP.Configuracion.RunTime === 0) { APP.RegistrarLog('0|CORE|🟢 INICIAR: Se inicio el recolector.'); APP.RegistrarLog('0|CORE|🛠️ DEBUG: ' + APP.Configuracion.debug); APP.Configuracion.RunTime = 1; if(APP.Configuracion.Modo != 'Recolector_IP') APP.Continuo(); } else { APP.RegistrarLog('0|CORE|🔄 Hay un proceso corriendo, se elimina.'); APP.LimpiarM(); if(APP.Configuracion.Modo != 'Recolector_IP') APP.Continuo(); } }, LimpiarM: function () { var tamanio = APP.Configuracion.IdsSetTimeouts.length; // Se limpias los tiempos identificados for (tamanio;tamanio>-1;tamanio--){ clearTimeout(APP.Configuracion.IdsSetTimeouts[tamanio]); APP.Configuracion.IdsSetTimeouts.splice(tamanio, 1); } // Se limpian las variables tamanio = null; return true; }, Guardar_Diario: function (Datos) { // GUARDA LOS REGISTROS DIARIOS fs.writeFile('./logs/registro_diario.log', JSON.stringify(Datos, null, 4), { encoding: 'utf8', autoClose: true }, (err) => { if (err) { APP.RegistrarLog('1|ERROR|🔴 Guardando registro diario en archivo :' + err); } }); }, TiempoActualRecolector: function (ahora = false) { if(ahora) {return [100,100]; } // APP.RegistrarLog(APP.Configuracion.IdsSetTimeouts); var fechaTiempo = APP.Configuracion.FechaLanzadoTimeout; var tiempoC = APP.Configuracion.TiempoContinuo; if (fechaTiempo > 0) { var Resto = 0; Resto = (tiempoC - ((Date.now() - fechaTiempo) / 1000)); if(Resto > -1 && Resto < 150){ var porcentaje = (100 - ((Resto * 100) / tiempoC)).toFixed(0); var segundos = (tiempoC - Resto).toFixed(1); return [porcentaje,segundos]; }else{return [false,false];} } else { return [false,false]; } }, UltimoRegistro: function () { if (typeof APP.Configuracion.UltimoRegistro !== 'undefined' && APP.Configuracion.UltimoRegistro !== '') { return APP.Configuracion.UltimoRegistro; } else { return false; } }, EstadoSensores: function () { if (typeof APP.Configuracion.EstadoSensores !== 'undefined' && APP.Configuracion.EstadoSensores !== '') { return APP.Configuracion.EstadoSensores; } else { return false; } }, UltimoPublicado: function () { if (typeof APP.Configuracion.UltimoPublicado !== 'undefined' && APP.Configuracion.UltimoPublicado !== '') { return APP.Configuracion.UltimoPublicado; } else { return false; } }, HayPendientes: function () { if (APP.Configuracion.CantidadPendientes !== 0) { return APP.Configuracion.CantidadPendientes; } else { return false; } }, // Metodo para conectar/verificar la conexion USB de la EMA USB. Conectar: function () { try { if(APP.Configuracion.Modo === 'Recolector_IP'){ APP.RegistrarLog('0|CORE|🔧 Estableciendo Time Zone UTC ' + configGeneralEMA.ConfGeneral.UTC); APP.RegistrarLog('0|CORE|🔧 Verificando Estado de la EMA...'); APP.RegistrarLog('0|CORE|🟢 Iniciando el Modo Recolector por IP/WIFI.'); APP.Configuracion.TiempoContinuo = configGeneralEMA.ConfGeneral.Tiempo_de_Recoleccion; APP.Configuracion.debug = configGeneralEMA.ConfGeneral.debug; // se levanta el puerto para escuchar las peticiones al puerto indicado. const PORT = APP.Configuracion.Puerto; const HOST = APP.Configuracion.IP; const RUTA = APP.Configuracion.Patch; // e.g., "/datos" const server = http.createServer((req, res) => { const base = `http://${HOST}:${PORT}`; let urlRaw = req.url; // Si la ruta empieza con "/xxxx" y no tiene "?" pero sí "&", agregamos "?" if (urlRaw.startsWith(RUTA) && !urlRaw.includes('?') && urlRaw.includes('&')) { urlRaw = urlRaw.replace(RUTA, RUTA + '?'); } const myURL = new URL(urlRaw, base); const pathname = myURL.pathname.toLowerCase(); const method = req.method.toUpperCase(); const ip = req.socket.remoteAddress.replace('::ffff:', ''); APP.RegistrarLog('6|REGISTRO|📥 Recepcion IP: ' + ip + ' por ' + method + ' ruta ' + pathname); //Para detener el servidor if (pathname === '/detener_servidor') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Servidor detenido'); APP.RegistrarLog('0|CORE| 🔴 Servidor detenido por botón'); server.close(() => { }); return false; } //Para recibir la información de la estacion WIFI/IP if (pathname === RUTA) { // Comunes para ambos metodos // se convierte la fecha a la UTC parametrizada var d = new Date(); var utc = d.getTime() + (d.getTimezoneOffset() * 60000); var db = new Date(utc + (3600000 * (APP.Configuracion.utc))); // UTC - Configurado var dbutc = new Date(utc); // UTC Pura // Se da formato a la fecha y hora var minutos = db.getMinutes(); if (minutos <= 9) { minutos = '0' + minutos; } var hora = db.getHours(); if (hora <= 9) { hora = '0' + hora; } var mes = db.getMonth() + 1; if (mes <= 9) { mes = '0' + mes; } var dia = db.getDate(); if (dia <= 9) { dia = '0' + dia; } var segundo = db.getSeconds(); if (segundo <= 9) { segundo = '0' + segundo; } var fecha = dia + '/' + mes + '/' + db.getFullYear() + ' ' + hora + ':' + minutos + ':' + segundo; var fechaISO = db.getFullYear() + '-' + mes + '-' + dia + 'T' + hora + ':' + minutos + ':' + segundo; dia = null; mes = null; hora = null; minutos = null; segundo = null; db = null; utc = null; d = null; // UTC PURA var minutost = dbutc.getMinutes(); if (minutost <= 9) { minutost = '0' + minutost; } var horat = dbutc.getHours(); if (horat <= 9) { horat = '0' + horat; } var mest = dbutc.getMonth() + 1; if (mest <= 9) { mest = '0' + mest; } var diat = dbutc.getDate(); if (diat <= 9) { diat = '0' + diat; } var segundot = dbutc.getSeconds(); if (segundot <= 9) { segundot = '0' + segundot; } var fechaUTC = dbutc.getFullYear() + '-' + mest + '-' + diat + '+' + horat + ':' + minutost + ':' + segundot; diat = null; mest = null; horat = null; minutost = null; segundot = null; dbutc = null; const Etiquetas = [ 'Fecha local', 'Fecha ISO', 'Temperatura exterior (°C)', 'Temperatura interior (°C)', 'Humedad exterior (%)', 'Humedad interior (%)', 'Luz (kLux)', 'Radiación UV', 'Viento (km/h)', 'Ráfaga (km/h)', 'Dirección viento (°)', 'Dirección viento (nombre)', 'Presión absoluta (hpa)', 'Presión relativa (hpa)', 'Lluvia total (mm)', 'Punto de rocío (°C)', 'Fecha UTC', 'Batería Baja (0-No/1-Si)' ]; if (method === 'GET') { let Vector = Object.fromEntries(myURL.searchParams.entries()); //APP.RegistrarLog(`5|VECTOR|${JSON.stringify(Vector)}`); let TemperaturaExternaC = ((parseFloat(Vector['tempf']) - 32) * 5 / 9).toFixed(2); let TemperaturaInternaC = ((parseFloat(Vector['indoortempf']) - 32) * 5 / 9).toFixed(2); let vientoEnKm = (parseFloat(Vector['windspeedmph']) * 1.60934).toFixed(2); let rafagaEnKm = (parseFloat(Vector['windgustmph']) * 1.60934).toFixed(2); let luxerIntencidad = Vector['solarradiation'] * 683; // luxerIntencidad en Luxer let PresionR = (parseFloat(Vector['baromin']) * 33.8639).toFixed(2); let PresionA = (parseFloat(Vector['absbaromin']) * 33.8639).toFixed(2); // calculo del punto de rocio let punto_de_rocio = ((parseFloat(Vector['dewptf']) - 32) * 5 / 9).toFixed(2); punto_de_rocio = (Math.round(punto_de_rocio * 100)) / 100; let x = Vector['winddir']; // direccion del viento por nombre switch (true) { case x === 0: VientoDireccion = 'Norte'; break; case x > 0 && x < 90: VientoDireccion = 'Nordeste'; break; case x === 90: VientoDireccion = 'Este'; break; case x > 90 && x < 180: VientoDireccion = 'Sudeste'; break; case x === 180: VientoDireccion = 'Sur'; break; case x > 180 && x < 270: VientoDireccion = 'Sudoeste'; break; case x === 270: VientoDireccion = 'Oeste'; break; case x > 270 && x < 360: VientoDireccion = 'Noroeste'; break; default: VientoDireccion = 'N/A'; } x = null; let lluviaTotalmm = (parseFloat(Vector['totalrainin']) * 25.4).toFixed(2);; // conversion a mm let DatosRecolectados = [ fecha, // *0: Fecha local fechaISO, // *1: Fecha ISO parseFloat(TemperaturaExternaC), // *2: Temperatura exterior parseFloat(TemperaturaInternaC), // *3: Temperatura interior parseFloat(Vector['humidity']), // *4: Humedad exterior parseFloat(Vector['indoorhumidity']), // *5: Humedad interior luxerIntencidad, // *6: Luz Intencidad en Klux parseFloat(Vector['UV']), // *7: Radiación UV parseFloat(vientoEnKm), // *8: Velocidad viento parseFloat(rafagaEnKm), // *9: Ráfaga parseFloat(Vector['winddir']), // *10: Dirección viento (grados) VientoDireccion, // *11: Dirección viento (nombre) parseFloat(PresionA), // *12: Presión absoluta hpa parseFloat(PresionR), // *13: Presión relativa hpa parseFloat(lluviaTotalmm), // *14: Lluvia acumulada mm punto_de_rocio, // *15: Punto de rocío fechaUTC, // *16: UTC desde 'dateutc' Vector['lowbatt'] // *17: Estado batería ]; // Se verifican cambios if (DatosRecolectadosAnterior.length < 1) { DatosRecolectadosAnterior = DatosRecolectados;} let cambios = {}; let bandera_cambios = false; for (let i = 0; i < DatosRecolectados.length; i++) { if ( i === 0 || i === 1 || i === 16) continue; // ignorar índices 0, 1 y 16 que son fechas if (DatosRecolectados[i] !== DatosRecolectadosAnterior[i]) { bandera_cambios = true; cambios[Etiquetas[i]] = { valorAnterior: DatosRecolectadosAnterior[i], valorNuevo: DatosRecolectados[i] }; } } //cambios = JSON.stringify(cambios, null, 2); DatosRecolectados.forEach((dato, i) => { APP.RegistrarLog(`5|REGISTRO|🗃️ ${i} - ${Etiquetas[i]}: ${dato}`); }); // ACA SE ENVIA AL VALIDADOR Y A LAS REDES CONFIGURADAS var Datos = []; Datos = ['validar', DatosRecolectados,cambios,bandera_cambios]; Validador.Registros(Datos, function (errorvalidador, estadovalidador) { if (estadovalidador === true) { APP.Configuracion.Repeticiones += 1; APP.Configuracion.RepeticionesConError = 0; APP.Configuracion.TiempoMaximo = 0; APP.Configuracion.TiempoFueraDeLinea = 0; APP.Configuracion.FechaLanzadoTimeout = Date.now(); APP.Registro_Diario(Datos[1],cambios,bandera_cambios); APP.Publicar_en_Redes(); Datos = null; } else { APP.Configuracion.Repeticiones = 0; APP.Configuracion.Estado_Val_Ant = errorvalidador[0]; APP.RegistrarLog('0|VALIDADOR|⚠️ Datos recolectados incorrectos: ' + errorvalidador[1]); Datos = null; } }); APP.Configuracion.EstadoSensores = DatosRecolectados[17]; DatosRecolectadosAnterior = DatosRecolectados; // Guardar los datos recolectados para la proxima vez. TiempoActualRecolector(true); // para reiniciar el tiempo y sincronizar. res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Datos GET recibidos'); //TERMINA EL METODO GET } else if (method === 'POST' || method === 'PATCH') { // COMIENZA EL MOTODO POST let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { // APP.RegistrarLog('5|REGISTRO|Datos formulario:'+body); const params = new URLSearchParams(body); const data = Object.fromEntries(params.entries()); // Se convierten las unidades necesarias let TemperaturaExternaC = ((parseFloat(data['tempf']) - 32) * 5 / 9).toFixed(2); let TemperaturaInternaC = ((parseFloat(data['tempinf']) - 32) * 5 / 9).toFixed(2); let luxerIntencidad = params.get("solarradiation") * 683; // luxerIntencidad en Luxer let vientoEnKm = (params.get('windspeedmph') * 1.60934).toFixed(2);; let rafagaEnKm = (params.get('windgustmph') * 1.60934).toFixed(2);; let PresionR = (parseFloat(params.get('baromabsin')) * 33.8639).toFixed(2); let PresionA = (parseFloat(params.get('baromrelin')) * 33.8639).toFixed(2); // calculo del punto de rocio var punto_de_rocio = (Math.pow((params.get("humidity") / 100), 0.125)) * (112 - (-(0.9 * TemperaturaExternaC))) - (-(0.1 * TemperaturaExternaC)) - 112; punto_de_rocio = (Math.round(punto_de_rocio * 100)) / 100; let x = params.get("winddir"); // direccion del viento por nombre switch (true) { case x === 0: VientoDireccion = 'Norte'; break; case x > 0 && x < 90: VientoDireccion = 'Nordeste'; break; case x === 90: VientoDireccion = 'Este'; break; case x > 90 && x < 180: VientoDireccion = 'Sudeste'; break; case x === 180: VientoDireccion = 'Sur'; break; case x > 180 && x < 270: VientoDireccion = 'Sudoeste'; break; case x === 270: VientoDireccion = 'Oeste'; break; case x > 270 && x < 360: VientoDireccion = 'Noroeste'; break; default: VientoDireccion = 'N/A'; } x = null; let lluviaTotalmm = (parseFloat(params.get('totalrainin')) * 25.4).toFixed(2); // conversion a mm let DatosRecolectados = [ fecha, // *0: Fecha local fechaISO, // *1: Fecha ISO parseFloat(TemperaturaExternaC), // *2: Temperatura exterior parseFloat(TemperaturaInternaC), // *3: Temperatura interior parseFloat(params.get("humidity")), // *4: Humedad exterior parseFloat(params.get("humidityin")), // *5: Humedad interior luxerIntencidad, // *6: Luz Intencidad en Klux parseFloat(params.get("uv")), // *7: Radiación UV parseFloat(vientoEnKm), // *8: Velocidad viento parseFloat(rafagaEnKm), // *9: Ráfaga parseFloat(params.get("winddir")), // *10: Dirección viento (grados) VientoDireccion, // *11: Dirección viento (nombre) parseFloat(PresionA), // *12: Presión absoluta hpa parseFloat(PresionR), // *13: Presión relativa hpa parseFloat(lluviaTotalmm), // *14: Lluvia acumulada punto_de_rocio, // *15: Punto de rocío fechaUTC, // *16: UTC desde 'dateutc' params.get('wh65batt') // *17: Estado batería ]; // Se verifican cambios if (DatosRecolectadosAnterior.length < 1) { DatosRecolectadosAnterior = DatosRecolectados;} let cambios = {}; let bandera_cambios = false; for (let i = 0; i < DatosRecolectados.length; i++) { if ( i === 0 || i === 1 || i === 16) continue; // ignorar índices 0, 1 y 16 que son fechas if (DatosRecolectados[i] !== DatosRecolectadosAnterior[i]) { bandera_cambios = true; cambios[Etiquetas[i]] = { valorAnterior: DatosRecolectadosAnterior[i], valorNuevo: DatosRecolectados[i] }; } } //cambios = JSON.stringify(cambios, null, 2); DatosRecolectados.forEach((dato, i) => { APP.RegistrarLog(`5|REGISTRO|🗃️ ${i} - ${Etiquetas[i]}: ${dato}`); }); // ACA SE ENVIA AL VALIDADOR Y A LAS REDES CONFIGURADAS var Datos = []; Datos = ['validar', DatosRecolectados,cambios,bandera_cambios]; Validador.Registros(Datos, function (errorvalidador, estadovalidador) { if (estadovalidador === true) { APP.Configuracion.Repeticiones += 1; APP.Configuracion.RepeticionesConError = 0; APP.Configuracion.TiempoMaximo = 0; APP.Configuracion.TiempoFueraDeLinea = 0; APP.Configuracion.FechaLanzadoTimeout = Date.now(); APP.Registro_Diario(Datos[1],cambios,bandera_cambios); APP.Publicar_en_Redes(); Datos = null; } else { APP.Configuracion.Repeticiones = 0; APP.Configuracion.Estado_Val_Ant = errorvalidador[0]; APP.RegistrarLog('0|VALIDADOR|⚠️ Datos recolectados incorrectos: ' + errorvalidador[1]); Datos = null; } }); APP.Configuracion.EstadoSensores = DatosRecolectados[17]; DatosRecolectadosAnterior = DatosRecolectados; // Guardar los datos recolectados para la proxima vez. APP.TiempoActualRecolector(true); // para reiniciar el tiempo y sincronizar. res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Datos POST/PATCH recibidos'); }); } else { APP.RegistrarLog('0|RECOLETOR_IP|⚠️ Dato Recibido pero metodo no encontrada: ' + method); } } else { APP.RegistrarLog('0|RECOLETOR_IP|⚠️ Dato Recibido pero ruta no encontrada: ' + pathname); } }); server.listen(PORT, HOST, () => { APP.RegistrarLog(`0|CORE|🟢 Servidor escuchando en ${HOST}:${PORT}`); APP.Configuracion.Errores = `🟢 Servidor escuchando en ${HOST}:${PORT}`; APP.Configuracion.TiempoMaximo = 0; APP.Configuracion.Run = 1; APP.Iniciar(); // Se llama a la funcion INICIO }); server.on('error', (err) => { if (err.code === 'EADDRINUSE') { APP.RegistrarLog(`0|CORE| ❌ Error: El puerto ${PORT} ya está en uso.`); //APP.Configuracion.Errores = '❌ Error el puerto ya está en uso.'; } else if (err.code === 'EACCES') { APP.RegistrarLog(`0|CORE| ❌ Error: Permiso denegado para usar el puerto ${PORT}.`); APP.Configuracion.Errores = '❌ Permiso denegado para usar el puerto.'; } else { APP.RegistrarLog(`0|CORE| ❌ Error al iniciar servidor: ${err.message}`); APP.Configuracion.Errores = '❌ Error al iniciar servidor.'; } }); }else{ // RECOLECTOR USB APP.RegistrarLog('0|CORE|Estableciendo Time Zone UTC ' + configGeneralEMA.ConfGeneral.UTC); APP.RegistrarLog('0|CORE|Verificando Estado de la EMA...'); APP.Configuracion.TiempoContinuo = configGeneralEMA.ConfGeneral.Tiempo_de_Recoleccion; APP.Configuracion.debug = configGeneralEMA.ConfGeneral.debug; recolector.conf.debug = configGeneralEMA.ConfGeneral.debug; if (recolector.status() === true || APP.Configuracion.Run === 0) { // Verifica la plataforma donde esta corriendo if (APP.Configuracion.Run === 0) { station = recolector.open(); // No puedo poner var station = -> no funciona ver. APP.RegistrarLog('0|CORE|Conectando..'); } // solo si es la primera vez, genera el recolector. if (station === null || station === false) { if (station === false) { APP.Configuracion.Errores = 'Problemas con el USB, por favor desconecte y conecte el mismo'; APP.Configuracion.Run = 0; throw new Error('Problemas con el USB, por favor desconecte y conecte el mismo.'); } else { APP.RegistrarLog('0|CORE|Info de Estado: Fuera de Linea.'); APP.RegistrarLog('0|CORE|Info de Detalle: EMA no conectada.'); APP.RegistrarLog('0|CORE|Info de Acción: Verifique la conexion USB de la EMA.'); APP.Configuracion.Errores = 'Se espera ' + APP.Configuracion.TiempoContinuo + ' segundos y se prueba conectar nuevamente.'; throw new Error('Problemas con la lectura USB'); } } else { APP.RegistrarLog('0|CORE|ESTADO: Online'); APP.RegistrarLog('0|CORE|PLATAFORMA: ' + recolector.conf.plataforma); APP.RegistrarLog('0|CORE|AUTOR:Gugler Lab'); APP.RegistrarLog('0|CORE|VERSION:' + configGlobalEMA.ConfGlobal.Version); if (APP.Configuracion.Run === 0) { APP.RegistrarLog('0|CORE|🟢 Se inicio el motor de EMA LIBRE.'); APP.Configuracion.Errores = 'CORE: INICIAR-> Se inicio el motor de EMA LIBRE.'; APP.Configuracion.Run = 1; } APP.Configuracion.TiempoMaximo = 0; APP.Iniciar(); // Se llama a la funcion INICIO } } else { if (recolector.status() === false && APP.Configuracion.Run === 0) { throw new Error('Conexión usb no detectada, por favor verifique el cable.'); } if (recolector.status() === false && APP.Configuracion.Run === 1) { APP.Configuracion.Run = 0; throw new Error('Conexión usb no detectada, se desconectó en funcionamiento.'); } } } } catch (ex) { APP.RegistrarLog('0|EXCEP|Información de la excepcion: -> ' + ex + ''); APP.Configuracion.Errores = 'EXCEP: Información de la excepcion: -> ' + ex; var tiempo = (APP.Configuracion.TiempoMaximo + APP.Configuracion.TiempoContinuo) * 1000; APP.Configuracion.TiempoFueraDeLinea += tiempo; APP.RegistrarLog('0|EXCEP|Se espera ' + (tiempo / 1000) + ' segundos y se prueba conectar nuevamente ....'); APP.Configuracion.IdsSetTimeouts.push(setTimeout(APP.Conectar, tiempo)); tiempo=null; } }, // Metodo para comprobar el errores. CompruebaError: function () { // se comprueba si ya existe otra excepcion en memoria if (process.listeners('uncaughtException').length === 0) { process.on('uncaughtException', function (err) { APP.Configuracion.RunTime = 0; // Se para el recolector APP.LimpiarM(); APP.Configuracion.Repeticiones = 0; var tiempo = (APP.Configuracion.TiempoMaximo + APP.Configuracion.TiempoContinuo) * 1000; APP.Configuracion.TiempoFueraDeLinea += tiempo; APP.Configuracion.Errores = err; if ((configGeneralEMA.ConfEmail.ActivarCorreos === true) && ((APP.Configuracion.TiempoFueraDeLinea > (APP.Configuracion.TiempoMaximoFueraDeLinea * 1000)) || ((APP.Configuracion.TiempoFueraDeLinea - tiempo) < 1))) { if ((APP.Configuracion.TiempoFueraDeLinea - tiempo) > 1) { APP.Configuracion.TiempoMaximoFueraDeLinea = APP.Configuracion.TiempoMaximoFueraDeLinea * 2; } APP.RegistrarLog('1|MAIL|Se envio correo notificando que la estacion ' + configGeneralEMA.ConfGeneral.NombreEstacion + ' se encuentra fuera de linea por mas de: ' + (APP.Configuracion.TiempoFueraDeLinea / 1000) + 's o ' + (APP.Configuracion.TiempoFueraDeLinea / 1000 / 60).toFixed(2) + ' minutos'); } APP.RegistrarLog('1|ERROR|🔴 ' + err + '.'); APP.RegistrarLog('1|ERROR|🔴 Se espera ' + (tiempo / 1000) + ' segundos ( Tiempo fuera de linea: ' + (APP.Configuracion.TiempoFueraDeLinea / 1000) + 's o ' + (APP.Configuracion.TiempoFueraDeLinea / 1000 / 60).toFixed(2) + ' minutos), luego se intenta iniciar el recolector.'); APP.Configuracion.IdsSetTimeouts.push(setTimeout(APP.Conectar, tiempo)); tiempo = null; }); } }, VerificarTanqueDePendientes: function (red) { // REGISTROS PENDIENTES DE ENVIAR (Solo redes Ema Center) if (APP.Configuracion.BanderaPendientes === 0) { // Pregunto si no esta destanqueando APP.Configuracion.TanquePendiente = []; APP.Configuracion.BanderaPendientes = 1; APP.RegistrarLog('3|PENDIENTE|🛢️ Verificando el tanque.'); try { fs.readFile('./logs/TanquePendientes.log', { encoding: 'utf8', autoClose: true }, function (err, data) { try { if (err) { APP.RegistrarLog('1|ERROR|🛢️🔴 Intentando destanquear los registros.'); APP.Configuracion.BanderaPendientes = 0; } if (data.length < 10) { APP.Configuracion.CantidadPendientes = 0; APP.Configuracion.BanderaPendientes = 0; APP.RegistrarLog('3|PENDIENTE|🛢️ Tanque vacio.'); } else { Guardar = []; var EnviarPendientes = []; var Pendientes = JSON.parse(data); var CantRegistros = Pendientes.length; var intentos = 0; APP.Configuracion.CantidadPendientes = CantRegistros; APP.RegistrarLog('3|PENDIENTE|🛢️ Cantidad Registros en Pendientes: ' + CantRegistros); for (var i = 0, t = CantRegistros; i < t; ++i) { EnviarPendientes[0] = [Pendientes[i].TipoRed, Pendientes[i].Usuario, Pendientes[i].Password, Pendientes[i].Server, Pendientes[i].Puerto, Pendientes[i].Ruta, Pendientes[i].Llave_W, Pendientes[i].Nombre, 'PENDIENTE']; EnviarPendientes[1] = Pendientes[i].registro; EnviarPendientes[2] = Pendientes[i].idRed; if ((red === Pendientes[i].idRed) && intentos < 3) { // Pregunto si la red online es la del registro en tanque y solo envio 3 registros pendientes intentos = intentos + 1; Redes.EviarRedesMeteorologicas(versionEMA, EnviarPendientes, function (red, estadored, errorRedes, idRed, registro) { var RegistroEnviado = JSON.parse(registro); if (estadored === 'ERROR') { // si falla el destanqueo APP.RegistrarLog('3|PENDIENTE|🛢️🔴 Error no se pudo publicar la Red : ' + red + ' - Estado:' + estadored); var Pendiente = { idRed: RegistroEnviado[2], TipoRed: RegistroEnviado[0][0], Usuario: RegistroEnviado[0][1], Password: RegistroEnviado[0][2], Server: RegistroEnviado[0][3], Puerto: RegistroEnviado[0][4], Ruta: RegistroEnviado[0][5], Llave_W: RegistroEnviado[0][6], Nombre: RegistroEnviado[0][7], registro: RegistroEnviado[1] }; APP.Configuracion.TanquePendiente.push(Pendiente); Pendiente = null; } else { // si es correcto, tiene que borrar el registro ya enviado APP.Configuracion.CantidadPendientes = APP.Configuracion.CantidadPendientes - 1; if (APP.Configuracion.CantidadPendientes < 0) { APP.Configuracion.CantidadPendientes = 0; } APP.RegistrarLog('0|RED|🌐🛢️ Red Publicada Tanque:' + red + '- Fecha Registro:' + RegistroEnviado[1].fecha + ' - Estado:' + estadored); } }); // CALLBACK ENVIAR RED } else { APP.Configuracion.TanquePendiente.push(Pendientes[i]); } } APP.Configuracion.BanderaPendientes = 0; APP.Guardar_Pendientes('', false); EnviarPendientes = null; } } catch (ex) { // si hay un error en el archivo tanque de pendiente se blanquea y se vuelve a llamar la misma. APP.RegistrarLog('1|ERROR|🔴 Tanque Pendientes corrupto.Se blanqueo el tanque diario para depurar el error. 2: ' + ex); APP.Configuracion.TanquePendiente = []; APP.Configuracion.BanderaPendientes = 0; fs.writeFile('./logs/TanquePendientes.log', JSON.stringify(APP.Configuracion.TanquePendiente, null, 4), { encoding: 'utf8', autoClose: true }, function (err) { if (err) { APP.RegistrarLog('1|ERROR|🔴 Guardando registro de prendientes de Ema Center en archivo :' + err); } }); } }); } catch (ex) { // si hay un error en el archivo tanque de pendiente se blanquea y se vuelve a llamar la misma. APP.RegistrarLog('1|ERROR|🔴 Tanque Pendientes corrupto.Se blanqueo el tanque diario para depurar el error. 1: ' +ex); APP.Configuracion.TanquePendiente = []; fs.writeFile('./logs/TanquePendientes.log', JSON.stringify([], null, 4), { encoding: 'utf8', autoClose: true }, function (err) { if (err) { APP.RegistrarLog('1|ERROR|🔴 Guardando registro de prendientes de Ema Center en archivo :' + err); } }); } } }, Guardar_Pendientes: function (Datos, guardar) { if (APP.Configuracion.BanderaPendientes === 0) { // Pregunto si no esta destanqueando try { if (guardar === true) { var pendienteCompleto = null; var TP_temp = fs.readFileSync('./logs/TanquePendientes.log', 'utf8'); APP.Configuracion.CantidadPendientes = APP.Configuracion.CantidadPendientes + 1; var pendienteCompleto = JSON.parse(TP_temp); for (var i = 0, t = Datos.length; i < t; ++i) {pendienteCompleto.push(Datos[i]);} APP.Configuracion.CantidadPendientes = pendienteCompleto.length; fs.writeFile('./logs/TanquePendientes.log', JSON.stringify(pendienteCompleto, null, 4), { encoding: 'utf8', autoClose: true }, function (err) { if (err) { APP.RegistrarLog('1|ERROR|🔴 Guardando registro de prendientes de Ema Center en archivo :' + err); } }); } else { fs.writeFile('./logs/TanquePendientes.log',JSON.stringify(APP.Configuracion.TanquePendiente, null, 4), { encoding: 'utf8', autoClose: true }, function (err) { if (err) { APP.RegistrarLog('1|ERROR|🔴 Guardando registro de prendientes de Ema Center en archivo :' + err); } }); } } catch (ex) { // si hay un error en el archivo tanque de pendiente se blanquea y se vuelve a llamar la misma. APP.RegistrarLog('1|ERROR| 🔴 Tanque Pendientes corrupto.Se blanqueo el tanque diario para depurar el error. 3:'+ex); APP.Configuracion.BanderaPendientes = 0; APP.Configuracion.TanquePendiente = []; APP.Guardar_Pendientes( '', false); } } }, // Metodo para publicar en redes meteorologicas Publicar_en_Redes: function () { var Publicar = configGeneralEMA.ConfPublicador; var Cantidad = Publicar.length; var UltimoRegistro = APP.Configuracion.UltimoRegistro; var Enviar = []; if (typeof UltimoRegistro !== 'undefined' && UltimoRegistro !== '') { var RegistroPublicado = ''; for (var i = 0, t = Cantidad; i < t; ++i) { if (Publicar[i].Publicar === true) { UltimoRegistro.tanque = false; Enviar[0] = [Publicar[i].TipoRed, Publicar[i].Usuario, Publicar[i].Password, Publicar[i].Server, Publicar[i].Puerto, Publicar[i].Ruta, Publicar[i].Llave_W, Publicar[i].Nombre]; Enviar[1] = UltimoRegistro; Enviar[2] = i; Redes.EviarRedesMeteorologicas(versionEMA, Enviar, function (red, estadored, errorRedes, idRed, registro) { var RegistroEnviado = JSON.parse(registro); // APP.RegistrarLog(RegistroEnviado); if (estadored === 'ERROR') { // Si hay error en publicar la red var fechaanterior = ''; if (typeof APP.Configuracion.UltimoPublicado[idRed] === 'undefined') { fechaanterior = '00/00/0000 00:00:00'; } else { fechaanterior = APP.Configuracion.UltimoPublicado[idRed].fecha; } RegistroPublicado = { "red": red, "estado": false, "fecha": fechaanterior, "error": errorRedes }; APP.Configuracion.UltimoPublicado[idRed] = RegistroPublicado; APP.RegistrarLog('3|RED|🌐🔴 Red No Publicada: ' + red + ' - Estado:' + estadored + ' ' + errorRedes); if ((red === 'emacenter') || (red === 'emacentergugler')) { APP.RegistrarLog('0|PENDIENTE|🛢️ Se almaceno registro en el tanque de pendientes: ' + RegistroEnviado[0][7]); RegistroEnviado[1].tanque = true; var PendienteTemp = { idRed: RegistroEnviado[2], TipoRed: RegistroEnviado[0][0], Usuario: RegistroEnviado[0][1], Password: RegistroEnviado[0][2], Server: RegistroEnviado[0][3], Puerto: RegistroEnviado[0][4], Ruta: RegistroEnviado[0][5], Llave_W: RegistroEnviado[0][6], Nombre: RegistroEnviado[0][7], registro: RegistroEnviado[1] }; APP.Configuracion.tempAlmacenadoPendientes.push(PendienteTemp); } } else { // Si se publico correctamente if (((red === 'emacenter' || red === 'emacentergugler')) && ((APP.Configuracion.CantidadPendientes > 0) || (APP.Configuracion.Repeticiones < 3))) { APP.VerificarTanqueDePendientes(idRed); } // verifica el tanque de redes Ema Libre Center Solamente if (estadored === 430) { RegistroPublicado = { "red": red, "estado": "No enviado", "fecha": errorRedes, "error": "No Enviado" }; estadored = 'No Enviado'; }else{ if (estadored === 429) { RegistroPublicado = { "red": red, "estado": "Esperar", "fecha": errorRedes, "error": "Red Congestionada" }; estadored = 'Congestionada'; } else { RegistroPublicado = { "red": red, "estado": true, "fecha": RegistroEnviado[1].fecha, "error": "-" }; } } APP.Configuracion.UltimoPublicado[idRed] = RegistroPublicado; APP.RegistrarLog('3|RED|🌐 Red Publicada: ' + red + ' - Estado:' + estadored); } }); // CALLBACK ENVIAR RED } else { if (typeof APP.Configuracion.UltimoPublicado[i] !== 'undefined') { RegistroPublicado = { "red": APP.Configuracion.UltimoPublicado[i].red, "estado": false, "fecha": APP.Configuracion.UltimoPublicado[i].fecha, "error": "Detenido" }; APP.Configuracion.UltimoPublicado[i] = RegistroPublicado; } } } if(APP.Configuracion.tempAlmacenadoPendientes.length > 0){APP.Guardar_Pendientes(APP.Configuracion.tempAlmacenadoPendientes, true);} APP.Configuracion.tempAlmacenadoPendientes = []; // SE eliminan las variables Publicar = null; Cantidad = null; RegistroPublicado = null; RegistroEnviado = null; UltimoRegistro = null; Enviar = null; } }, // Metodo para obtener datos de EMA CENTER en modo visor por llave de lectura Visor: function (cant, callback) { var timeout = 5000; var ServidorEMACENTER = { hostname: 'emacenter.gugler.com.ar', port: 443, path: '/api/get/' + configGeneralEMA.ConfGeneral.Llave_R + '/?cant=' + cant, method: 'GET' }; if (typeof callback !== 'function') callback = function () {}; APP.RegistrarLog('8|VISOR|Buscando un registro en EMACENTER(' + ServidorEMACENTER.hostname + ')...'); var request = https.request(ServidorEMACENTER, function (response) { if (response.statusCode === 200) { // RESPUESTA HTML Y COMPARA var message = ''; response.on('data', function (chunk) { message += chunk; }); response.on('end', function () { var result = message.trim(); var Respuesta = JSON.parse(result); // Se verifica la Respuesta // APP.RegistrarLog(Respuesta); if (typeof Respuesta.error === 'undefined') { APP.RegistrarLog('6|VISOR|Registro obtenido de ' + Respuesta.modelo + ' de Fecha: ' + Respuesta.registros[0].fecha); callback(null, Respuesta); } else { APP.RegistrarLog('6|ERROR| 🔴 Registro con algun error.'); callback(Respuesta.error, null); } }); } else { var respuesta = 'Codigo: ' + response.statusCode; APP.RegistrarLog('6|ERROR| 🔴 No se pudo obtener el registro (Modo Visor). ' + respuesta); callback(respuesta, null); } }); request.on('socket', function (socket) { socket.setTimeout(timeout); socket.on('timeout', function () { APP.RegistrarLog('6|ERROR| 🔴 TimeOut cuando se intenta obtener el registro (Modo Visor). Codigo: ' + request.statusCode); request.abort(); }); }).on('error', function (error) { callback(error, null); }); request.end(); }, // Metodo para el registro de lecturas obtenidas Registro_Diario: function (Datos,Cambios,Cambio) { // Leo El archivo de Tanque diario var LLuviaAcumuladaTotal = 0; var LLuviaAcumuladaDia = 0; var LLuviaAcumuladaHora = 99999999; var LluviaActual = 0; var LLuviaAcumuladaMinutos = 99999999; var luxerintencidad1hs = 0; var tempIntMinDia = 99; var tempIntMaxDia = -99; var humIntMaxDia = -99; var humIntMinDia = 99; var tempExtMinDia = 99; var tempExtMaxDia = -99; var humExtMaxDia = -99; var humExtMinDia = 99; var puntoDeRocioMinDia = 99; var puntoDeRocioMaxDia = -99; var luxerIntencidadMinDia = 999999; var luxerIntencidadMaxDia = -999999; var luxerUvMinDia = 99; var luxerUvMaxDia = -99; var presionRelativaMinDia = 999999; var presionRelativaMaxDia = -999999; var vientoDireccionPromDia = 0; var CantidadV = 0; var vientoVelocidadMaxDia = -999999; var vientoRafagasMaxDia = -999999; fs.readFile('./logs/registro_diario.log', { encoding: 'utf8', autoClose: true }, (err, data) => { var Guardar = []; if (err) { APP.RegistrarLog('1|ERROR| 🔴 Tanque diario corrupto.Se blanqueo el tanque diario para depurar el error.'); APP.Guardar_Diario(Guardar); } else { var DepurarLog = false; if (data.length < 10) { APP.RegistrarLog('8|ARCHIVO|🗄️ Tanque diario vacio.'); } else { try { var RegistroDiario = JSON.parse(data); var CantRegistros = RegistroDiario.length; APP.RegistrarLog('8|ARCHIVO|🗄️ Cantidad registros diarios: ' + CantRegistros); var RegistroNuevoDia = Datos[0].substring(0, 2); var RegistroNuevoHora = Datos[0].substring(11, 13); var RegistroNuevoMinuto = Datos[0].substring(14, 15); LLuviaAcumuladaTotal = Datos[14]; LLuviaAcumuladaDia = LLuviaAcumuladaTotal - RegistroDiario[0].lluvia_acumulado_total; for (var j = 0; j < CantRegistros; j++) { // Comprueba si no cambio de dia var Dia = RegistroDiario[j].fecha.substring(0, 2); var Hora = RegistroDiario[j].fecha.substring(11, 13); var Min = RegistroDiario[j].fecha.substring(14, 15); if (Dia === RegistroNuevoDia) { // Se calcula los max y min diarios (ej:terperatura y humedad) if (RegistroDiario[j].temperatura_interna > parseFloat(tempIntMaxDia)) { tempIntMaxDia = RegistroDiario[j].temperatura_interna; } if (RegistroDiario[j].temperatura_interna < parseFloat(tempIntMinDia)) { tempIntMinDia = RegistroDiario[j].temperatura_interna; } if (RegistroDiario[j].humedad_interna > parseFloat(humIntMaxDia)) { humIntMaxDia = RegistroDiario[j].humedad_interna; } if (RegistroDiario[j].humedad_interna < parseFloat(humIntMinDia)) { humIntMinDia = RegistroDiario[j].humedad_interna; } if (RegistroDiario[j].temperatura_externa > parseFloat(tempExtMaxDia)) { tempExtMaxDia = RegistroDiario[j].temperatura_externa; } if (RegistroDiario[j].temperatura_externa < parseFloat(tempExtMinDia)) { tempExtMinDia = RegistroDiario[j].temperatura_externa; } if (RegistroDiario[j].humedad_externa > parseFloat(humExtMaxDia)) { humExtMaxDia = RegistroDiario[j].humedad_externa; } if (RegistroDiario[j].humedad_externa < parseFloat(humExtMinDia)) { humExtMinDia = RegistroDiario[j].humedad_externa; } if (RegistroDiario[j].punto_de_rocio > parseFloat(puntoDeRocioMaxDia)) { puntoDeRocioMaxDia = RegistroDiario[j].punto_de_rocio; } if (RegistroDiario[j].punto_de_rocio < parseFloat(puntoDeRocioMinDia)) { puntoDeRocioMinDia = RegistroDiario[j].punto_de_rocio; } if (RegistroDiario[j].presion_relativa > parseFloat(presionRelativaMaxDia)) { presionRelativaMaxDia = RegistroDiario[j].presion_relativa; } if (RegistroDiario[j].presion_relativa < parseFloat(presionRelativaMinDia)) { presionRelativaMinDia = RegistroDiario[j].presion_relativa; } if (RegistroDiario[j].viento_velocidad > parseFloat(vientoVelocidadMaxDia)) { vientoVelocidadMaxDia = RegistroDiario[j].viento_velocidad; } if (RegistroDiario[j].viento_rafagas > parseFloat(vientoRafagasMaxDia)) { vientoRafagasMaxDia = RegistroDiario[j].viento_rafagas; } // Solo si existe sensor UV y LUX if ((RegistroDiario[j].luxer_intencidad != null) || (RegistroDiario[j].luxer_intencidad != null)) { if (RegistroDiario[j].luxer_intencidad > parseFloat(luxerIntencidadMaxDia)) { luxerIntencidadMaxDia = RegistroDiario[j].luxer_intencidad; } if (RegistroDiario[j].luxer_intencidad < parseFloat(luxerIntencidadMinDia)) { luxerIntencidadMinDia = RegistroDiario[j].luxer_intencidad; } if (RegistroDiario[j].luxer_uv > parseFloat(luxerUvMaxDia)) { luxerUvMaxDia = RegistroDiario[j].luxer_uv; } if (RegistroDiario[j].luxer_uv < parseFloat(luxerUvMinDia)) { luxerUvMinDia = RegistroDiario[j].luxer_uv; } } vientoDireccionPromDia += RegistroDiario[j].viento_direccion; CantidadV++; if (Hora === RegistroNuevoHora) { // Se calcula la lluvia acumulada hora y actual if (RegistroDiario[j].lluvia_acumulado_total < LLuviaAcumuladaHora) { LLuviaAcumuladaHora = RegistroDiario[j].lluvia_acumulado_total; luxerintencidad1hs = RegistroDiario[j].luxer_intencidad; } if (Min === RegistroNuevoMinuto) { if (RegistroDiario[j].lluvia_acumulado_total < LLuviaAcumuladaMinutos) { LLuviaAcumuladaMinutos = RegistroDiario[j].lluvia_acumulado_total; } } } Guardar.push(RegistroDiario[j]); } else { DepurarLog = true; } } vientoDireccionPromDia = vientoDireccionPromDia / CantidadV; RegistroDiario = null; } catch (ex) { // si hay un error en el archivo registro_diario se blanquea y se vuelve a llamar la misma. APP.RegistrarLog('1|ERROR| 🔴 Tanque diario corrupto.Se blanqueo el tanque diario para depurar el error.'); Guardar = []; APP.Guardar_Diario(Guardar); } } // Se depurar el registro de logs if (DepurarLog) { APP.RegistrarLog('6|ARCHIVO|Depurando archivo de logs.', true); } // REGISTRO ACTUAL LLuviaAcumuladaHora = Datos[14] - LLuviaAcumuladaHora; LLuviaAcumuladaMinutos = Datos[14] - LLuviaAcumuladaMinutos; if (tempIntMaxDia < -90) { tempIntMaxDia = 'S/D'; } if (humIntMaxDia < -90) { humIntMaxDia = 'S/D'; } if (tempIntMinDia > 90) { tempIntMinDia = 'S/D'; } if (humIntMinDia > 90) { humIntMinDia = 'S/D'; } if (tempExtMaxDia < -90) { tempExtMaxDia = 'S/D'; } if (humExtMaxDia < -90) { humExtMaxDia = 'S/D'; } if (tempExtMinDia > 90) { tempExtMinDia = 'S/D'; } if (humExtMinDia > 90) { humExtMinDia = 'S/D'; } if (puntoDeRocioMinDia > 90) { puntoDeRocioMinDia = 'S/D'; } if (puntoDeRocioMaxDia < -90) { puntoDeRocioMaxDia = 'S/D'; } if (luxerIntencidadMinDia > 900000) { luxerIntencidadMinDia = 'S/D'; } if (luxerIntencidadMaxDia < -900000) { luxerIntencidadMaxDia = 'S/D'; } if (luxerUvMinDia > 90) { luxerUvMinDia = 'S/D'; } if (luxerUvMaxDia < -90) { luxerUvMaxDia = 'S/D'; } if (presionRelativaMinDia > 900000) { presionRelativaMinDia = 'S/D'; } if (presionRelativaMaxDia < -900000) { presionRelativaMaxDia = 'S/D'; } if (vientoVelocidadMaxDia < -900000) { vientoVelocidadMaxDia = 'S/D'; } if (vientoRafagasMaxDia < -900000) { vientoRafagasMaxDia = 'S/D'; } if (LLuviaAcumuladaMinutos > 0) { LluviaActual = LLuviaAcumuladaMinutos; } else { LLuviaAcumuladaMinutos = 0; LluviaActual = 0; } if (LLuviaAcumuladaHora < 0) { LLuviaAcumuladaHora = 0; } if (LLuviaAcumuladaDia < 0) { LLuviaAcumuladaDia = 0; } APP.RegistrarLog('5|REGISTRO|🌧️ Calculado - Lluvia Hora: ' + LLuviaAcumuladaHora.toFixed(2)); APP.RegistrarLog('5|REGISTRO|🌧️ Calculado - Lluvia Actual: ' + LLuviaAcumuladaMinutos.toFixed(2)); APP.RegistrarLog('5|REGISTRO|🌧️ Calculado - Lluvia Dia: ' + LLuviaAcumuladaDia.toFixed(2)); var RegistroJSON = { fecha: Datos[0], fechaISO: Datos[1], fechaUTC: Datos[16], temperatura_externa: Datos[2], temperatura_interna: Datos[3], humedad_externa: Datos[4], humedad_interna: Datos[5], punto_de_rocio: parseFloat(Datos[15].toFixed(2)), luxer_intencidad: Datos[6], luxer_intencidad_1hs: luxerintencidad1hs, luxer_uv: Datos[7], viento_velocidad: parseFloat(Datos[8].toFixed(2)), viento_rafagas: parseFloat(Datos[9].toFixed(2)), viento_direccion: Datos[10], viento_direccion_nombre: Datos[11], presion_absoluta: Datos[12], presion_relativa: Datos[13], lloviendo: parseFloat(LluviaActual.toFixed(2)), lluvia_acu_hora: parseFloat(LLuviaAcumuladaHora.toFixed(2)), lluvia_acu_diaria: parseFloat(LLuviaAcumuladaDia.toFixed(2)), lluvia_acumulado_total: parseFloat(Datos[14].toFixed(2)), temperatura_interna_max_dia: tempIntMaxDia, temperatura_interna_min_dia: tempIntMinDia, humedad_interna_max_dia: humIntMaxDia, humedad_interna_min_dia: humIntMinDia, temperatura_externa_max_dia: tempExtMaxDia, temperatura_externa_min_dia: tempExtMinDia, humedad_externa_max_dia: humExtMaxDia, humedad_externa_min_dia: humExtMinDia, punto_de_rocio_max_dia: puntoDeRocioMaxDia, punto_de_rocio_min_dia: puntoDeRocioMinDia, luxer_intencidad_max_dia: luxerIntencidadMaxDia, luxer_intencidad_min_dia: luxerIntencidadMinDia, luxer_uv_max_dia: luxerUvMaxDia, luxer_uv_min_dia: luxerUvMinDia, presion_relativa_max_dia: presionRelativaMaxDia, presion_relativa_min_dia: presionRelativaMinDia, viento_direccion_prom_dia: parseFloat(vientoDireccionPromDia.toFixed(2)), viento_velocidad_max_dia: vientoVelocidadMaxDia, viento_rafagas_max_dia: vientoRafagasMaxDia, estado_sensores: Datos[17], diferencia: Cambios, cambio: Cambio, estado_validacion_ant: APP.Configuracion.Estado_Val_Ant }; APP.Configuracion.Estado_Val_Ant = 0; APP.Configuracion.UltimoRegistro = RegistroJSON; Guardar.push(RegistroJSON); APP.Guardar_Diario(Guardar); RegistroJSON = null; Guardar = null; LLuviaAcumuladaTotal = null; LLuviaAcumuladaDia = null; LLuviaAcumuladaHora = null; LluviaActual = null; LLuviaAcumuladaMinutos = null; luxerintencidad1hs = null; tempIntMinDia = null; tempIntMaxDia = null; humIntMaxDia = null; humIntMinDia = null; tempExtMinDia = null; tempExtMaxDia = null; humExtMaxDia = null; humExtMinDia = null; puntoDeRocioMinDia = null; puntoDeRocioMaxDia = null; luxerIntencidadMinDia = null; luxerIntencidadMaxDia = null; luxerUvMinDia = null; luxerUvMaxDia = null; presionRelativaMinDia = null; presionRelativaMaxDia = null; vientoDireccionPromDia = null; CantidadV = null; vientoVelocidadMaxDia = -null; vientoRafagasMaxDia = null; } }); }, // Metodo de ejecucion continua (repite continuamente). Continuo: function () { try { APP.LimpiarM(); APP.Configuracion.FechaLanzadoTimeout = -99; if (APP.Configuracion.Run === 1 && APP.Configuracion.RunTime === 1) { APP.Configuracion.TiempoMaximo = 0; APP.CompruebaError(); APP.Configuracion.RepeticionesConError += 1; var d = new Date(); var utc = d.getTime() + (d.getTimezoneOffset() * 60000); var db = new Date(utc + (3600000 * (APP.Configuracion.utc))); var minutos = db.getMinutes(); if (minutos <= 9) { minutos = '0' + minutos; } var hora = db.getHours(); if (hora <= 9) { hora = '0' + hora; } var mes = db.getMonth() + 1; if (mes <= 9) { mes = '0' + mes; } var dia = db.getDate(); if (dia <= 9) { dia = '0' + dia; } var segundo = db.getSeconds(); if (segundo <= 9) { segundo = '0' + segundo; } var fechac = dia + '/' + mes + '/' + db.getFullYear() + ' ' + hora + ':' + minutos + ':' + segundo; dia = null; mes = null; hora = null; minutos = null; segundo = null; db = null; utc = null; d = null; if (recolector.status() === true) { if (APP.Configuracion.Repeticiones > 1) APP.RegistrarLog('8|LECTURA|Inicio Lectura'); APP.RegistrarLog('8|REGISTRO|🎛️ Estado: online (' + APP.Configuracion.RepeticionesConError + ')'); APP.RegistrarLog('8|REGISTRO|🎛️ Fecha: ' + fechac); APP.RegistrarLog('8|REGISTRO|🎛️ Tiempo Recolección: ' + APP.Configuracion.TiempoContinuo); APP.RegistrarLog('8|REGISTRO|🎛️ Cant. Lect. sin corte: ' + APP.Configuracion.Repeticiones); //Se busca un registro usb (PROMESA - resultado(registro,cambios, true o false(si hay cambios)) recolector.Recolectar().then((resultado)=> { //APP.RegistrarLog(resultado[1]); var datosRecolectados = resultado[0]; if ((APP.Configuracion.RepeticionesConError) > APP.Configuracion.Cantidad_No_Lectura) { APP.RegistrarLog('0|CORE|⚠️ IMPORTANTE: No se puede leer la EMA por USB. Supero la Cantidad Máxima de No Lectura definida.'); APP.RegistrarLog('0|CORE|⚠️ IMPORTANTE: Supero la Cantidad Máxima de No Lectura definida.'); throw new Error('NolecturaUSB'); } if (typeof datosRecolectados !== 'undefined') { // Estado Sensores APP.Configuracion.EstadoSensores = datosRecolectados[17]; var Datos = []; Datos = ['validar', datosRecolectados,resultado[1],resultado[2]]; // Se pasa el registro al validador Validador.Registros(Datos, function (errorvalidador, estadovalidador) { if (estadovalidador === true) { APP.Configuracion.Repeticiones += 1; APP.Configuracion.RepeticionesConError = 0; APP.Configuracion.TiempoMaximo = 0; APP.Configuracion.TiempoFueraDeLinea = 0; APP.Registro_Diario(Datos[1],resultado[1],resultado[2]); APP.Publicar_en_Redes(); APP.Configuracion.FechaLanzadoTimeout = Date.now(); APP.Configuracion.IdsSetTimeouts.push(setTimeout(APP.Continuo, APP.Configuracion.TiempoContinuo * 1000)); Datos = null; } else { APP.Configuracion.Repeticiones = 0; APP.Configuracion.Estado_Val_Ant = errorvalidador[0]; APP.RegistrarLog('0|VALIDADOR|⚠️ Datos recolectados incorrectos: ' + errorvalidador[1]); APP.Configuracion.FechaLanzadoTimeout = Date.now(); APP.Configuracion.IdsSetTimeouts.push(setTimeout(APP.Continuo, APP.Configuracion.TiempoContinuo * 1000)); Datos = null; } }); Datos = null; } else { APP.RegistrarLog('0|CORE|⏳ Sincronizando.'); APP.Configuracion.Repeticiones = 0; APP.Configuracion.RepeticionesConError = 0; APP.Configuracion.IdsSetTimeouts.push(setTimeout(APP.Continuo, 1000)); } }); } else { APP.RegistrarLog('0|CORE|Estación no sincronizada.'); APP.Configuracion.Repeticiones = 0; APP.Configuracion.IdsSetTimeouts.push(setTimeout(APP.Continuo, 5000)); } } else { APP.RegistrarLog('0|CORE|⏹️ Recolector detenido.'); APP.Configuracion.RunTime = 0; } } catch (ex) { APP.RegistrarLog('0|EXCEP|💥 Información de la excepción: -> ' + ex + ''); APP.Configuracion.Errores = 'EXCEP: Información de la excepción: -> ' + ex; var tiempo = (APP.Configuracion.TiempoMaximo + APP.Configuracion.TiempoContinuo) * 1000; APP.Configuracion.TiempoFueraDeLinea += tiempo; APP.RegistrarLog('0|EXCEP|💥 Se espera ' + (tiempo / 1000) + ' segundos y se prueba conectar nuevamente ....'); APP.Configuracion.IdsSetTimeouts.push(setTimeout(APP.Conectar, tiempo)); tiempo = null; } } }; // termina el Objeto/Clase // Control de Ejecucion de Consola var parametros = process.argv; // Se lee el parametro if (parametros.indexOf('console') === -1) { // No se realiza nada ya que se tiene que iniciar desde el aplicativo APP.RegistrarLog('0|CORE|⏳ Iniciando Ema Libre en Modo gráfico o Web.'); } else { APP.Conectar(); APP.RegistrarLog('0|CORE|⏳ Iniciando Ema Libre en Modo Consola!!!.'); }