﻿#include "Medidor.h"
// #include "Puerto.h"  // Comentar esta línea si Puerto.h no existe o no es necesario
#include <ctime>
#include <math.h>
#include <unistd.h>
#include <sys/time.h>

using namespace std;

// Definir variables globales externas si es necesario
extern MYSQL *mysqlConexiones[];
extern int fd;

miPuerto = new Puerto(); 

Medidor::Medidor()
{
    this->idPuerto = 1;
    this->estado = 1;
    this->direccion = 1;
    this->puntoMedida = 1;
    this->clave = 1;
    this->gap = 1000;
    this->forzarLectura = false;

    fechaUltimaComunicacionCierres[0] = 1;
    fechaUltimaComunicacionCierres[1] = 1;
    fechaUltimaComunicacionCierres[2] = 1;
    this->fechaUltimaComunicacionInstantaneos = 1;
}

int Medidor::CRC8(unsigned char *puchMsg, unsigned int inicio, unsigned int fin)
 //param1 apunta al mensaje a calcularle el CRC 
//param2 cantidad de bytes a tratar, dentro del mensaje 
{
	try
	{
		long suma = 0;
	
		for (unsigned int i = inicio; i <= fin; i++)
		{
			suma += puchMsg[i];
		}
		return (suma % 256);
	}
	catch (...)
	{
		cout << "Problemas en ->unsigned int ModBus::CRC8 (unsigned char *puchMsg, unsigned int usDataLen)";
		return 1;
	}

}


int Medidor::enviarADSUfijo(int control)
{
	try
	{
	
	unsigned char mensajeTX[200]; 

	mensajeTX[0] = 0x10;
	mensajeTX[1] = control;
	mensajeTX[2] = (this->direccion) & 255; 
	mensajeTX[3] = (this->direccion) >> 8;
	mensajeTX[4] = CRC8(mensajeTX, 1, 3);//calculo el CRC del mensaje
	mensajeTX[5] = 0x16;

	miPuerto[this->indiceArrayPuerto].vaciarBuffer();
	miPuerto[this->indiceArrayPuerto].enviaDatos(mensajeTX, 6);
	return 0;
	}
catch(...)
 {
	 return 1;
 }

}




int Medidor::autenticarMedidor(void)
{
//(7) Envío de clave de acceso, ver apartado 5.3.1.
//(8) Idem (4)
//(9) Se envía un campo de control H5B=Bin 0101 1011, esto es PRM=1, bit de validez de
//cuenta de trama FCV=1 y código de función 11: solicitud de datos de clase 2.
//(10) El contador devuelve una ASDU 183 (HB7) de confirmación (campo de control H08) de
//clave de acceso correcta, causa H07 (Tabla 2).

	try
	{
		if (this->estado == 0)
			return NO_INTERROGA_ESTADO_0;

		unsigned int crc, nDat;
		int i, bytesRec, intento;
		unsigned char mensajeTX[200]; 
		//unsigned char mensajeRX[512]; 
		int cant;
		double nextTime, timeOut;

			
		if (miPuerto[this->indiceArrayPuerto].getConectado() == 0)
		{
			return FALTA_PROXIMO_INTERVALO;//PUERTO_DESCONECTADO;
		}

		//////////////////////////////////////////////////////
		//(1) Se inicia la comunicación por el ordenador (maestro) con una trama de longitud fija, 
		// Byte de inicio H10, campo de control H49=Bin 0100 1001, ver Figura 4, indicando PRM=1 (mensaje de maestro a esclavo) 
		//y código de función 9: Solicitud de estado de enlace), dirección de contador H581B=7000, byte de checksum HBC y byte END H16.
		//10 49 DIR_L DIR_H CRC 16
		this->enviarADSUfijo(0x49);
		
		//El contador responde con campo de control H0B=Bin 0000 1011, código función 11: estado del enlace.
		if (esperaPaqueteADSU(1000, mensajeTX) !=0x0B)
			return 1;//NO HAY RTA;

		//////////////////////////////////////////////////////
		//(3) Se envía un campo de control H40 = Bin 0100 0000, esto es PRM = 1 y código de función 0 : Reposición del enlace remoto.
		//10 40 DIR_L DIR_H CRC 16
		this->enviarADSUfijo(0x40);
		
		//(4) El contador responde con un campo de control H00, PRM=0 y código de función 0: ACK, reconocimiento positivo tipo confirm.
		if (esperaPaqueteADSU(1000, mensajeTX) !=0x00)
			return 2;//NO HAY RTA;

		
		//////////////////////////////////////////////////////
		//10 49 DIR_L DIR_H CRC 16
		this->enviarADSUfijo(0x49);
		//El contador responde con campo de control H0B=Bin 0000 1011, código función 11: estado del enlace.
		if (esperaPaqueteADSU(1000, mensajeTX) !=0x0B)
			return 3;//NO HAY RTA;


		////////////////////////////////////////////////////////////
		//ESPERAR RTA
		//(7) Envío de clave de acceso
		//////ENVIAR ATUTENTICACION
		//68 0D 0D 68 73 01 00 B7 01 06 01 00 00 01 00 00 00 34 16
		mensajeTX[0] = 0x68;//Byte de inicio de trama
		mensajeTX[1] = 0x0D;//Longitud trama
		mensajeTX[2] = 0x0D;//idem
		mensajeTX[3] = 0x68;//Byte de inicio de trama
		mensajeTX[4] = 0x73;//Campo de Control
		mensajeTX[5] = (this->direccion) & 255; 
		mensajeTX[6] = (this->direccion) >> 8;
		mensajeTX[7] = 0xB7;//Identificador de tipo, HB7=183
		mensajeTX[8] = 0x01;//SQ=0 N=1, cualificador de estructura variable con N=1 objeto de información
		mensajeTX[9] = 0x06;//Causa
		mensajeTX[10] = 0x01;//Punto de medida
		mensajeTX[11] = 0x00;//Dirección de registro (siempre =<0>)
		mensajeTX[12] = 0x00;//Dirección de registro (siempre =<0>)
		mensajeTX[13] = (clave) & 255;//Clave
		mensajeTX[14] = (clave >> 8) & 255;//Clave 
		mensajeTX[15] = (clave >> 16) & 255;//Clave
		mensajeTX[16] = (clave >> 24) & 255;//Clave
		mensajeTX[17] = CRC8(mensajeTX, 4, 16);//calculo el CRC del mensaje
		mensajeTX[18] = 0x16;//Fin de la trama
		bytesRec = 0;
		miPuerto[this->indiceArrayPuerto].vaciarBuffer();
		miPuerto[this->indiceArrayPuerto].enviaDatos(mensajeTX, 19);
		////////////////////////////////////////////////////////////
		if (esperaPaqueteADSU(1000, mensajeTX) !=0x00)
			return 4;//NO HAY RTA;


		//////////////////////////////////////////////////////
		//10 5B DIR_L DIR_H CRC 16
		this->enviarADSUfijo(0x5B);
		//(10) El contador devuelve una ASDU 183 (HB7) de confirmación (campo de control H08) de
		//clave de acceso correcta, causa H07(Tabla 2).
		if (esperaPaqueteADSU(1000, mensajeTX) != 0x08 || mensajeTX[7] != 0xB7 || mensajeTX[9] != 0x07)
			return 5;//NO HAY RTA;

		//AQUI FINALIZA LA AUTENTICACION//////////////////
		//////////////////////////////////////////////////////
		
		return COMUNICACION_EXITOSA;
	}
	catch (...)
	{
		return ERROR_TRY_CATCH;
	}
}
//*/



