/********************************************************************************
*********************************************************************************
*Projeto:	TCgertec
*Arquivo:	TCgertec_PostGre.c
*Descrição:	Programa responsável pela comunicação entre o terminal e o servidor
*Data da Criação:	01/06/2006

*Revisão:	1.0
*Data:		01/06/2006
*Modificações:

**********************************************************************************
**********************************************************************************

Funções e procedimentos utilizados no arquivo

unsigned short ConvertCor(char *cor) - Converte as cores (nome para código)
void LOG_RECEIVE(char *comando,int ID,int type,FILE *log) - Escreve no LOG mensagens vindas dos terminais
void LOG(char *comando,int POS,FILE *log) - Escreve no LOG mensagens vindas do servidor
void *Check(void* arg) - Verifica e trata mensagens vindas dos terminais
void *Start(void *arg) - Inicia a lib
int main() - Inicia o programa e recebe mensagens vindas do servidor

********************************************************************************/

/*-------------------------------------------------------------------------------
			INCLUDES
-------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/msg.h>
#include <time.h>
#include <unistd.h>
#include <pgsql/libpq-fe.h> // Biblioteca do postgre

#include "libTCgertec.h" // Header que contém as funções e TYPES da libTCgertec.so

#include "tabelas_PostGre.h"

#include "images.h" // Header com as Funções que montam as imagens (ver images.c)
#include "msq.h" // Header com Types e constantes para o "Message Queue"

/*-------------------------------------------------------------------------------
			VARIÁVEIS GLOBAIS
-------------------------------------------------------------------------------*/

TabConec tabela; //Recebe a tabela de terminais conectados

ARG_SETUP_TCP setup; //Recebe as configurações dos terminais de consultas TC504
PARAMConfig param; // Recebe os Parâmetros de rede dos terminais (protocolo TC501 apenas)
Config conf; // Recebe as Configurações dos terminais (protocolo TC501 apenas)
UPDConfig upd; // Recebe as Parâmetros de Atualização dos terminais (protocolo TC501 apenas)

char linha_log[512]; // String que possue a linha a ser escrita no LOG

int msgkey;

struct tm *hora; // Estrutura para a escrita da HORA (LOG)
time_t hora_sist; // Variável para o controle da HORA (LOG)

PGconn *conn; //Cria a conexão com o banco de dados PostGreSQL

