Thursday, December 13, 2012

Caller ID Project - part six

I got the LCD code integrated with the Caller ID app and began integration testing of the Version 0.9 code this evening.  Looking good!

Next steps

  • Complete integration testing (just let it run for a couple of days...)
  • Wire everything together and do the final testing


























Here's the code with the LCD routines integrated (see Phil Bambridge's blog for complete details on the LCD routines.)

/*
 *    main.c
 *
 *    M. Amos
 *    (LCD code by Phil Bambridge)
 *
 *      Listens for Caller ID info from USB modem, decodes it, writes it to the console, formats the info onto a
 *      web page and writes the caller name and number to an LCD display
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>

#include <arpa/inet.h>
#include <net/if.h>

#include <sys/sysinfo.h>
#include <sys/vfs.h>

#include <time.h>

#include <unistd.h>

#include <signal.h>

#include "lcd.h"

struct lcdmodule module;

int get_fld(char *, int);
int hex_to_ascii(int, int);
int hex_to_int(int);
int write_web_page(char *, char *, char *);

int main(int argc, char **argv) {
    struct lcdmodule module2;
    
    // Variables for Caller ID
    int  msg_len;
    int  msg_end;
    long fld_type;
    long fld_len;
    char fld_val [64] = "";
    int  str_ptr;
    char str_date_time [20] = "  /     :  ";
    char str_nbr [20] = "   -   -    ";
    char str_nam [64] = "";
    char str_input [256] = "\0";
    
    // Here we create and initialise two LCD modules.
    // The arguments are, in order, EN, RS, D4, D5, D6, D7.
    module = lcdInit(17, 18, 22, 23, 24, 25);
    module2 = lcdInit(21, 18, 22, 23, 24, 25);
    
    // Send configuration strings to modem
    // On Raspberry Pi, leaving echo on and status messages on causes problems with some kind of "loop back" on the
    // /dev/ttyACM0 port.  So, we have to turn them off.
    FILE *out_file;
    out_file = fopen("/dev/ttyACM0", "w");
    if (out_file == NULL) {
        fprintf(stderr, "Can't open output file\n");
    }
    fprintf(out_file,"ATE0");                                 // Turn off echo
    fprintf(out_file,"%c%c",0x0d,0x0a);
    fprintf(out_file,"ATQ1");                                 // Turn off status messages
    fprintf(out_file,"%c%c",0x0d,0x0a);
    fprintf(out_file,"AT#CID=2");                             // Turn on unformatted Caller ID
    fprintf(out_file,"%c%c",0x0d,0x0a);
    fclose(out_file);
    
    // Open modem for input
    FILE *in_file;
    in_file = fopen("/dev/ttyACM0", "r");
    if (in_file == NULL) {
        fprintf(stderr, "Can't open input file\n");
    }
    
    // display splash screen on LCD
    gotoXy(module, 0,0);
    prints(module, "Caller ID       ");
    gotoXy(module, 0,1);
    prints(module, "Version 1.0     ");
    
    while (fgets(str_input, 250, in_file) != NULL ){            // Check to see if there's input available
        if(strstr(str_input,"MESG=80")){                        // Check to see if we received a CID message
            
            // Get Message Length
            str_ptr = 7;                                        // position pointer to point at the message length field
            msg_len = get_fld(str_input, str_ptr);
            msg_end = (msg_len * 2) + 8;                        //  Adjust for two bytes per hexx digit, plus "header" + length
            str_ptr+=2;                                         // position pointer to point to the start of first field
            
            // Parse message while there's still input to be had
            while (str_ptr < msg_end){
                fld_type = get_fld(str_input, str_ptr);         // Get Field Type
                str_ptr+=2;
                
                fld_len = get_fld(str_input, str_ptr);          // Get Field Length
                str_ptr+=2;
                fld_len = fld_len * 2;
                
                int j = 0;                                      // Get Field Value
                int i = 0;
                for (i=str_ptr; i< fld_len + str_ptr - 1; i+=2){
                    fld_val[j++] = hex_to_ascii(str_input[i], str_input[i+1]);
                    fld_val[j] = '\0';
                }
                
                str_ptr += fld_len;                             // decode field values using field type
                switch (fld_type) {
                    case 1: {
                        strcpy(str_date_time, fld_val);
                    } break;
                    case 2: {
                        strcpy(str_nbr, fld_val);
                    } break;
                    case 4: {
                        strcpy(str_nbr, "No Number");
                    } break;
                    case 7: {
                        strcpy(str_nam, fld_val);
                    } break;
                    case 8: {
                        strcpy(str_nam, "No Name");
                    } break;
                }
            }
            // end while parse message
            
            // Echo date, number and name to console
            printf("Date: %s\n",str_date_time);
            printf("Number: %s\n",str_nbr);
            printf("Name: %s\n",str_nam);
            
            // Create the HTML for the web page displaying the Caller ID info
            write_web_page(str_date_time, str_nbr, str_nam);
            
            // Display Caller ID info on LCD
            gotoXy(module, 0,0);
            prints(module,str_nbr);
            prints(module,"                ");
            gotoXy(module, 0,1);
            prints(module,str_nam);
            prints(module,"                ");
        }
        else {                                                  // else extraneous input (i.e. not MESG=...)
            printf("%s\n",str_input);                           // shouldn't be any - we turned off echo and status messages
        }
    }                                                           // end while fgets
    
    
    return 0;
} // main

// Create HTML for web page to display the Caller ID info:
int write_web_page(char *str_date_time, char *str_nbr, char *str_nam){
    FILE *web_file;
    web_file = fopen("/var/www/index.html", "w");  // for Raspberry Pi use /var/www/index.html
    if (web_file == NULL) {
        fprintf(stderr, "Can't open web page output file\n");
    }
    // format the date and time and output a record to the web server.
    fprintf(web_file,"<html><body>\n");
    fprintf(web_file,"<p><b>Caller ID</b></p>\n");
    fprintf(web_file,"<p>Date: %c%c-%c%c</p>\n",str_date_time[0], str_date_time[1], str_date_time[2], str_date_time[3]);
    fprintf(web_file,"<p>Time: %c%c:%c%c</p>\n",str_date_time[4], str_date_time[5], str_date_time[6], str_date_time[7]);
    fprintf(web_file,"<p>Number: %s</p>\n", str_nbr);
    fprintf(web_file,"<p>Name: %s</p>\n", str_nam);
    fprintf(web_file,"</body></html>\n");
    
    fclose(web_file);
    
    return 0;
}

// Convert input hex characters to integer 
int hex_to_int(int c){
    int first = c / 16 - 3;
    int second = c % 16;
    int result = first * 10 + second;
    if(result > 9) result--;
    return result;
}

int hex_to_ascii(int c, int d){
    int high = hex_to_int(c) * 16;
    int low = hex_to_int(d);
    return high+low;
}

// Convert two characters from the incoming string and return as an integer
int get_fld(char *fldBuf, int bufPtr){
    char fldStr[3] = "00";
    char *p;
    fldStr[0] = fldBuf[bufPtr++];
    fldStr[1] = fldBuf[bufPtr++];
    return (int) strtoul(fldStr, &p, 16);
}

No comments:

Post a Comment