int Medidor::leerCierreMedidor(fecha vInicio,fecha vFin)
{
	try
	{
		if (this->estado == 0)
			return NO_INTERROGA_ESTADO_0;

		static int i=0, bytesRec, intento;
		unsigned char mensajeTX[200]; 
		int cant, rta;
		


		if (miPuerto[this->indiceArrayPuerto].getConectado() == 0)
		{
			return FALTA_PROXIMO_INTERVALO;//PUERTO_DESCONECTADO;
		}
		
		rta = this->autenticarMedidor();

		
		if (rta != 0) //inicio sesion con el medidor
		{
			cout << endl << "AUTENTICACION INCORRECTA IDMODBUS:" << this->idModBus << " PASO:" << rta;
			return 1;
		}

		int contrato = 134;

		cout << endl << endl << endl << "*************SOLICTIDUD DE CIERRE:***************" << endl;
		unsigned long clave = 1;
		//LECTURAS DE CIERRE
		
		/*
		0030   68 13 13 68 73 01 00 86 01 06  
		0040   01 00 86 02 01 81 06 11 16 15 34 08 12 9c 16      
		*/
		mensajeTX[0] = 0x68;//Byte de inicio de trama
		mensajeTX[1] = 0x13;//Longitud trama
		mensajeTX[2] = 0x13;//idem
		mensajeTX[3] = 0x68;//Byte de inicio de trama
		mensajeTX[4] = 0x73;//Campo de Control
		mensajeTX[5] = (this->direccion) & 255; 
		mensajeTX[6] = (this->direccion) >> 8;
		mensajeTX[7] = 0x86;//Identificador de tipo, H86=134
		mensajeTX[8] = 0x01;//SQ=0 N=1, cualificador de estructura variable con N=1 objeto de información
		mensajeTX[9] = 0x06;//Causa
		mensajeTX[10] = 0x01;//Punto de medida
		mensajeTX[11] = 00;//Dirección de registro 134=CONTRATO 1, 135=2 136=3
		mensajeTX[12] = contrato;//Dirección de registro (siempre =<0>)
		
		mensajeTX[13] = vInicio.minutos;//MIN
		mensajeTX[14] = vInicio.hora;//HORA
		mensajeTX[15] = vInicio.dia;//DIA
		mensajeTX[16] = vInicio.mes;//MES
		mensajeTX[17] = vInicio.ano;//AÑO
		
		mensajeTX[18] = vFin.minutos;//MIN
		mensajeTX[19] = vFin.hora;//HORA
		mensajeTX[20] = vFin.dia;//DIA
		mensajeTX[21] = vFin.mes;//MES
		mensajeTX[22] = vFin.ano;//AÑO
		
		mensajeTX[23] = CRC8(mensajeTX, 4, 22);//calculo el CRC del mensaje
		mensajeTX[24] = 0x16;//Fin de la trama
		
		bytesRec = 0;
		miPuerto[this->indiceArrayPuerto].vaciarBuffer();
		miPuerto[this->indiceArrayPuerto].enviaDatos(mensajeTX, 25);
		////////////////////////////////////////////////////////////
	
		if (esperaPaqueteADSU(1000, mensajeTX) != 0x00)
			return 2;//NO HAY RTA;

		//////////////////////////////////////////////////////
		//10 5B DIR_L DIR_H CRC 16
		this->enviarADSUfijo(0x5B);
	
	
		esperaPaqueteADSU(1000, mensajeTX);
		//68 13 13 68 08 01 00 86 01 07 01 00 86 02 01 81 06 11 16 15 34 08 12 32 16  
		if (mensajeTX[4] != 8 || mensajeTX[7] != 0x86 || mensajeTX[9] != 0x07)	 
		{
			return 3;//NO HAY RTA;
		}
		miPuerto[this->indiceArrayPuerto].setFechaRecepcionExitosa(time(NULL));
	
		
		tarificacion valores;
		int c = 0;
		int campoControl = 0x5B;
		while (1)
		{
			cout << endl << "LEYENDO CIERRE:"<<c++;
			if (campoControl == 0x5B)
				campoControl = 0x7B;
			else
				campoControl = 0x5B;
			//usleep(100000);
			this->enviarADSUfijo(campoControl);	
			esperaPaqueteADSU(1000, mensajeTX);
			if (mensajeTX[4] != 8 || mensajeTX[7] != 0x88 || mensajeTX[9] != 0x05)	 	
			{
				if (mensajeTX[4]  == 0x08 && mensajeTX[7] == contrato && mensajeTX[9] == 0x0A)
				{ //0x0A No hay más datos disponibles para el contrato
					cout << endl << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
					cout << endl << "COMUNICACION_EXITOSA-> leerCierreMedidor (Cantidad:" << c << ") -> IDMODBUS:" <<this->idModBus << endl; 
					return COMUNICACION_EXITOSA;
				}
	
				return 3;//FIN;
			}
			valores.periodoTarifario =  mensajeTX[13]-20;//20 al 29
		
			valores.VabA = (mensajeTX[17] << 24) + (mensajeTX[16] << 16) + (mensajeTX[15] << 8) + (mensajeTX[14]);
			valores.VinA = (mensajeTX[21] << 24) + (mensajeTX[20] << 16) + (mensajeTX[19] << 8) + (mensajeTX[18]);
			valores.CinA =  mensajeTX[22];
		
			valores.VabRi = (mensajeTX[26] << 24) + (mensajeTX[25] << 16) + (mensajeTX[24] << 8) + (mensajeTX[23]);
			valores.VinRi = (mensajeTX[30] << 24) + (mensajeTX[29] << 16) + (mensajeTX[28] << 8) + (mensajeTX[27]);
			valores.CinA =  mensajeTX[31];
				
			valores.VabRc = (mensajeTX[35] << 24) + (mensajeTX[34] << 16) + (mensajeTX[33] << 8) + (mensajeTX[32]);
			valores.VinRc = (mensajeTX[39] << 24) + (mensajeTX[38] << 16) + (mensajeTX[37] << 8) + (mensajeTX[36]);
			valores.CinRc =  mensajeTX[40];

			valores.VMaxA =(mensajeTX[54] << 24) + (mensajeTX[53] << 16) + (mensajeTX[52] << 8) + (mensajeTX[51]);
			valores.VMaxA /= 100;

			valores.FechaA.segundos = 0;
			valores.FechaA.minutos = mensajeTX[55] & 63;
			valores.FechaA.hora = mensajeTX[56] & 31;
			valores.FechaA.dia = mensajeTX[57] & 31;
			valores.FechaA.mes = mensajeTX[58] & 15;
			valores.FechaA.ano = mensajeTX[59];
		
			valores.CMaxA =  mensajeTX[60];
			valores.VexcA = (mensajeTX[64] << 24) + (mensajeTX[63] << 16) + (mensajeTX[62] << 8) + (mensajeTX[61]);
			valores.VexcA /= 100; 
			valores.CexcA =  mensajeTX[65];
			
			valores.inicio.segundos = 0;
			valores.inicio.minutos = mensajeTX[66] & 63;
			valores.inicio.hora = mensajeTX[67] & 31;
			valores.inicio.dia = mensajeTX[68] & 31;
			valores.inicio.mes = mensajeTX[69] & 15;
			valores.inicio.ano = mensajeTX[70];
		
			valores.fin.segundos = 0;
			valores.fin.minutos = mensajeTX[71] &63;
			valores.fin.hora = mensajeTX[72] & 31;
			valores.fin.dia = mensajeTX[73] & 31;
			valores.fin.mes = mensajeTX[74] & 15;
			valores.fin.ano = mensajeTX[75];
		
			this->insertLectura(valores);
		}
		
		cout << endl << "LECTURA DE CIERRES PARCIAL IDMODBUS:" << this->idModBus << endl;
		return 5;
	}
	catch (...)
	{
		return ERROR_TRY_CATCH;
	}
}