struct
{
	Preco produto;
	int ID;
}ImagemCasada; //Struct para o tratamento de Imagens casadas
/********************************************************************************
>>>> void *Menu_504(void *arg) <<<<
---------------------------------------------------------------------------------
*Função:	void Menu_504(int ID , int cmd)
*Descrição:	Transfoma os botões do 504 em um menu

*Entrada:	ID: Referência do terminal
		cmd: Char que indica qual botão foi pressionado
*Saída:		void

*Data da Criação:	25/09/2006
*Modificações:

*Obs:

********************************************************************************/
void *Menu_504(void *arg)
{
	int controle[100];
	int i;
	char img1[50],img2[50],img3[50],img4[50],img5[50],img6[50],img7[50],img8[50];
	char caractere;
	
	Menu_TC504 mqueue;
	
	strcpy(img1,".//images//img1.bmp");
	strcpy(img2,".//images//img2.bmp");
	strcpy(img3,".//images//img3.bmp");
	strcpy(img4,".//images//img4.bmp");
	strcpy(img5,".//images//img5.bmp");
	strcpy(img6,".//images//img6.bmp");
	strcpy(img7,".//images//img7.bmp");
	strcpy(img8,".//images//img8.bmp");
	
	for(i = 0 ; i<100 ; i++)
	controle[i] = 0;
	
	while(1)
	{
		if(msgrcv(msgkey,&mqueue,5,5,0))
		{
			
			if(controle[mqueue.identificador] == 0)
			{
				StopLoop(mqueue.identificador);
				SendImage(mqueue.identificador,img1);
				controle[mqueue.identificador] = 1;
			}
// 			Tratamento do botão a no teclado do 504
			else if(mqueue.comando == 'a' && controle[mqueue.identificador] == 1)
			{
				SendImage(mqueue.identificador,img2);
				controle[mqueue.identificador] = 2;
			}
		
			else if(mqueue.comando == 'a' && controle[mqueue.identificador] == 2)
			{
				SendImage(mqueue.identificador,img3);
				controle[mqueue.identificador] = 3;
			}
			
			else if(mqueue.comando == 'a' && controle[mqueue.identificador] == 3)
			{
				SendImage(mqueue.identificador,img4);
				controle[mqueue.identificador] = 4;
			}

			else if(mqueue.comando == 'a' && controle[mqueue.identificador] == 5)
			{
				SendImage(mqueue.identificador,img6);
				controle[mqueue.identificador] = 6;
			}

			else if(mqueue.comando == 'a' && controle[mqueue.identificador] == 6)
			{
				SendImage(mqueue.identificador,img7);
				controle[mqueue.identificador] = 7;
			}

			else if(mqueue.comando == 'a' && controle[mqueue.identificador] == 7)
			{
				SendImage(mqueue.identificador,img8);
				controle[mqueue.identificador] = 8;
			}
// 			Tratamento do botão b no teclado do 504
			else if(mqueue.comando == 'b' && controle[mqueue.identificador] == 4)
			{
				SendImage(mqueue.identificador,img3);
				controle[mqueue.identificador] = 3;
			}
			
			else if(mqueue.comando == 'b' && controle[mqueue.identificador] == 3)
			{
				SendImage(mqueue.identificador,img2);
				controle[mqueue.identificador] = 2;
			}
			
			else if(mqueue.comando == 'b' && controle[mqueue.identificador] == 2)
			{
				SendImage(mqueue.identificador,img1);
				controle[mqueue.identificador] = 1;
			}

			else if(mqueue.comando == 'b' && controle[mqueue.identificador] == 8)
			{
				SendImage(mqueue.identificador,img7);
				controle[mqueue.identificador] = 7;
			}

			else if(mqueue.comando == 'b' && controle[mqueue.identificador] == 7)
			{
				SendImage(mqueue.identificador,img6);
				controle[mqueue.identificador] = 6;
			}

			else if(mqueue.comando == 'b' && controle[mqueue.identificador] == 6)
			{
				SendImage(mqueue.identificador,img5);
				controle[mqueue.identificador] = 5;
			}
// 			Tratamento do botão c no teclado do 504
			else if(mqueue.comando == 'c' && controle[mqueue.identificador] == 1)
			{
				SendImage(mqueue.identificador,img5);
				controle[mqueue.identificador] = 5;
			}
			
			else if(mqueue.comando == 'c' && controle[mqueue.identificador] == 2)
			{
				SendImage(mqueue.identificador,img6);
				controle[mqueue.identificador] = 6;
			}
			
			else if(mqueue.comando == 'c' && controle[mqueue.identificador] == 3)
			{
				SendImage(mqueue.identificador,img7);
				controle[mqueue.identificador] = 7;
			}
			
			else if(mqueue.comando == 'c' && controle[mqueue.identificador] == 4)
			{
				SendImage(mqueue.identificador,img8);
				controle[mqueue.identificador] = 8;
			}
// 			Tratamento do botão d no teclado do 504
			else if(mqueue.comando == 'd' && controle[mqueue.identificador] == 5)
			{
				SendImage(mqueue.identificador,img1);
				controle[mqueue.identificador] = 1;
			}
			
			else if(mqueue.comando == 'd' && controle[mqueue.identificador] == 6)
			{
				SendImage(mqueue.identificador,img2);
				controle[mqueue.identificador] = 2;
			}
			
			else if(mqueue.comando == 'd' && controle[mqueue.identificador] == 7)
			{
				SendImage(mqueue.identificador,img3);
				controle[mqueue.identificador] = 3;
			}
			
			else if(mqueue.comando == 'd' && controle[mqueue.identificador] == 8)
			{
				SendImage(mqueue.identificador,img4);
				controle[mqueue.identificador] = 4;
			}
			
			else if(mqueue.comando == 'd' && (controle[mqueue.identificador] == 1 || controle[mqueue.identificador] == 2 || controle[mqueue.identificador] == 3 || controle[mqueue.identificador] == 4))
			{
				controle[mqueue.identificador] = 0;
				StartLoop(mqueue.identificador);
				
			}
		}
	}
}
/********************************************************************************
>>>> ConvertCor(char *cor) <<<<
---------------------------------------------------------------------------------
*Função:	unsigned short ConvertCor(char *cor)
*Descrição:	Converte a cor (string com o nome) para o códgo em hexadecimal

*Entrada:	String com o nome da cor
*Saída:		Retorna o código Hexadecimal da cor

*Data da Criação:	01/06/2006
*Modificações:

*Obs:

********************************************************************************/

