buffer, pointers, and other str-related stuff

22 Jun 2011

Hi people.

I'm trying to write a program that reads the incoming messages on a SIM900 gsm modem. First of, it works. I can read the interrupt-buffer i wrote. But: I can't work out how to use strstr, strncpy and those. I've tried to look all over the web, but I can't seem to find the solution. Can anybody POINT me to the right direction? Serial interrupt, for now this, maybe serialbuffered later.

char inputbuffer[512];

void serialinterrupt() {                    // Interrupt routine whenever serial receive
    if (SIM900.readable()) {
        inputbuffer[i]=SIM900.getc();            // copy to buffer
        pc.putc(inputbuffer[i]);
        i++;
    }
    // Look for +CMTI: "SM",1
    L2 = !L2;			
    return;
}

char phonenum[8];
SIM900.printf("AT+CMGR=1\r");
wait_ms(500);
char *phonenumber = phonenum; // maybe this is wrong?
phonenumber = strstr(inputbuffer,"+45");  // point to location of +45 - Denmark country-code
strncpy(phonenumber,phonenumber+3,8); // copy from after +45 into phonenumber 
for(int hej=0; hej > 8; hej++){       // Only 0's in phonenum.
pc.printf("%c",phonenum[hej]);
}		

Am I doing it completely wrong?

Thanks in advance. Lerche

22 Jun 2011

char *phonenumber = phonenum; // maybe this is wrong?
---   phonenumber becomes an alias of phonenum (the string is not copied), but it is useless because...
phonenumber = strstr(inputbuffer,"+45");  // point to location of +45 - Denmark country-code
...overwrites the phonenumber pointer (possibly with 0)
strncpy(phonenumber,phonenumber+3,8); // copy from after +45 into phonenumber 
---  I would change this to: strncpy(phonenum,phonenumber+3,8); // copy from after +45 into phonenumber 
---  and test first that phonenumber is not 0