int Medidor::leerCurvaCarga(void)
{
	try
	{
		if (this->estado == 0)
			return NO_INTERROGA_ESTADO_0;

		static int i = 0, bytesRec, intento;
		unsigned char mensajeTX[200]; 
		//unsigned char mensajeRX[512]; 
		int cant, rta;
		
			
		if (miPuerto[this->indiceArrayPuerto].getConectado() == 0)
		{
			return FALTA_PROXIMO_INTERVALO;//PUERTO_DESCONECTADO;
		}
		
		rta = this->autenticarMedidor();
		if (rta != 0) //inicio sesion con el medidor
		{
			cout << endl << "AUTENTICACION INCORRECTA IDMODBUS:" << this->idModBus << " PASO:" << rta;
			return 1;
		}
		cout << endl << "AUTENTICACION CORRECTA IDMODBUS:" << this->idModBus;

		cout << endl << endl << endl << "*************SOLICTIDUD DE CIERRE:***************" << endl;
		unsigned long clave = 1;
		//LECTURAS DE CURVA DE CARGA
	
		mensajeTX[0] = 0x68;//Byte de inicio de trama
		mensajeTX[1] = 0x15;//Longitud trama
		mensajeTX[2] = 0x15;//idem
		mensajeTX[3] = 0x68;//Byte de inicio de trama
		mensajeTX[4] = 0x73;//Campo de Control
		mensajeTX[5] = (this->direccion) & 255; 
		mensajeTX[6] = (this->direccion) >> 8;
		mensajeTX[7] = 0x7A;//Identificador de tipo, H7A=122
		mensajeTX[8] = 0x01;//SQ=0 N=1, cualificador de estructura variable con N=1 objeto de información
		mensajeTX[9] = 0x06;//Causa
		mensajeTX[10] = 0x01;//Punto de medida
		mensajeTX[11] = 0x00;//Dirección de registro 
		mensajeTX[12] = 0x0B;//Dirección de registro 
		
		mensajeTX[13] = 0x01;//Dirección del primer total integrado
		mensajeTX[14] = 0x08;//Dirección del ultimo total integrado
	
		mensajeTX[15] = 0x01;//MIN
		mensajeTX[16] = 0x01;//HORA
		mensajeTX[17] = 0x1A;//DIA
		mensajeTX[18] = 0x07;//MES
		mensajeTX[19] = 0x12;//AÑO
		
		mensajeTX[20] = 0x01;//MIN
		mensajeTX[21] = 0x02;//HORA
		mensajeTX[22] = 0x1A;//DIA
		mensajeTX[23] = 0x08;//MES
		mensajeTX[24] = 0x12;//AÑO
		
		mensajeTX[25] = CRC8(mensajeTX, 4, 24);//calculo el CRC del mensaje
		mensajeTX[26] = 0x16;//Fin de la trama
		
		bytesRec = 0;
		miPuerto[this->indiceArrayPuerto].vaciarBuffer();
		miPuerto[this->indiceArrayPuerto].enviaDatos(mensajeTX, 27);
		////////////////////////////////////////////////////////////
	
		if (esperaPaqueteADSU(1000, mensajeTX) != 0x00)
			return 2;//NO HAY RTA;

		//////////////////////////////////////////////////////
		//10 5B DIR_L DIR_H CRC 16
		this->enviarADSUfijo(0x5B);
		//(14) El contador devuelve una ASDU 122(H7A) con campo de control H08 (datos de
		//usurario respond) y causa H07 (Tabla 2) de confirmación.
		if (esperaPaqueteADSU(1000, mensajeTX) != 0x08 || mensajeTX[7] != 0x7A || mensajeTX[9] != 0x07)
			return 3;//NO HAY RTA;

		//////////////////////////////////////////////////////
		//10 7B DIR_L DIR_H CRC 16
		while (1)
		{
			this->enviarADSUfijo(0x7B);
			//(14) El contador devuelve una ASDU 122(H7A) con campo de control H08 (datos de
			//usurario respond) y causa H0A FIN DE DATOS
			if (esperaPaqueteADSU(1000, mensajeTX) == 0x08 && mensajeTX[7] == 0x7A && mensajeTX[9] == 0x0A)
			{
				//this->fechaUltimaComunicacionCierres = time(NULL);
				return 3;//FIN;
			}
			this->enviarADSUfijo(0x7B);
			esperaPaqueteADSU(1000, mensajeTX);
			//(14) El contador devuelve una ASDU 122(H7A) con campo de control H08 (datos de
			//usurario respond) y causa H0A FIN DE DATOS
			if (esperaPaqueteADSU(1000, mensajeTX) == 0x08 && mensajeTX[7] == 0x7A && mensajeTX[9] == 0x0A)
				return 3;//FIN;

	
		}
		
		if (esperaPaqueteADSU(1000, mensajeTX) == 0x09)
		{
			cout << endl << "DATOS DE CIERRE NO DISPONIBLES:" << endl;
			return 4;//NO HAY RTA;
		}
		////////////////////////////////////////////////////////////
		//ESPERAR RTA

		cout << endl << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
		cout << endl << "COMUNICACION_EXITOSA-> leerCierreMedidor:" << endl;
		miPuerto[this->indiceArrayPuerto].setFechaRecepcionExitosa(time(NULL));
		return COMUNICACION_EXITOSA;
	}
	catch (...)
	{
		return ERROR_TRY_CATCH;
	}
}