unsigned short ConvertCor(char *cor)
{
	// Verifica a string com o nome da cor e retorna o código
	if (!strncmp(cor,"black",5)) return 0x100;
	else if (!strncmp(cor,"brown",5)) return 0x101;
	else if (!strncmp(cor,"green",5)) return 0x102;
	else if (!strncmp(cor,"olive",5)) return 0x103;
	else if (!strncmp(cor,"navy",4)) return 0x104;
	else if (!strncmp(cor,"purple",6)) return 0x105;
	else if (!strncmp(cor,"teal",4)) return 0x106;
	else if (!strncmp(cor,"gray",4)) return 0x107;
	else if (!strncmp(cor,"silver",6)) return 0x108;
	else if (!strncmp(cor,"red",3)) return 0x109;
	else if (!strncmp(cor,"lime",4)) return 0x10A;
	else if (!strncmp(cor,"yellow",6)) return 0x10B;
	else if (!strncmp(cor,"blue",4)) return 0x10C;
	else if (!strncmp(cor,"fuchsia",7)) return 0x10D;
	else if (!strncmp(cor,"aqua",4)) return 0x10E;
	else if (!strncmp(cor,"white",5)) return 0x10F;
	else return 0x100;
}

/********************************************************************************
>>>> LOG_RECEIVE(char *comando,int ID,int type,FILE *log) <<<<
---------------------------------------------------------------------------------
*Função:	void LOG_RECEIVE(char *comando,int ID,int type,FILE *log)
*Descrição:	Escreve no arquivo de LOG informações proveniente dos terminais

*Entrada:	comando: nome do comando
		ID: ID do terminal que enviou a mensagem
		type: Tipo de terminal
		log: Descritor do arquivo
		
*Saída:		Nenhuma

*Data da Criação:	01/06/2006
*Modificações:

*Obs:

********************************************************************************/

void LOG_RECEIVE(char *comando,int ID,int type,FILE *log)
{
	int i = 0,POS = -1;
	
	// Mostra a tabela de conectados
	GetTabConec(&tabela);
	
	//Captura a hora atual para ser escrita no LOG
	hora_sist = time(NULL);
	hora = localtime(&hora_sist);
	
	// Procura o terminal na tabela (A procura é feita pelo ID e pelo TIPO)
	while (POS == -1)
	{
		if( (tabela.ID[i] == ID) && (tabela.type[i] == type) )
			POS = i;
		i++;
	}
	
	//Se encontra o terminal na tabela escreve no LOG
	if (POS != -1)
	{
	sprintf(linha_log,"%s;%s;%d/%d/%d;%d:%d\n",
		Inet_ntoa(tabela.IP[POS]),comando,hora->tm_mday,hora->tm_mon+1,hora->tm_year+1900,hora->tm_hour,hora->tm_min);
	
	fwrite(linha_log,strlen(linha_log),1,log);
	fflush(log);
	bzero(comando,sizeof(comando));
	}
}

/********************************************************************************
>>>> LOG(char *comando,int POS,FILE *log) <<<<
---------------------------------------------------------------------------------
*Função:	void LOG(char *comando,int POS,FILE *log)
*Descrição:	Escreve no arquivo de LOG informações proveniente do servidor

*Entrada:	comando: nome do comando
		POS: posição do terminal que receberá a mensagem na tabela de conectados
		log: Descritor do arquivo
		
*Saída:		Nenhuma

*Data da Criação:	01/06/2006
*Modificações:

*Obs:

********************************************************************************/

