Blog


View CommentsView Comments

Tarifador em C++

14.Jul.2006 Tags: trampo

Há algum tempo atrás, desenvolvi em C++ um tarifador simples para PABX com saída serial. Com ele, você loga em um banco mysql todas as ligações que sua central faz e recebe. Espero que gostem. Só por curiosidade ele ta rodando até hoje se problemas lá :).

tarifador-v2.cpp

/*
Author: Wagner Sartori Junior <wsartori@uol.com.br>
Revision: $Id: tarifador-v2.cpp,v 2.0 2004/11/04 17:38:51 greg Exp greg $
GPL License Compatible
*/

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <getopt.h>

#include <termios.h>
#include <mysql++/mysql++.h>

using namespace std;

char __revision__[] = "$Id: tarifador.cpp,v 2.0 2004/11/04 17:38:51 greg Exp greg $";

/* Override with -f option */
#define DEFAULT_CONFIG_FILE "/etc/tarifador.conf"
/* Modify with -v/-q options */
static int VERBOSE = 0;

/* Default */
#define VERSAO "2.0"

#define _POSIX_SOURCE 1

#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

static char * USAGE =
   "usage: tarifador [options]\n"
   "\n"
   "options:\n"
   "  -h, --help           this help screen\n"
   "  -d, --daemon         detach and run as a daemon process\n"
   "  -v                   increase verbosity by 1\n"
   "  -q, --quiet          run with no output\n"
   "  -fFILE, --file=FILE  read config from FILE\n"
   "                       (default: " DEFAULT_CONFIG_FILE ")\n"
   "\n"
   "-d implies -q; non-zero verbosity disables -d\n";

/* DataBase Variables */
char *dbserver;
char *database;
char *username;
char *password;
/* Serial Variables */
char *device;
char *baudrate;

static char * munge_line (char * line) {
    char * c;

    c = line+strlen(line)-1;
    if (*c == '\n') *c = (char) 0;

    c = strchr(line, '#');
    if (c != NULL) *c = (char) 0;
    else c = line + strlen(line);

    c--;
    while (c > line && isspace(*c)) {
        *c = (char) 0;
        c--;
    }
    c++;
    if (c == line) return NULL;
    else return line;
}

static void read_config(char * filename) {
    char buf[1024];
    FILE * file;
    char * param;
    char * resul;
    int i;
    int linenum;

    file = fopen(filename, "r");
    if (!file) {
        fprintf(stderr, USAGE);
        if (VERBOSE > 0) {
            printf("Erro abrindo arquivo de configura��o %s\n", filename);
            exit(1);
        }
    }
    linenum = 0;

    while (!feof(file)) {
        char * line;

        if (!fgets(buf, 1024, file)) {
            break;
        }
        linenum++;

        line = munge_line(buf);
        if (line == NULL) continue;

        if (VERBOSE > 1) {
            printf("valid configfile line(%d): %s\n", linenum, line);
        }

        param = strtok(line, "=");
        resul = strtok(NULL, "=");

        if (strcmp(param, "dbserver") == 0) {
            dbserver = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
            strcpy(dbserver, resul);
        } else if (strcmp(param, "database") == 0) {
            database = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
            strcpy(database, resul);
        } else if (strcmp(param, "username") == 0) {
            username = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
            strcpy(username, resul);
        } else if (strcmp(param, "password") == 0) {
            password = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
            strcpy(password, resul);
        } else if (strcmp(param, "device") == 0) {
            device = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
            strcpy(device, resul);
        } else if (strcmp(param, "baudrate") == 0) {
            baudrate = (char *)malloc(sizeof(char *) * (strlen(resul) + 1));
            strcpy(baudrate, resul);
        }
    }
    fclose(file);
}

static void daemonize (void) {
    pid_t pid;

    pid = fork();
    if (pid) {
        printf("parent process exiting\n");
        exit(0);
    } else {
        printf("child process detaching\n");
        setsid();
        chdir("/");
        close(0); open("/dev/null", O_RDONLY);
        close(1); open("/dev/null", O_WRONLY);
        close(2); open("/dev/null", O_WRONLY);
    }
}

MYSQL *pConnection;