int Medidor::leerInstantaneos(int grupo) //192:Energia 193:Potencias 194:Tensiones y Corrientes
{
	try
	{
		if (this->estado == 0)
			return NO_INTERROGA_ESTADO_0;

		static int i = 0, bytesRec, intento;
		unsigned char mensajeTX[200]; 
		//unsigned char mensajeRX[512]; 
		int cant, rta;
		
			
		if (miPuerto[this->indiceArrayPuerto].getConectado() == 0)
		{
			return FALTA_PROXIMO_INTERVALO;//PUERTO_DESCONECTADO;
		}
		
		rta = this->autenticarMedidor();

		
		if (rta != 0) //inicio sesion con el medidor
		{
			cout << endl << "AUTENTICACION INCORRECTA IDMODBUS:" << this->idModBus << " PASO:" << rta;
			return 1;
		}

		cout << endl << "*SOLICTIDUD DE INSTANTANEOS:" << grupo << endl;
		unsigned long clave = 1;
		//LECTURAS DE CIERRE
		mensajeTX[0] = 0x68;//Byte de inicio de trama
		mensajeTX[1] = 0x0A;//Longitud trama
		mensajeTX[2] = 0x0A;//idem
		mensajeTX[3] = 0x68;//Byte de inicio de trama
		mensajeTX[4] = 0x73;//Campo de Control
		mensajeTX[5] = (this->direccion) & 255; 
		mensajeTX[6] = (this->direccion) >> 8;
		mensajeTX[7] = 0xA2;//Identificador de tipo, HA2=162 PETICION GRUPOS INSTANTANEOS
		mensajeTX[8] = 0x01;//SQ=0 N=1, cualificador de estructura variable con N=1 objeto de información
		mensajeTX[9] = 0x05;//Causa
		mensajeTX[10] = 0x01;//Punto de medida
		mensajeTX[11] = 0x00;//Dirección de registro 
		mensajeTX[12] = 0x00;//Dirección de registro (siempre =<0>)
		
		mensajeTX[13] = grupo;//POTENCIAS

		mensajeTX[14] = CRC8(mensajeTX, 4, 13);//calculo el CRC del mensaje
		mensajeTX[15] = 0x16;//Fin de la trama
		
		bytesRec = 0;
		miPuerto[this->indiceArrayPuerto].vaciarBuffer();
		miPuerto[this->indiceArrayPuerto].enviaDatos(mensajeTX, 16);
		////////////////////////////////////////////////////////////
	
		if (esperaPaqueteADSU(1000, mensajeTX) != 0x00)
			return 2;//NO HAY RTA;

		//////////////////////////////////////////////////////
		//10 5B DIR_L DIR_H CRC 16
		this->enviarADSUfijo(0x5B);
		//(14) El contador devuelve una ASDU 163() con campo de control H08 (datos de
		//usurario respond) y causa H05 
		if (esperaPaqueteADSU(1000, mensajeTX) != 0x08 || mensajeTX[7] != 163 || mensajeTX[9] != 0x05)
		{
			return 3;//NO HAY RTA;
		}
		//////////////////////////////////////////////////////
		//PROCESO RTA
		switch (grupo)
		{
		case 192://ENERGIA
			registros[0]=valoresInstantaneos.E.activaImpo = (mensajeTX[17] << 24) + (mensajeTX[16] << 16) + (mensajeTX[15] << 8) + (mensajeTX[14]);
			registros[1]= valoresInstantaneos.E.activaExpo = (mensajeTX[21] << 24) + (mensajeTX[20] << 16) + (mensajeTX[19] << 8) + (mensajeTX[18]);
			registros[2] = valoresInstantaneos.E.reactivaQ1 = (mensajeTX[25] << 24) + (mensajeTX[24] << 16) + (mensajeTX[23] << 8) + (mensajeTX[22]);
			registros[3] = valoresInstantaneos.E.reactivaQ2 = (mensajeTX[29] << 24) + (mensajeTX[28] << 16) + (mensajeTX[27] << 8) + (mensajeTX[26]);
			registros[4] = valoresInstantaneos.E.reactivaQ3 = (mensajeTX[33] << 24) + (mensajeTX[32] << 16) + (mensajeTX[31] << 8) + (mensajeTX[30]);
			registros[5] = valoresInstantaneos.E.reactivaQ4 = (mensajeTX[37] << 24) + (mensajeTX[36] << 16) + (mensajeTX[35] << 8) + (mensajeTX[34]);

		
			valoresInstantaneos.E.tiempo.ano = mensajeTX[42];
			valoresInstantaneos.E.tiempo.mes = mensajeTX[41];
			valoresInstantaneos.E.tiempo.dia = mensajeTX[40] & 31;
			valoresInstantaneos.E.tiempo.hora = mensajeTX[39] & 31;
			valoresInstantaneos.E.tiempo.minutos = mensajeTX[38] & 63;
			valoresInstantaneos.E.tiempo.segundos = 0;//
			break;

		case 193://POTENCIAS
			registros[6] = valoresInstantaneos.P.activaTotal = (float)((mensajeTX[16] << 16) + (mensajeTX[15] << 8) + (mensajeTX[14]))/10;
			registros[7] = valoresInstantaneos.P.reactivaTotal = (float)((mensajeTX[19] << 16) + (mensajeTX[18] << 8) + (mensajeTX[17]))/10;
			registros[8] = valoresInstantaneos.P.factorPotenciaTotal = ((float)((mensajeTX[21] & 3) << 8) + (float)(mensajeTX[20])) / 1000;

			registros[9] = valoresInstantaneos.P.activaFases[0] = (float)((mensajeTX[24] << 16) + (mensajeTX[23] << 8) + (mensajeTX[22])) / 10;
			registros[10] = valoresInstantaneos.P.reactivaFases[0] = (float)((mensajeTX[27] << 16) + (mensajeTX[26] << 8) + (mensajeTX[25])) / 10;
			registros[11] = valoresInstantaneos.P.factorPotenciaFases[0] = ((float)((mensajeTX[29] & 3) << 8) + (float)(mensajeTX[28])) / 1000;

			registros[12] = valoresInstantaneos.P.activaFases[1] = (float)((mensajeTX[32] << 16) + (mensajeTX[31] << 8) + (mensajeTX[30])) / 10;
			registros[13] = valoresInstantaneos.P.reactivaFases[1] = (float)((mensajeTX[35] << 16) + (mensajeTX[34] << 8) + (mensajeTX[33])) / 10;
			registros[14] = valoresInstantaneos.P.factorPotenciaFases[1] = ((float)((mensajeTX[37] & 3) << 8) + (float)(mensajeTX[36])) / 1000;

			registros[15] = valoresInstantaneos.P.activaFases[2] = (float)((mensajeTX[40] << 16) + (mensajeTX[39] << 8) + (mensajeTX[38])) / 10;
			registros[16] = valoresInstantaneos.P.reactivaFases[2] = (float)((mensajeTX[43] << 16) + (mensajeTX[42] << 8) + (mensajeTX[41])) / 10;
			registros[17] = valoresInstantaneos.P.factorPotenciaFases[2] = ((float)((mensajeTX[45] & 3) << 8) + (float)(mensajeTX[44])) / 1000;

			
			valoresInstantaneos.P.tiempo.ano = mensajeTX[50];
			valoresInstantaneos.P.tiempo.mes = mensajeTX[49];
			valoresInstantaneos.P.tiempo.dia = mensajeTX[48] & 31;
			valoresInstantaneos.P.tiempo.hora = mensajeTX[47] & 31;
			valoresInstantaneos.P.tiempo.minutos = mensajeTX[46] & 63;
			valoresInstantaneos.P.tiempo.segundos = 0;
			break;

		case 194://TENSIONES Y CORRIENTES
			registros[18] = valoresInstantaneos.IV.tension[0] = (float)((mensajeTX[19] << 16) + (mensajeTX[18] << 8) + (mensajeTX[17])) / 10;
			registros[19] = valoresInstantaneos.IV.tension[1] = (float)((mensajeTX[26] << 16) + (mensajeTX[25] << 8) + (mensajeTX[24])) / 10;
			registros[20] = valoresInstantaneos.IV.tension[2] = (float)((mensajeTX[33] << 16) + (mensajeTX[32] << 8) + (mensajeTX[31])) / 10;

			registros[21] = valoresInstantaneos.IV.corriente[0] = (float)((mensajeTX[16] << 16) + (mensajeTX[15] << 8) + (mensajeTX[14])) / 10;
			registros[22] = valoresInstantaneos.IV.corriente[1] = (float)((mensajeTX[23] << 16) + (mensajeTX[22] << 8) + (mensajeTX[21])) / 10;
			registros[23] = valoresInstantaneos.IV.corriente[2] = (float)((mensajeTX[30] << 16) + (mensajeTX[29] << 8) + (mensajeTX[28])) / 10;

			registros[24] = valoresInstantaneos.IV.tiempo.ano = mensajeTX[39];
			registros[25] = valoresInstantaneos.IV.tiempo.mes = mensajeTX[38];
			registros[26] = valoresInstantaneos.IV.tiempo.dia = mensajeTX[37] & 31;
			registros[27] = valoresInstantaneos.IV.tiempo.hora = mensajeTX[36] & 31;
			registros[28] = valoresInstantaneos.IV.tiempo.minutos = mensajeTX[35] & 63;
			registros[29] = valoresInstantaneos.IV.tiempo.segundos = mensajeTX[34] & 63;

			fechaUltimaComunicacionInstantaneos = time(NULL);
			break;
		}
	
		cout << endl << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
		cout << endl << "COMUNICACION_EXITOSA-> Instantaneos:" << endl;
		miPuerto[this->indiceArrayPuerto].setFechaRecepcionExitosa(time(NULL));
		return COMUNICACION_EXITOSA;
	}
	catch (...)
	{
		return ERROR_TRY_CATCH;
	}
}
//*/