void LOG(char *comando,int POS,FILE *log)
{
	// Captura a hora no sistema para escrever no LOG
	hora_sist = time(NULL);
	hora = localtime(&hora_sist);
	
	// Monta a string para o LOG e escreve no arquivo
	sprintf(linha_log,"%s;%s;%d/%d/%d;%d:%d\n",
		Inet_ntoa(tabela.IP[POS]),comando,hora->tm_mday,hora->tm_mon+1,hora->tm_year+1900,hora->tm_hour,hora->tm_min);
	
	fwrite(linha_log,strlen(linha_log),1,log);
	fflush(log);
}

/********************************************************************************
>>>> void *Casadas(void *arg) <<<<
---------------------------------------------------------------------------------
*Função:	void *Casadas(void *arg)
*Descrição:	Thread que Trata as imagens casadas quando houverem

*Entrada:	Nenhuma
Saída:		Nenhuma

*Data da Criação:	01/06/2006
*Modificações:

*Obs:

********************************************************************************/
void *Casadas(void *arg)
{
	char imagem2[255];
	char imagem3[255];
	
	bzero(imagem2,255);
	bzero(imagem3,255);
	
	sprintf(imagem2,".//images//%s",ImagemCasada.produto.imagem2);
	sprintf(imagem3,".//images//%s",ImagemCasada.produto.imagem3);
	
	sleep(5);
	SendImage(ImagemCasada.ID,imagem2);
	
	if (ImagemCasada.produto.imagem3 != NULL)
	{
		sleep(5);
		SendImage(ImagemCasada.ID,imagem3);
	}
}

/********************************************************************************
>>>> void *Check_504(void* arg) <<<<
---------------------------------------------------------------------------------
*Função:	void *Check_504(void* arg)
*Descrição:	Thread que checará qualquer informação proveniente dos terminais(protocolo 504)

*Entrada:	arg: Descritor do arquivo de LOG (ver sobre threads)
Saída:		Nenhuma

*Data da Criação:	01/06/2006
*Modificações:

*Obs:

********************************************************************************/