int main (int argc, char *argv[]) {
    int fd,c, res;
    struct termios oldtio,newtio;
    char buf[255];
    string Query;
    string linha;

    int daemon = 0;
    char * config_file = DEFAULT_CONFIG_FILE;

    char * optstring = "dvqhf:";
    struct option longopts[] = {
        { "daemon", no_argument, NULL, 'd' },
        { "quiet", no_argument, NULL, 'q' },
        { "help", no_argument, NULL, 'h' },
        { "file", required_argument, NULL, 'f' },
        { NULL, 0, NULL, 0 }
    };
    int opt;
    int longindex = 0;
    opt = getopt_long(argc, argv, optstring, longopts, &longindex);
    while (opt != -1) {
        if (opt == 'd') {
            daemon = 1;
            VERBOSE = 0;
        } else if (opt == 'v') {
            VERBOSE++;
            daemon = 0;
        } else if (opt == 'q') {
            VERBOSE = 0;
        } else if (opt == 'f') {
            config_file = strdup(optarg);
        } else if (opt == 'h' || opt == '?') {
            fprintf(stderr, USAGE);
            exit(1);
        }
        opt = getopt_long(argc, argv, optstring, longopts, &longindex);
    }

    read_config(config_file);
    if (VERBOSE > 0) {
        printf("Var: device=%s\n", device);
        printf("Var: baudrate=%s\n", baudrate);
        printf("Var: dbserver=%s\n", dbserver);
        printf("Var: dbserver=%s\n", database);
        printf("Var: dbserver=%s\n", username);
        printf("Var: dbserver=%s\n", password);
    }

    fd = open(device, O_RDONLY | O_NOCTTY );
    if (fd < 0) {
        printf("Erro na abertura do device (%s)\n", device);
        exit(1);
    }
    tcgetattr(fd,&oldtio);
    bzero(&newtio, sizeof(newtio));

    if (strcmp(baudrate, "2400") == 0) {
        newtio.c_cflag = B2400 | CRTSCTS | CS8 | CLOCAL | CREAD;
    } else if (strcmp(baudrate, "4800") == 0) {
        newtio.c_cflag = B4800 | CRTSCTS | CS8 | CLOCAL | CREAD;
    } else if (strcmp(baudrate, "4800") == 0) {
        newtio.c_cflag = B4800 | CRTSCTS | CS8 | CLOCAL | CREAD;
    } else if (strcmp(baudrate, "9600") == 0) {
        newtio.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
    } else if (strcmp(baudrate, "19200") == 0) {
        newtio.c_cflag = B19200 | CRTSCTS | CS8 | CLOCAL | CREAD;
    } else if (strcmp(baudrate, "38400") == 0) {
        newtio.c_cflag = B38400 | CRTSCTS | CS8 | CLOCAL | CREAD;
    } else {
        printf("Baudrate (%s) not supported.", baudrate);
        exit(1);
    }

    newtio.c_iflag = IGNPAR | ICRNL;
    newtio.c_oflag = 0;
    newtio.c_lflag = ICANON;

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtio);

    if (daemon) {
        daemonize();
        syslog(LOG_NOTICE, "Daemon started");
    }

    while (STOP==FALSE) {
        res = read(fd,buf,255);
        buf[res]=0;

        if (res > 30) {
            linha.empty();
            Query.empty();
            linha = buf;
            if (VERBOSE > 0) {
                cout<<"Linha:"<<linha<<endl;
                cout<<"Data:"<<linha.substr(0,8)<<endl;
                cout<<"Hora:"<<linha.substr(8,8)<<endl;
                cout<<"Linha:"<<linha.substr(17,1)<<endl;
                cout<<"Ramal:"<<linha.substr(21,2)<<endl;
                cout<<"Duracao:"<<linha.substr(28,8)<<endl;
                cout<<"Destino:"<<linha.substr(36,32)<<endl;
                cout<<"Tipo:"<<linha.substr(68,1)<<endl;
                cout<<"================================================"<<endl;
            }
            if (linha.substr(68,1) == "2") {
                pConnection = mysql_init(NULL);
                if(!pConnection) {
                    if (daemon) syslog(LOG_ERR, "mysql_init error");
                    printf("mysql_init error\n");
                    exit(1);
                }
                if(mysql_real_connect(pConnection, dbserver, username, password, database,0,NULL,0) == NULL) {
                    if (daemon) syslog(LOG_ERR, "mysql pConnection error");
                    printf("mysql pConnection error\n");
                    exit(1);
                }
                Query = "INSERT INTO pabx_ligacoes (lin_id, ram_ramal, lig_data, lig_duracao, lig_destino) VALUES ('" + linha.substr(17,1) + "', '" + linha.substr(21,2) + "', '20" + linha.substr(6,2) + "-" + linha.substr(3,2) + "-" + linha.substr(0,2)  + " " + linha.substr(8,8) + "', '" + linha.substr(28,8) + "', '" + linha.substr(36,32) + "');";
                if(mysql_query(pConnection,Query.c_str()) != 0) {
                    if (daemon) syslog(LOG_ERR, "Query (%s) error\n", Query.c_str());
                    printf("Query (%s) error\n", Query.c_str());
                    exit(1);
                }
                mysql_close(pConnection);
            }
        }
        if (buf[0]=='z') STOP=TRUE;
    }
    tcsetattr(fd,TCSANOW,&oldtio);

    return 0;
}