//////////////////////////////////////////////////////////////////////////////////
int Medidor::esperaPaqueteADSU(unsigned int vDelay, unsigned char *vMensajeRX)
 /*
 Carácter de inicio
Es el que inicia la trama (1 byte). En las tramas de longitud variable es el byte hexadecimal 68, 
indicado como 16#68 o H68. Se utiliza dos veces, una para comenzar la trama y otra para indicar el 
lugar en el que comienzan los comandos de la misma. En las tramas de longitud fija es el byte H10.

3.2. Longitud
Se envía por duplicado. Son dos bytes repetidos y cada uno indica el número de bytes que se envían 
en la trama comenzando por el campo de control (incluido) hasta el Checksum (no incluido).
*/
{
	try
	{	
		int bytesRec;
		unsigned long nextTime = 0;
		int cantidad=6;

		for (int i = 0; i < 200; i++)
			vMensajeRX[i] = 0xFF;
		vDelay = vDelay + this->gap;

		while (1)
		{
			bytesRec = miPuerto[this->indiceArrayPuerto].getCantRecibidos();
			if (bytesRec > 2)
			{//me fijo si es fijo o variables
				miPuerto[this->indiceArrayPuerto].getRecibidos(vMensajeRX);
				if (vMensajeRX[0] == 0x10)
					cantidad = 6;
				else
				if (vMensajeRX[0] == 0x68 && vMensajeRX[1] == vMensajeRX[2])
					cantidad = vMensajeRX[1] + 6;//4 0x68 CANT CANT 0x68 ..........0x16
				else
				if (vMensajeRX[0] != 0x10 || vMensajeRX[0] != 0x68)
					return -1;//error
			}

			if (bytesRec >= cantidad)
			{
				bytesRec = miPuerto[this->indiceArrayPuerto].getCantRecibidos();
				miPuerto[this->indiceArrayPuerto].getRecibidos(vMensajeRX);
				break;//sale por recepción de paquete
			}
				
			if (nextTime > vDelay)
				return -2;//sale por timeOut

			usleep(10000);
			nextTime += 10; //esperé 10ms más
		
		}
		
		//FIJO
		if (CRC8(vMensajeRX, 1, 3) == vMensajeRX[4] && vMensajeRX[0] == 0x10) //calculo el CRC del mensaje
			return vMensajeRX[1];//si es OK retorno el campo Control del mensaje

		//VARIABLE
		if (CRC8(vMensajeRX, 4, vMensajeRX[1] + 3) == vMensajeRX[(vMensajeRX[1]+4)] && vMensajeRX[0] == 0x68) //calculo el CRC del mensaje
			return vMensajeRX[4];//si es OK retorno el campo Control del mensaje

		return -3;
	}
	catch (...)
	{
		cout << "Problemas en ->unsigned int Medidor::esperaPaqueteADSU";
		return -100;
	}

}