void *Check_504(void* arg)
{
	// Recebe o argumento da thread
	FILE *log;
	log = (FILE *) arg;
	
	pthread_t casada;
	
	ARG_DISPLAY_TEXT texto1,texto2; // Variáveis que receberão os textos dos terminais TC504 (descrição e preço)
	char imagem1[100],imagem2[100],imagem3[100]; // Strings que receberão o nome das imagens
	char stringBonus[512]; // String que enviará o bonus para o LOG

	int ID = 0; // Variável que receberá o ID do terminal

	Menu_TC504 mqueue;
	
	int CMD; // Variável que receberá o comando do terminal (TC504)
	char Bar[256]; // Variável que envia para o LOG o código de barras encontrado (TC504)
	char track1[128],track2[128]; //Variável que recebe as trilhas dos cartões (TC504)
	char c; //Variável que recebe o caractere (TC504)
	
	int achou; // Variável que receberá se o código pesquisado foi encontrado
	Preco produto; // Variável que receberá as informações dos produtos (Barras) (ver tabelas.h)
	Bonus bonus; // Variável que recebe as informações dos bonus (cartão) (ver tabelas.h)
	
	while(1)
	{
		if( CheckCMD_504(&ID,&CMD) ) // Verifica que algum terminal TC504 enviou comando
		{
			switch (CMD)
			{
				case BARCODE: // Se enviou BARCODE
					ReceiveBAR(ID,Bar); // Recebe o código de barras
					Bar[strlen(Bar)-1] = '\0';
					produto = SeekBarCode(conn,Bar,&achou); // Procura na tabela o código
					if (achou == 1)
					{
						LOG_RECEIVE(Bar,ID,1,log); // Escreve no LOG que encontrou produto
						bzero(imagem1,sizeof(imagem1));

						bzero(&texto1,sizeof(ARG_DISPLAY_TEXT));
						bzero(&texto2,sizeof(ARG_DISPLAY_TEXT));
						
						sprintf(imagem1,".//images//%s",produto.imagem1);

						
						// Monta a estrutura para enviar o texto
						texto1.wPosX = (unsigned short)produto.Xnome;
						texto1.wPosY = (unsigned short)produto.Ynome;
						texto1.wSize = 1;
						texto1.wColor = ConvertCor(produto.cor);
						texto1.wBGColor = ConvertCor(produto.background);
						strcpy(texto1.sFont,"c:\\fonts\\LUCIDA16.BMP");
						strncpy(texto1.sText,produto.nome,strlen(produto.nome));
						
						texto2.wPosX = (unsigned short)produto.Xpreco;
						texto2.wPosY = (unsigned short)produto.Ypreco;
						texto2.wSize = 1;
						texto2.wColor = ConvertCor(produto.cor);
						texto2.wBGColor = ConvertCor(produto.background);
						strcpy(texto2.sFont,"c:\\fonts\\LUCIDA16.BMP");
						strcpy(texto2.sText,produto.preco);
						
						// Envia os textos e imagens
						LoadImage(ID,1);
						SendImage(ID,imagem1);
						SendText_504(ID,texto1);
						SendText_504(ID,texto2);
						
						ImagemCasada.produto = produto;
						ImagemCasada.ID = ID;
						
						if (produto.imagem2 != NULL)
							pthread_create(&casada,NULL,Casadas,NULL);
					}
					else
					{
						SendImage(ID,".//images//notfound.bmp"); // Caso não encontre o produto envia uma imagem
					}
					break;
				case MCR: // Se recebeu o código MCR (Cartão)
					ReceiveMCR(ID,track1,track2); // Recebe as trilhas do cartão lido
					bzero(stringBonus,sizeof(stringBonus));
					sprintf(stringBonus,"%s%s",track1,track2);
					bonus = SeekBonus(conn,stringBonus,&achou); // Procura na tabela o código
					
					if (achou == 1)
					{
						LOG_RECEIVE(stringBonus,ID,1,log); // Escreve no LOG o código do cartão lido
						bzero(imagem1,sizeof(imagem1));
						bzero(&texto1,sizeof(ARG_DISPLAY_TEXT));
						bzero(&texto2,sizeof(ARG_DISPLAY_TEXT));
						
						sprintf(imagem1,".//images//%s",bonus.imagem);
						
						// Monta os textos para enviar para o terminal
						texto1.wPosX = 0;
						texto1.wPosY = 195;
						texto1.wSize = 1;
						texto1.wColor = 0x10B;
						texto1.wBGColor = 0x100;
						strcpy(texto1.sFont,"c:\\fonts\\LUCIDA12.BMP");
						strncpy(texto1.sText,bonus.nome,strlen(bonus.nome));
						
						texto2.wPosX = 0;
						texto2.wPosY = 215;
						texto2.wSize = 1;
						texto2.wColor = 0x10F;
						texto2.wBGColor = 0x100;
						strcpy(texto2.sFont,"c:\\fonts\\LUCIDA12.BMP");
						strcpy(texto2.sText,bonus.bonus);
						
						// Envia para o terminal
						LoadImage(ID,2);
						SendImage(ID,imagem1);
						SendText_504(ID,texto1);
						SendText_504(ID,texto2);
					}
					else
					{
						SendImage(ID,".//images//errocartao.bmp");//se nao encontrar, envia para o terminal uma imagem
					}
					break;
				case CHAR: // Se  receber o comando CHAR
					ReceiveCHAR(ID,&c); // Recebe o caractere da tecla pressionada
					
						mqueue.type = 5;
						mqueue.comando = c;
						mqueue.identificador = ID;
						msgsnd(msgkey,&mqueue,5,0);

						ImagemCasada.produto = produto;
						ImagemCasada.ID = ID;
					break;
			}
		}
	}
}

/********************************************************************************
>>>> void *Check(void* arg) <<<<
---------------------------------------------------------------------------------
*Função:	void *Check(void* arg)
*Descrição:	Thread que checará qualquer informação proveniente dos terminais

*Entrada:	arg: Descritor do arquivo de LOG (ver sobre threads)
Saída:		Nenhuma

*Data da Criação:	01/06/2006
*Modificações:

*Obs:

********************************************************************************/