tarifador.conf

# Configuracoes do Tarifador
# device = device serial para leitura das tarifas
# dbserver = hostname/ip do servidor de banco de dados
# database = nome do banco de dados
# username = nome do usuario para acesso ao banco de dados
# password = senha de acesso ao banco de dados
device=/dev/ttyS0
baudrate=2400

dbserver=server01
database=dbname
username=dbuser
password=dbpass

sql=INSERT INTO pabx_ligacoes (lin_id, ram_ramal, lig_data, lig_duracao, lig_destino) VALUES (?, ?, ?, ?, ?);

tarifador.sql

--
-- Estrutura da tabela `pabx_ligacoes`
--

CREATE TABLE `pabx_ligacoes` (
  `lig_id` int(11) NOT NULL auto_increment,
  `lin_id` int(11) NOT NULL default '0',
  `ram_ramal` int(2) NOT NULL default '0',
  `lig_data` datetime NOT NULL default '0000-00-00 00:00:00',
  `lig_duracao` time NOT NULL default '00:00:00',
  `lig_destino` varchar(32) NOT NULL default '',
  PRIMARY KEY  (`lig_id`),
  KEY `lin_id` (`lin_id`),
  KEY `ram_ramal` (`ram_ramal`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Tabela de Ligacoes Telefonicas' AUTO_INCREMENT=0;

-- --------------------------------------------------------

--
-- Estrutura da tabela `pabx_linhas`
--

CREATE TABLE `pabx_linhas` (
  `lin_id` int(11) NOT NULL auto_increment,
  `lin_linha` int(8) NOT NULL default '0',
  `lin_celular` int(11) NOT NULL default '0',
  PRIMARY KEY  (`lin_id`),
  UNIQUE KEY `lin_linha` (`lin_linha`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Tabela de Linhas Telefonicas' AUTO_INCREMENT=0 ;

-- --------------------------------------------------------

--
-- Estrutura da tabela `pabx_ramais`
--

CREATE TABLE `pabx_ramais` (
  `ram_ramal` int(2) NOT NULL default '0',
  `fun_id` int(11) default NULL,
  PRIMARY KEY  (`ram_ramal`),
  KEY `fun_id` (`fun_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Tabela de Ramais Telefonicos';

--
-- Constraints for table `pabx_ligacoes`
--
--ALTER TABLE `pabx_ligacoes`
--  ADD CONSTRAINT `pabx_ligacoes_ibfk_1` FOREIGN KEY (`lin_id`) REFERENCES `pabx_linhas` (`lin_id`),
--  ADD CONSTRAINT `pabx_ligacoes_ibfk_2` FOREIGN KEY (`ram_ramal`) REFERENCES `pabx_ramais` (`ram_ramal`);

--
-- Constraints for table `pabx_ramais`
--
--ALTER TABLE `pabx_ramais`
--  ADD CONSTRAINT `pabx_ramais_ibfk_1` FOREIGN KEY (`fun_id`) REFERENCES `funcionarios` (`fun_id`);

blog comments powered by Disqus