int Medidor::insertLectura(tarificacion lectura)
{

	try
	{
		char buffer[600];
		bool guardaNULL = false;
		//return 1;
		struct tm * fReg;
		char stringFechaInicio[50];
		char stringFechaFin[50];	
		char stringFechaMax[50];
		char stringInsert[400];	
		char stringInsertColumnas[400];
		
		sprintf(stringFechaInicio,"'%04d-%02d-%02d %02d:%02d:%02d'", lectura.inicio.ano + 2000, lectura.inicio.mes, lectura.inicio.dia, lectura.inicio.hora, lectura.inicio.minutos, lectura.inicio.segundos);		
		sprintf(stringFechaFin,  "'%04d-%02d-%02d %02d:%02d:%02d'", lectura.fin.ano + 2000, lectura.fin.mes, lectura.fin.dia, lectura.fin.hora, lectura.fin.minutos, lectura.fin.segundos);		
		sprintf(stringFechaMax,  "'%04d-%02d-%02d %02d:%02d:%02d'", lectura.FechaA.ano + 2000, lectura.FechaA.mes, lectura.FechaA.dia, lectura.FechaA.hora, lectura.FechaA.minutos, lectura.FechaA.segundos);		
		

		sprintf(stringInsertColumnas,"%d,%d,%ld,%ld,%d,%ld,%ld,%d,%ld,%ld,%d,0,0,0,0,%.2f,%s,%d,%.1f,%d,%s,%s,1",
			this->idSistema,lectura.periodoTarifario,lectura.VabA,lectura.VinA,lectura.CinA,lectura.VabRi,lectura.VinRi,
			lectura.CinRi,lectura.VabRc,lectura.VinRc,lectura.CinRc,lectura.VMaxA,stringFechaMax,lectura.CMaxA,
			lectura.VexcA,lectura.CexcA,stringFechaInicio,stringFechaFin);

		sprintf(buffer, "INSERT IGNORE INTO medidores_lecturas(idSistema, periodoTarifario, vaba, vina, cina, vabri, vinri, cinri, vabrc, vinrc, cinrc, r7, cr7, r8, cr8, vmaxa, fechaA, cmaxa, vexca, cexca, fechaIni, fechaFin, informacionCierre) VALUES(%s);", stringInsertColumnas);	

		usleep(100000);
		if (mysqlConexiones[1] != NULL)
		{	
			cout << endl << "INSERT MEDIDORES:" << buffer<< endl;
        	if (mysql_query(mysqlConexiones[1], buffer))
			{
				fprintf(stderr, "%s\n", mysql_error(mysqlConexiones[1]));
				return 1;
			}
		}

		return 0;
	}
	catch (...)
	{
		cout << "Problemas en ->void Entrada::insertLectura, IDMODBUS: "<< this->idModBus;
		return 2;
	}
}