void *Check(void* arg)
{
	// Recebe o argumento da thread
	FILE *log;
	log = (FILE *) arg;
	
	char buffercmd[512]; // String que recebe os comandos dos Terminais (protocolo TC501)
	int ID = 0; // Variável que receberá o ID do terminal

	int achou; // Variável que receberá se o código pesquisado foi encontrado
	Preco produto; // Variável que receberá as informações dos produtos (Barras) (ver tabelas.h)

	while(1)
	{
		bzero(buffercmd,sizeof(buffercmd));
		ID = CheckCMD(buffercmd); // Se receber o comando do terminal (protocolo TC501)
		if (ID>=0)
			if ( buffercmd[0] == '#' )
			{
				if ( !strncmp(buffercmd,"#img_ok",6) || !strncmp(buffercmd,"#img_error",10) ||
				     !strncmp(buffercmd,"#restartsoft_ok",15) )
					bzero(buffercmd,sizeof(buffercmd));
				else
					{
					//procura pelo produto no banco de dados
					produto = SeekBarCode(conn,&buffercmd[1],&achou);
					if (achou == 1)
					{
						LOG_RECEIVE(&buffercmd[1],ID,0,log);
						SendProductPrice(ID,produto.nome,produto.preco);
					}
					else
						SendProductNotFound(ID);
					}
			}
			else
				//Se receber que algum terminal compatível com imagens se conectar envia a lista de propagandas
				SendImageList(ID);
	}
}

/********************************************************************************
>>>> void *Start(void *arg) <<<<
---------------------------------------------------------------------------------
*Função:	void *Start(void *arg)
*Descrição:	Thread que Inicia a lib (ver manual da libTCgertec.so)

*Entrada:	Nenhuma
Saída:		Nenhuma

*Data da Criação:	01/06/2006
*Modificações:

*Obs:

********************************************************************************/

void *Start(void *arg)
{
	//Processo especial para o tratamento da função StartServer (ver manual da lib)
	StartServer();
}

/********************************************************************************
>>>> main() <<<<
---------------------------------------------------------------------------------
*Função:	int main()
*Descrição:	Função Principal. Inicia as threads, o Message Queue, o arquivo de LOG
		e checa mensagens provenientes do servidor

*Entrada:	Nenhuma
Saída:		Nenhuma

*Data da Criação:	01/06/2006
*Modificações:

*Obs:

********************************************************************************/