You probably mean : for(int hej=0; hej < 8; hej++){       
22 Jun 2011

Thanks for the reply.

I tried the code, but the strstr function never found a phone number. I returned 0. And as I follow the inputbuffer on my computer terminal, it sure does get into the buffer array. Hmm, wonder if that strstr doesn't work.....

22 Jun 2011

It's likely that inputbuffer isn't being filled how you are expecting it to be filled even though the pc.putc(inputbuffer[i]); is leading you to think it is. Can you publish the entire program so we can have a proper look and see as your snippets don't reveal enough to see for sure. Also, if you could paste from your terminal the actual string that is sent into a <quote> here on this forum thread that would also help.

22 Jun 2011

It's unlikely that strstr doesn't work, I would rather think that inputbuffer does not contain +45 at the time you check it. Printf("%s" inputbuffer) right before you check.

22 Jun 2011

You can try the suggested Printf("%s" inputbuffer) above, but only if you are brave. printf()ing vars is a useful debug tool. But I suspect that your construction of inputbuffer is not correct. If that is the case I would conclude there's no null terminator on inputbuffer for %s to end at (or in fact for strstr to end at). Using unterminated C strings is a sure fire way to send your program into, err, an unstable condition.

Like I said, without seeing the whole program it's impossible to tell.

22 Jun 2011

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

Project: SIM900 remote relay
Author: Christian Lerche - Lerchetech.dk
Date: 10-06-2011
Notes:
LPC1768 on custom board.

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

//------------------------------Include--------------------------------------------
#include "mbed.h"                           // Standard include 
#include "platform.h"                       // include platform for custom board
#include <string>
using namespace std;
//#define PROTOPLATFORM                       // use of LPC_pinnames activated
//------------------------------Input/Output---------------------------------------
DigitalOut myled(LED1);                     // Just digitalout
Serial SIM900(p9, p10);                    // TX RX
Serial pc(USBTX, USBRX);
DigitalOut PWRKEY(p11);                    // High to turn on module
DigitalOut Relay(LED4);                     //Indicate relay
DigitalOut L3(LED3);
DigitalOut L2(LED2);

char lookup[] = "LTR 8606";
char * buffer;
char inputbuffer[512];
int i = 0;
int received = 0;
int u = 0;
int newsmsrec = 0;
char on[] = "Lt1";
char off[] = "Lt0";
char * pch;
char * end;
char phonenum[8];
char textbuf[160];
char * str;
int phonenumcheck = 0;

//------------------------------Interrupts-----------------------------------------
void serialinterrupt() {                    // Interrupt routine whenever serial receive
    if (SIM900.readable()) {
        inputbuffer[i]=SIM900.getc();            // copy to buffer
        pc.putc(inputbuffer[i]);
        i++;
    }
    // Look for +CMTI: "SM",1
    L2 = !L2;			
    return;
}

void turnon() {                             // Sequence to turn on SIM900
    PWRKEY = 1;
    wait_ms(1200);
    PWRKEY = 0;
}

void setup() {
    turnon();
    wait(5);
    SIM900.printf("ATE0\r\0");                  // SIM900 won't return every typed char
	wait_ms(100);
	LPC_UART0->FCR |= 0x06;                 // Flush the serial buffer.
	SIM900.printf("AT+CMGF=1\r\0");
	wait_ms(100);
	LPC_UART0->FCR |= 0x06;                 // Flush the serial buffer.	
	SIM900.printf("AT+CMGDA=\"DEL ALL\"\r\0");
	wait_ms(100);
    LPC_UART0->FCR |= 0x06;                 // Flush the serial buffer.	
	memset(inputbuffer, '0', 512);
    SIM900.attach(&serialinterrupt);        // Jump to serialinterrupt when receiving byte
    wait(15);                               // Wait for SIM900 to get ready
	PWRKEY = 0;
}

void sendsms(string sms) {

}
 /*
char compare_string(char const *compare_string){
	char *ch;
	char ret_val
}

*/
void readsms(char place, char *phone, char *text, int max_length) {
	if(place == 0){
		return;
	}
    pc.printf("readsms started\r\n");
	SIM900.printf("AT+CMGR=%c\r",place);
	pc.printf("1\r\n");
	wait_ms(500);
	pc.printf("%d\r\n",inputbuffer);			// print the decimal value of inputbuffer.
	/*
	for(int o = 0; o > 128; o++){
		switch(inputbuffer[o]){
			case('+'):
				switch(inputbuffer[o+1]){
					case('4'):
						switch(inputbuffer[o+2]){
							case('5'):
								phonenumcheck = 1;
								break;
							default:
								break;
						}
					default:
						break;	
				}
			default:
				break;
		}
	}
	*/
	phone = strstr(inputbuffer,"+45");	  		// locate +45 in inputbuffer, next copy the text
	pc.printf("3\r\n");
	u = phone-inputbuffer;
	pc.printf("4\r\n");
	str = strncpy(phonenum,inputbuffer+(u+3),8);	  // str = char *
	pc.printf("%c\r\n",str); // or str?!?!?
	text = strstr(inputbuffer,"LTR");				  // text is array. Maybe char*?
	pc.printf("6\r\n");
	u = text-inputbuffer;
	pc.printf("7\r\n");
	strncpy(textbuf,inputbuffer+u,160);
	pc.printf("8\r\n");
	pc.printf("Copy phonenumber to phonenum buffer\r\n");
	for(int telefonnummer = 0; telefonnummer < 8; telefonnummer++){
		phonenum[telefonnummer] = inputbuffer[pch-inputbuffer+(3+telefonnummer)];
	}		// This functions copies phonenumber of message to memory. 
			// This COULD be done with a -cpy function, but they don't seem to work. 
			// strncpy should copy from pointed array to array, in n chars.
	pc.printf("Copy text message\r\n");
	for(int tekstbesked = 0; tekstbesked < 160; tekstbesked++){
		if(inputbuffer[text-inputbuffer+tekstbesked] == '\0'){
			tekstbesked = 160;	
		}
		textbuf[tekstbesked] = inputbuffer[text-inputbuffer+tekstbesked];
	} 
	int ok = 0;
	ok = strncmp(textbuf,lookup,7);
	/*
	int q = 0;
	for(int y = 0; y<7; y++){
		if(textbuf[y] == lookup[y]){
			q++;
		}
	}
	*/
	if(/*q == 7*/ok >= 0){
		pc.printf("ok was >= 0");
		switch(textbuf[9]){
			case('1'):
				Relay = 1;
				break;
			case('0'):
				Relay = 0;
				break;
			default:
				break;
		}
	}
	SIM900.printf("AT+CMGDA=\"DEL READ\"\r");
	pc.printf("9\r\n");
	memset (inputbuffer, '0', 512);
	pc.printf("Delete inputbuffer\r\n");
	delete pch;
	pc.printf("Delete pch\r\n");
	delete text;
	pc.printf("Delete text\r\n");
	i = 0;
	return;
}


char CMTI(){
	char * newsms;
	newsms = strstr(inputbuffer,"+CMTI:");
	if(newsms-inputbuffer <= 0){
		delete newsms;
		return 0;
	}
	char var = inputbuffer[newsms-inputbuffer+12];
	delete newsms; 
	return(var);
}

//------------------------------Main routine---------------------------------------
int main() {
    pc.baud(19200);
    SIM900.baud(19200);
    setup();
	buffer = inputbuffer;
    while (1) {
		myled = !myled;
        wait_ms(10000);
		u = CMTI();
		pc.printf("U was: %c\r\n",u);			// CMTI reads the number of the new sms		
		//readsms(u, phonenum, textbuf, 160);	 	// Read the sms, return non, but use phonenum and buffer
		if(u > 0){
			SIM900.printf("AT+CMGR=%c\r",u);
			wait_ms(500);
			char *phonenumber;
			phonenumber = strstr(inputbuffer,"\"REC UNREAD");
			pc.printf("%d\r\n",phonenumber);
			strncpy(phonenum,phonenumber,8);
			for(int hej=0; hej < 8; hej++){
				pc.printf("%d",phonenum[hej]);		
			}

		}
		u = 0;
    }
}

Here's the code, is real messy, sorry about that. The only routines I call i CMTI and the serial interrupt.

I'll try the printf("%s",inputbuffer);

Lerche

22 Jun 2011

You were right, the inputbuffer doesn't contain any chars. It is simply 0 all the way through.

THat's weird.

22 Jun 2011

I don't know if it is the cause of your problems but in CMTI you delete pointers that were never new'ed.

22 Jun 2011

Well, that just did the trick, now I can read out the inputbuffer. Why can't I delete pointers like I do? Or "refresh" them? Or is it not nessecary?

22 Jun 2011

IT'S ALIIIIIIVEE!!! :D

It worked after non-deleting the pointers, as the pointers points to my inputbuffer. I can now retrieve the phonenumber succesfully!

Thanks guys, you're the best!!!

Lerche

22 Jun 2011

you should only delete pointers to objects that you new'ed. strstr returns a pointer into str1 (inputbuffer), not a new object! you can create a buffer like this: char *buffer = new char[BUFFERSIZE]; and delete it later with delete[] buffer; new and delete need to be paired otherwise you get a memory leak or you destroy memory that you don't own. This is one of the bigger problems in C++.

22 Jun 2011

So..... How do I point my pointer to like "0" after using it in fx CMTI? Sorry the stupid question, I'm more of a hardware dude. :-)

Lerche

22 Jun 2011

Hi Christian -

I didn't work through your code but have you seen the reference for strstr here:

http://www.cplusplus.com/reference/clibrary/cstring/strstr/

Hope that helps,

Mike

22 Jun 2011

You mean the newsms pointer? There is no need, newsms points into inputbuffer that it doesn't own so it should leave it alone. newsms itself disappears on exit from CMTI. In your program you have only static and automatic variables, you should never need 'delete' or 'delete[]'. Of course you can write newsms = 0; but for what reason? newsms is destroyed anyway. When you need objects for the entire duration of your program you create them static (meaning at file level) or possibly in main() or setup() with new. When you only need them temporarily e.g. only in a function, you use automatic (stack) allocation. For all other objects you use dynamic (heap) allocation with new and delete.

22 Jun 2011

Mike: Thanks, I knew, thats why i didn't use for loops to find the +45 string ;-)

Weiden: Okay, great. Thanks for clearifying. :D - It works perfectly now :-)

Lerche