int Medidor::updateInstantaneos(instantaneos lectura)
{

	try
	{
		char buffer[800];
		char stringFecha[50];	
		
		if (lectura.IV.tiempo.mes < 1 || lectura.IV.tiempo.dia < 1)
			return 6;

		sprintf(stringFecha, "'%04d-%02d-%02d %02d:%02d:%02d'", lectura.IV.tiempo.ano + 2000, lectura.IV.tiempo.mes, lectura.IV.tiempo.dia, lectura.IV.tiempo.hora, lectura.IV.tiempo.minutos, lectura.IV.tiempo.segundos);		
		
		sprintf(buffer,
			"call updateMedidorInstantaneos(%d, %.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%d,%d,%.1f,%.1f,%.2f,%d,%d,%.1f,%.1f,%.2f,%d,%d,%.1f,%.1f,%.2f,%d,%d,%ld,%ld,%ld,%ld,%ld,%ld,%s);",

//			"call updateMedidorInstantaneos(%d, %.1f,%.1f,%.1f,%.1f,%.1f,%.1f,%ld,%ld,%d,%d,%ld,%ld,%.2f,%d,%d,%ld,%ld,%.2f,%d,%d,%ld,%ld,%.2f,%d,%d,%ld,%ld,%ld,%ld,%ld,%ld,%s);",
			this->idSistema,
			lectura.IV.corriente[0],
			lectura.IV.tension[0],
			lectura.IV.corriente[1],
			lectura.IV.tension[1],
			lectura.IV.corriente[2],
			lectura.IV.tension[2],
			lectura.P.activaTotal,
			lectura.P.reactivaTotal,
			lectura.P.activaTotalImpoExpo,
			lectura.P.reactivaTotalImpoExpo,
			lectura.P.activaFases[0],
			lectura.P.reactivaFases[0],
			lectura.P.factorPotenciaFases[0],
			lectura.P.activaFasesImpoExpo[0],
			lectura.P.reactivafasesImpoExpo[0],
			lectura.P.activaFases[1],
			lectura.P.reactivaFases[1],
			lectura.P.factorPotenciaFases[1],
			lectura.P.activaFasesImpoExpo[1],
			lectura.P.reactivafasesImpoExpo[1],
			lectura.P.activaFases[2],
			lectura.P.reactivaFases[2],
			lectura.P.factorPotenciaFases[2],
			lectura.P.activaFasesImpoExpo[2],
			lectura.P.reactivafasesImpoExpo[2],

			lectura.E.activaImpo,
			lectura.E.activaExpo,
			lectura.E.reactivaQ1,
			lectura.E.reactivaQ2,
			lectura.E.reactivaQ3,
			lectura.E.reactivaQ4,//*/
			stringFecha);



		cout << endl << buffer << endl;		//OJOOOOOOOOOOOOOOOOOO
		//sleep(5);
		if (mysqlConexiones[1] != NULL)
		{	
			if (mysql_query(mysqlConexiones[1], buffer))
			{
				fprintf(stderr, "%s\n", mysql_error(mysqlConexiones[1]));
				return 1;
			}
		}

		return 0;
	}
	catch (...)
	{
		cout << "Problemas en ->void Entrada::insertInstantaneos, IDMODBUS: " << this->idModBus;
		return 2;
	}
}


void Medidor::inicializarMedidor(int vIdModbus)
{

	try
	{
		
		char buffer[400];
  
		this->idModBus = vIdModbus;

		sprintf(buffer, "SELECT idPuerto,GAP,direccionEnlace,puntoMedida,clave,IdSistema FROM modbus WHERE idModBus=%d", this->idModBus);
 	
		if (mysqlConexiones[0] != NULL)
		{
			if (!mysql_query(mysqlConexiones[0], buffer))
			{
				MYSQL_RES *result = mysql_store_result(mysqlConexiones[0]);
				if (result != NULL)
				{
				//Get the number of columns
					MYSQL_ROW row;	//An array of strings
					if ((row = mysql_fetch_row(result)))
					{
						this->idPuerto = (atoi(row[0]));
						this->gap = (atoi(row[1]));
						this->direccion = (atoi(row[2]));
						this->puntoMedida = (atoi(row[3]));
						this->clave = (atoi(row[4]));
						this->idSistema = (atoi(row[5]));
					}
				}
				mysql_free_result(result);
			}
		}
			//*/
		return;
	}
	catch (...)
	{
		cout << "Problemas en ->void Medidor::inicializarMedidor(void)";
		return;
	}
}//FIN //////////////////////////////////////////////////////////////////////////////////////////////