int main()
{ 
	// Cria as threads
	pthread_t comandos; // thread para o receber os comandos
	pthread_t comandos_504;
	pthread_t conexao; // thread para controlar a conexão dos terminais
	pthread_t menu; // threaque controla o menu do TC 504
	
	int POS; //Recebe a posição do terminal
	int arg; // Recebe os argumentos para algumas funções
	
	Arquivo file; // Recebe informações para o envio de arquivos (TC504)
	
	Texto texto;
	ARG_DISPLAY_TEXT texto_504;
	Imagem image;
	
	UPDConfig upd;
	PARAMConfig param;
	Config conf;
	ARG_SETUP_TCP setup;
	
	MSG_DATA msg; // Variável que recebe as mensagens
	
	FILE *log; // Descritor do arquivo de log
	
	// Recebe informações do dia e da hora para a criação e abertura do arquivo de LOG
	hora_sist = time(NULL);
	hora = localtime(&hora_sist);
	char nomeFile[50];
	
	int msgkey;
	msgkey=msgget(MSG_KEY,PERM|IPC_CREAT); // Inicializa o Message Queue
	
	//Inicia a conexao com o postgre
	conn = PQsetdbLogin(NULL, NULL , NULL, NULL, PGDBNAME, PGUSER, PGPWD);
	
	PQexec(conn, "BEGIN");
	
	if(!PQexec(conn, "BEGIN"))
	{
		printf("\nNao foi posivel conectar com o banco de dados\n");
		exit(0);
	}
	
	if (msgkey != -1)
	{
		sprintf(nomeFile,".//log//log_%d_%d.txt",hora->tm_mon+1,hora->tm_year+1900);
		log = fopen(nomeFile,"a+"); // Abre ou cria o arquivo de LOG
		
		// Inicia as threads
		pthread_create(&conexao,NULL,Start,NULL);
		pthread_create(&comandos,NULL,Check,(void*)log);
		pthread_create(&comandos_504,NULL,Check_504,(void*)log);
		pthread_create(&menu,NULL,Menu_504,NULL);
		
		while (1)
		{
			if ( msgrcv(msgkey,&msg,MSG_LENGHT,1,0) != -1) // verifica e recebe mensagens do servidor
			{
				POS = msg.ID; //pega o ID que receberá a mensagem
				
				switch (msg.CMD)
				{
					case STOP: //Se a mensagem for para parar o servidor
						//Recebe a hora atual
						hora_sist = time(NULL);
						hora = localtime(&hora_sist);
						
						//Monta a string para o LOG
						sprintf(linha_log,"0;%s;%d/%d/%d;%d:%d\n",
						"STOP_SERVER",hora->tm_mday,hora->tm_mon+1,hora->tm_year+1900,hora->tm_hour,hora->tm_min);
						
						//Escreve no LOG
						fwrite(linha_log,strlen(linha_log),1,log);
						fclose(log);
						PQfinish(conn);
						exit(0);
						break;
					case SEND_TEXT://Se a mensagem for para enviar texto
						LOG("SEND_TEXT",POS,log); // Escreve no LOG
						if (tabela.type[POS] == 0) //Verifica o tipo de terminal
						{
							//Monta a estrutura e envia para o terminal
							memmove((char*)&texto,msg.data,sizeof(Texto));
							SendText(tabela.ID[POS],texto.linha1,texto.linha2,texto.tempo);
						}
						else
						{
							//Monta a estrutura e envia para o terminal
							memmove((char*)&texto_504,msg.data,sizeof(ARG_DISPLAY_TEXT));
							SendText_504(tabela.ID[POS],texto_504);
						}
						break;
					case SEND_IMAGE: //Se for para enviar imagem
						LOG("SEND_IMAGE",POS,log); // Escreve no LOG
						if (tabela.type[POS] == 0) // Verifica o tipo de terminal
						{
							//Monta a estrutura e envia para o terminal
							memmove((char*)&image,msg.data,sizeof(Imagem));
							SendImageFromFile(tabela.ID[POS],image.filename,128,64,8,0,0,image.tempo);
						}
						else
						{
							//Monta a estrutura e envia para o terminal
							memmove((char*)&image,msg.data,sizeof(Imagem));
							SendImage(tabela.ID[POS],image.filename);
						}
						break;
					case GET_CONFIG:
						//Prepara a mensagem para enviar para o servidor
						msg.type = 2;
						msg.ID = POS;
						msg.CMD = GET_CONFIG;
						if (tabela.type[POS] == 0) //Verifica o tipo de terminal
						{
							//Envia o pedido para o terminal
							SendGetConfig(tabela.ID[POS]);
							SendGetUpdConfig(tabela.ID[POS]);
							SendGetParamConfig(tabela.ID[POS]);
							sleep(1); // Espera 1 segundo
							//Recebe do terminal as configurações
							GetConfig(tabela.ID[POS],&conf);
							GetUpdConfig(tabela.ID[POS],&upd);
							GetParamConfig(tabela.ID[POS],&param);
							
							//monta a mensagem
							memmove(msg.data,(char*)&conf,sizeof(Config));
							memmove(&msg.data[sizeof(Config)],(char*)&upd,sizeof(UPDConfig));
							memmove(&msg.data[sizeof(Config)+sizeof(UPDConfig)],
								(char*)&param,sizeof(PARAMConfig));
						}
						else
						{
							SendGetSetup_504(tabela.ID[POS]);//Faz o pedido para o terminal
							sleep(1);//Espera 1 segundo
							GetSetup_504(tabela.ID[POS],&setup);//Recebe a configuração de terminal
							memmove(msg.data,(char*)&setup,sizeof(ARG_SETUP_TCP));//Monta a mensagem
						}
						msgsnd(msgkey,&msg,MSG_LENGHT,0);//Envia para o servidor as informações
						break;
					case S_LEC:
						LOG("SET_LEC",POS,log);//Escreve no LOG
						memmove(&arg,msg.data,sizeof(int)); //recebe o argumento
						SendSetLec(tabela.ID[POS],arg);//envia a alteração para o terminal
						break;
					case S_TIME:
						LOG("SET_TIME",POS,log);//Escreve no LOG
						memmove(&arg,msg.data,sizeof(int));//recebe o argumento
						SetTime(tabela.ID[POS],arg);//envia a alteração para o terminal
						break;
					case S_KEY:
						LOG("SET_KEY",POS,log);//Escreve no LOG
						memmove(&arg,msg.data,sizeof(int));//recebe o argumento
						SetEnableKey(tabela.ID[POS],arg);//envia a alteração para o terminal
						break;
					case RESTART:
						LOG("RESTART",POS,log); //Escreve no LOG
						switch (tabela.type[POS]) //Verifica o tipo de terminal
						{
							case 0:
								SendRestart(tabela.ID[POS]);//Envia o comando para o terminal
								break;
							case 1:
								Restart_504(tabela.ID[POS]);//Envia o comando para o terminal
								break;
						}
						break;
					case CLEAR:
						LOG("CLEAR_DISP",POS,log);//Escreve no LOG
						memmove(&arg,msg.data,sizeof(int));//recebe o argumento
						ClearDisp(tabela.ID[POS],arg);//Envia o comando para o terminal
						break;
					case START_LOOP:
						LOG("START_LOOP",POS,log);//Escreve no LOG
						StartLoop(tabela.ID[POS]);//Envia o comando para o terminal
						break;
					case STOP_LOOP:
						LOG("STOP_LOOP",POS,log);//Escreve no LOG
						StopLoop(tabela.ID[POS]);//Envia o comando para o terminal
						break;
					case SEND_FILE:
						LOG("SEND_FILE",POS,log);//Escreve no LOG
						memmove(&file,msg.data,sizeof(Arquivo));//recebe o nome do arquivo de origem e destino
						SendFile(tabela.ID[POS],file.origem,file.destino);//Envia o comando para o terminal
						break;
					case RELOAD_ADV:
						LOG("RELOAD_ADV",POS,log);//Escreve no LOG
						ReloadADV(tabela.ID[POS]);//Envia o comando para o terminal
						break;
					case DELETE_ADV:
						LOG("DELETE_ADV",POS,log);//Escreve no LOG
						DeleteADV(tabela.ID[POS]);//Envia o comando para o terminal
						break;
					case RELOAD_PRE:
						LOG("RELOAD_PREIMAGE",POS,log);//Escreve no LOG
						ReloadPreImage(tabela.ID[POS]);//Envia o comando para o terminal
						break;
					case DELETE_PRE:
						LOG("DELETE_PREIMAGE",POS,log);//Escreve no LOG
						DeletePreImage(tabela.ID[POS]);//Envia o comando para o terminal
						break;
					case SEND_CONFIG:
						LOG("SEND_CONFIG",POS,log);//Escreve no LOG
						memmove((char*)&conf,msg.data,sizeof(Config));//monta a estrutura para enviar
						SendConfig(tabela.ID[POS],conf);//Envia o comando para o terminal
						break;
					case SEND_UPD:
						LOG("SEND_UPD",POS,log);//Escreve no LOG
						memmove((char*)&upd,msg.data,sizeof(UPDConfig));//monta a estrutura para enviar
						SendUpdConfig(tabela.ID[POS],upd);//Envia o comando para o terminal
						break;
					case SEND_PARAM:
						LOG("SEND_PARAM",POS,log);//Escreve no LOG
						memmove((char*)&param,msg.data,sizeof(PARAMConfig));//monta a estrutura para enviar
						SendParamConfig(tabela.ID[POS],param);//Envia o comando para o terminal
						break;
					case SEND_SETUP:
						LOG("SEND_SETUP",POS,log);//Escreve no LOG
						memmove((char*)&setup,msg.data,sizeof(ARG_SETUP_TCP));//monta a estrutura para enviar
						SendSetup_504(tabela.ID[POS],setup);//Envia o comando para o terminal
						break;
					case TAB_CONEC:
						GetTabConec(&tabela);//Recebe da lib a tabela de terminais conectados
						memmove(&msg.data,(char*)&tabela,sizeof(tabela));//monta a mensagem
						msg.type = 2;
						msg.ID = 0;
						msg.CMD = TAB_CONEC;
						msgsnd(msgkey,&msg,MSG_LENGHT,0); //Envia para o terminal
						break;
				}
			}
		}
	}
}