int Medidor::interrogarMedidor(void)
{
	try
	{
		static unsigned long ultimoIntentoCierre[] = { 0, 0, 0 };//hora,1 meses,3 meses
		static unsigned long ultimoIntentoInstantaneos = 0;
		int respuesta;
		respuesta = ERROR_TIEMPO_EXCEDIDO;

		if (this->estado == 0)
			return NO_INTERROGA_ESTADO_0;
	
		///////////////////////
		fecha fechaInicio,fechaFin;
		struct tm * fInicio;	
		time_t tiempoInicio;	
		char stringFechaInicio[200]; 
		
		
		struct tm * fFin;
		char stringFechaFin[200]; 
		time_t tiempoFin = time(NULL);			
		fFin = localtime(&tiempoFin);
		sprintf(stringFechaFin, "%02d-%02d-%02d %02d:%02d:%02d", fFin->tm_year - 100, fFin->tm_mon + 1, fFin->tm_mday, fFin->tm_hour, fFin->tm_min, fFin->tm_sec);		
		fechaFin.ano = fFin->tm_year - 100;
		fechaFin.mes = fFin->tm_mon + 1;
		fechaFin.dia = fFin->tm_mday;
		fechaFin.hora = fFin->tm_hour;
		fechaFin.minutos = fFin->tm_min;

		//////////////

			
		if (miPuerto[this->indiceArrayPuerto].getConectado() == 0)
		{
			return FALTA_PROXIMO_INTERVALO;//PUERTO_DESCONECTADO;
		}


		
		////////////////////////////CIERRE ///////////////////////////////////////////
		if ((time(NULL) - this->fechaUltimaComunicacionCierres[0] > (3600 * 24 * 31 * 3) && time(NULL) - ultimoIntentoCierre[0] > 3600) || forzarLectura)
		{//ULTIMOS 13 MESES
			forzarLectura = false;
			tiempoInicio = time(NULL) - (3600 * 24 * 31 * 13);
			fInicio = localtime(&tiempoInicio);
			sprintf(stringFechaInicio, "%02d-%02d-%02d %02d:%02d:%02d", fInicio->tm_year - 100, fInicio->tm_mon + 1, fInicio->tm_mday, fInicio->tm_hour, fInicio->tm_min, fInicio->tm_sec);		
		
			fechaInicio.ano = fInicio->tm_year - 100;
			fechaInicio.mes = fInicio->tm_mon + 1;
			fechaInicio.dia = fInicio->tm_mday;
			fechaInicio.hora = fInicio->tm_hour;
			fechaInicio.minutos = fInicio->tm_min;

			ultimoIntentoCierre[0] = time(NULL);
			if (leerCierreMedidor(fechaInicio, fechaFin) == COMUNICACION_EXITOSA)
				fechaUltimaComunicacionCierres[0] = time(NULL);	
		}
		
		if (time(NULL) - this->fechaUltimaComunicacionCierres[1] > (3600 * 24 * 31) && time(NULL) - ultimoIntentoCierre[1] > 900)
		{//ULTIMOS 3 MESES
			tiempoInicio = time(NULL) - (3600 * 24 * 31 * 3);
			fInicio = localtime(&tiempoInicio);
			sprintf(stringFechaInicio, "%02d-%02d-%02d %02d:%02d:%02d", fInicio->tm_year - 100, fInicio->tm_mon + 1, fInicio->tm_mday, fInicio->tm_hour, fInicio->tm_min, fInicio->tm_sec);		
		
			fechaInicio.ano = fInicio->tm_year - 100;
			fechaInicio.mes = fInicio->tm_mon + 1;
			fechaInicio.dia = fInicio->tm_mday;
			fechaInicio.hora = fInicio->tm_hour;
			fechaInicio.minutos = fInicio->tm_min;

			ultimoIntentoCierre[1] = time(NULL);
			if (leerCierreMedidor(fechaInicio, fechaFin) == COMUNICACION_EXITOSA)
				fechaUltimaComunicacionCierres[1] = time(NULL);	
		}
		
			
		if (time(NULL) - this->fechaUltimaComunicacionCierres[2] > 3600 && time(NULL) - ultimoIntentoCierre[2] > 900)
		{//ULTIMOS 1 MESES
			tiempoInicio = time(NULL) - (3600 * 24 * 31 * 1);
			fInicio = localtime(&tiempoInicio);
			sprintf(stringFechaInicio, "%02d-%02d-%02d %02d:%02d:%02d", fInicio->tm_year - 100, fInicio->tm_mon + 1, fInicio->tm_mday, fInicio->tm_hour, fInicio->tm_min, fInicio->tm_sec);		
		
			fechaInicio.ano = fInicio->tm_year - 100;
			fechaInicio.mes = fInicio->tm_mon + 1;
			fechaInicio.dia = fInicio->tm_mday;
			fechaInicio.hora = fInicio->tm_hour;
			fechaInicio.minutos = fInicio->tm_min;

			ultimoIntentoCierre[2] = time(NULL);
			if (leerCierreMedidor(fechaInicio, fechaFin) == COMUNICACION_EXITOSA)
				fechaUltimaComunicacionCierres[2] = time(NULL);	
		}

		//*/
		//////////////////////INSTANTANEOS////////////////////////////////////////////////////////////
		if(time(NULL) - this->fechaUltimaComunicacionInstantaneos > 30  && time(NULL) - ultimoIntentoInstantaneos > 4)
		{
			ultimoIntentoInstantaneos = time(NULL);
			leerInstantaneos(192);
			leerInstantaneos(193);
			leerInstantaneos(194);

			this->updateInstantaneos(valoresInstantaneos);	
			//miPuerto[this->indiceArrayPuerto].setFechaRecepcionExitosa(time(NULL));
		}//*/
		
	 if (time(NULL) - this->fechaUltimaComunicacionInstantaneos < 60) 
			respuesta = COMUNICACION_EXITOSA;

		return respuesta;
	}
	catch (...)
	{
		return ERROR_TRY_CATCH;
	}
}