# Examples

All these examples are also available in docs/examples/ directory in Gammu sources.

## Getting phone information

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

    GSM_StateMachine *s;
    INI_Section *config_section;
    GSM_Error error;
    char buffer[GSM_MAX_INFO_LENGTH];

    /* Function to handle errors */
    void error_handler(void)
    {
    	if (error != ERR_NONE) {
    		printf("ERROR: %s\n", GSM_ErrorString(error));
    		if (GSM_IsConnected(s))
    			GSM_TerminateConnection(s);
    		exit(EXIT_FAILURE);
    	}
    }

    int main(int argc UNUSED, char **argv UNUSED)
    {
    	GSM_Debug_Info *debug_info;
    	GSM_NetworkInfo netinfo;

    	/*
    	 * We don't need gettext, but need to set locales so that
    	 * charset conversion works.
    	 */
    	GSM_InitLocales(NULL);

    	/* Enable global debugging to stderr */
    	debug_info = GSM_GetGlobalDebug();
    	GSM_SetDebugFileDescriptor(stderr, FALSE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/* Allocates state machine */
    	s = GSM_AllocStateMachine();
    	if (s == NULL)
    		return 3;

    	/*
    	 * Enable state machine debugging to stderr
    	 * Same could be achieved by just using global debug config.
    	 */
    	debug_info = GSM_GetDebug(s);
    	GSM_SetDebugGlobal(FALSE, debug_info);
    	GSM_SetDebugFileDescriptor(stderr, FALSE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/*
    	 * Find configuration file (first command line parameter or
    	 * defaults)
    	 */
    	error = GSM_FindGammuRC(&config_section, argc == 2 ? argv[1] : NULL);
    	error_handler();

    	/* Read it */
    	error = GSM_ReadConfig(config_section, GSM_GetConfig(s, 0), 0);
    	error_handler();

    	/* Free config file structures */
    	INI_Free(config_section);

    	/* We have one valid configuration */
    	GSM_SetConfigNum(s, 1);

    	/* Connect to phone */
    	/* 1 means number of replies you want to wait for */
    	error = GSM_InitConnection(s, 1);
    	error_handler();

    	/* Here you can do some stuff with phone... */

    	/* As an example we read some information about phone: */

    	/* Manufacturer name */
    	error = GSM_GetManufacturer(s, buffer);
    	error_handler();
    	printf("Manufacturer  : %s\n", buffer);

    	/* Model name */
    	error = GSM_GetModel(s, buffer);
    	error_handler();
    	printf("Model         : %s (%s)\n",
    		GSM_GetModelInfo(s)->model,
    		buffer);

    	/* Network info */
    	error = GSM_GetNetworkInfo(s, &netinfo);
    	if (error == ERR_NONE) {
    		printf("Network code  : %s\n", netinfo.NetworkCode);
    		printf("Network name  : %s\n", DecodeUnicodeConsole(netinfo.NetworkName));
    	} else if (error != ERR_NOTSUPPORTED) {
    		/* Some phones don't support network info, that's okay */
    		error_handler();
    	}

    	/* Terminate connection */
    	error = GSM_TerminateConnection(s);
    	error_handler();

    	/* Free up used memory */
    	GSM_FreeStateMachine(s);

    	return 0;
    }

    /* Editor configuration
     * vim: noexpandtab sw=8 ts=8 sts=8 tw=72:
     */

## Reading SMS message

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

    GSM_StateMachine *s;
    INI_Section *cfg;
    GSM_Error error;
    volatile GSM_Error sms_send_status;
    volatile gboolean gshutdown = FALSE;

    /* Function to handle errors */
    void error_handler(void)
    {
    	if (error != ERR_NONE) {
    		printf("ERROR: %s\n", GSM_ErrorString(error));
    		if (GSM_IsConnected(s))
    			GSM_TerminateConnection(s);
    		exit(error);
    	}
    }

    /* Interrupt signal handler */
    void interrupt(int sign)
    {
    	signal(sign, SIG_IGN);
    	gshutdown = TRUE;
    }

    int main(int argc UNUSED, char **argv UNUSED)
    {
    	GSM_Debug_Info *debug_info;
    	gboolean start;
    	GSM_MultiSMSMessage 	sms;
    	int i;

    	/* Register signal handler */
    	signal(SIGINT, interrupt);
    	signal(SIGTERM, interrupt);

    	/*
    	 * We don't need gettext, but need to set locales so that
    	 * charset conversion works.
    	 */
    	GSM_InitLocales(NULL);

    	/* Enable global debugging to stderr */
    	debug_info = GSM_GetGlobalDebug();
    	GSM_SetDebugFileDescriptor(stderr, TRUE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/* Allocates state machine */
    	s = GSM_AllocStateMachine();
    	if (s == NULL)
    		return 3;

    	/*
    	 * Enable state machine debugging to stderr
    	 * Same could be achieved by just using global debug config.
    	 */
    	debug_info = GSM_GetDebug(s);
    	GSM_SetDebugGlobal(FALSE, debug_info);
    	GSM_SetDebugFileDescriptor(stderr, TRUE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/*
    	 * Find configuration file (first command line parameter or
    	 * defaults)
    	 */
    	error = GSM_FindGammuRC(&cfg, argc == 2 ? argv[1] : NULL);
    	error_handler();

    	/* Read it */
    	error = GSM_ReadConfig(cfg, GSM_GetConfig(s, 0), 0);
    	error_handler();

    	/* Free config file structures */
    	INI_Free(cfg);

    	/* We have one valid configuration */
    	GSM_SetConfigNum(s, 1);

    	/* Connect to phone */
    	/* 1 means number of replies you want to wait for */
    	error = GSM_InitConnection(s, 1);
    	error_handler();

    	/* Read all messages */
    	error = ERR_NONE;
    	start = TRUE;
    	sms.Number = 0;
    	sms.SMS[0].Location = 0;
    	sms.SMS[0].Folder = 0;
    	while (error == ERR_NONE && !gshutdown) {
    		error = GSM_GetNextSMS(s, &sms, start);
    		if (error == ERR_EMPTY) break;
    		error_handler();
    		start = FALSE;

    		/* Now we can do something with the message */
    		for (i = 0; i < sms.Number; i++) {
    			printf("Location: %d, Folder: %d\n", sms.SMS[i].Location, sms.SMS[i].Folder);
    			printf("Number: \"%s\"\n", DecodeUnicodeConsole(sms.SMS[i].Number));
    			/*
    			 * Decoding with GSM_DecodeMultiPartSMS is also an option here,
    			 * but for simplicity we use this approach which will handle only
    			 * text messages.
    			 */
    			if (sms.SMS[i].Coding == SMS_Coding_8bit) {
    				printf("8-bit message, can not display\n");
    			} else {
    				printf("Text: \"%s\"\n", DecodeUnicodeConsole(sms.SMS[i].Text));
    			}
    			printf("\n");
    		}
    	}

    	/* Terminate connection */
    	error = GSM_TerminateConnection(s);
    	error_handler();

    	/* Free up used memory */
    	GSM_FreeStateMachine(s);

    	return 0;
    }

    /* Editor configuration
     * vim: noexpandtab sw=8 ts=8 sts=8 tw=72:
     */

## Sending SMS message

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

    GSM_StateMachine *s;
    INI_Section *cfg;
    GSM_Error error;
    volatile GSM_Error sms_send_status;
    volatile gboolean gshutdown = FALSE;

    /* Handler for SMS send reply */
    void send_sms_callback (GSM_StateMachine *sm, int status, int MessageReference, void * user_data)
    {
    	printf("Sent SMS on device: \"%s\"\n", GSM_GetConfig(sm, -1)->Device);
    	if (status==0) {
    		printf("..OK");
    		sms_send_status = ERR_NONE;
    	} else {
    		printf("..error %i", status);
    		sms_send_status = ERR_UNKNOWN;
    	}
    	printf(", message reference=%d\n", MessageReference);
    }

    /* Function to handle errors */
    void error_handler(void)
    {
    	if (error != ERR_NONE) {
    		printf("ERROR: %s\n", GSM_ErrorString(error));
    		if (GSM_IsConnected(s))
    			GSM_TerminateConnection(s);
    		exit(error);
    	}
    }

    /* Interrupt signal handler */
    void interrupt(int sign)
    {
    	signal(sign, SIG_IGN);
    	gshutdown = TRUE;
    }

    int main(int argc UNUSED, char **argv UNUSED)
    {
    	GSM_SMSMessage sms;
    	GSM_SMSC PhoneSMSC;
    	char recipient_number[] = "+1234567890";
    	char message_text[] = "Sample Gammu message";
    	GSM_Debug_Info *debug_info;
    	int return_value = 0;

    	/* Register signal handler */
    	signal(SIGINT, interrupt);
    	signal(SIGTERM, interrupt);

    	/*
    	 * We don't need gettext, but need to set locales so that
    	 * charset conversion works.
    	 */
    	GSM_InitLocales(NULL);

    	/* Enable global debugging to stderr */
    	debug_info = GSM_GetGlobalDebug();
    	GSM_SetDebugFileDescriptor(stderr, TRUE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/* Prepare message */
    	/* Cleanup the structure */
    	memset(&sms, 0, sizeof(sms));
    	/* Encode message text */
    	EncodeUnicode(sms.Text, message_text, strlen(message_text));
    	/* Encode recipient number */
    	EncodeUnicode(sms.Number, recipient_number, strlen(recipient_number));
    	/* We want to submit message */
    	sms.PDU = SMS_Submit;
    	/* No UDH, just a plain message */
    	sms.UDH.Type = UDH_NoUDH;
    	/* We used default coding for text */
    	sms.Coding = SMS_Coding_Default_No_Compression;
    	/* Class 1 message (normal) */
    	sms.Class = 1;

    	/* Allocates state machine */
    	s = GSM_AllocStateMachine();
    	if (s == NULL)
    		return 3;

    	/*
    	 * Enable state machine debugging to stderr
    	 * Same could be achieved by just using global debug config.
    	 */
    	debug_info = GSM_GetDebug(s);
    	GSM_SetDebugGlobal(FALSE, debug_info);
    	GSM_SetDebugFileDescriptor(stderr, TRUE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/*
    	 * Find configuration file (first command line parameter or
    	 * defaults)
    	 */
    	error = GSM_FindGammuRC(&cfg, argc == 2 ? argv[1] : NULL);
    	error_handler();

    	/* Read it */
    	error = GSM_ReadConfig(cfg, GSM_GetConfig(s, 0), 0);
    	error_handler();

    	/* Free config file structures */
    	INI_Free(cfg);

    	/* We have one valid configuration */
    	GSM_SetConfigNum(s, 1);

    	/* Connect to phone */
    	/* 1 means number of replies you want to wait for */
    	error = GSM_InitConnection(s, 1);
    	error_handler();

    	/* Set callback for message sending */
    	/* This needs to be done after initiating connection */
    	GSM_SetSendSMSStatusCallback(s, send_sms_callback, NULL);

    	/* We need to know SMSC number */
    	PhoneSMSC.Location = 1;
    	error = GSM_GetSMSC(s, &PhoneSMSC);
    	error_handler();

    	/* Set SMSC number in message */
    	CopyUnicodeString(sms.SMSC.Number, PhoneSMSC.Number);

    	/*
    	 * Set flag before callind SendSMS, some phones might give
    	 * instant response
    	 */
    	sms_send_status = ERR_TIMEOUT;

    	/* Send message */
    	error = GSM_SendSMS(s, &sms);
    	error_handler();

    	/* Wait for network reply */
    	while (!gshutdown) {
    		GSM_ReadDevice(s, TRUE);
    		if (sms_send_status == ERR_NONE) {
    			/* Message sent OK */
    			return_value = 0;
    			break;
    		}
    		if (sms_send_status != ERR_TIMEOUT) {
    			/* Message sending failed */
    			return_value = 100;
    			break;
    		}
    	}

    	/* Terminate connection */
    	error = GSM_TerminateConnection(s);
    	error_handler();

    	/* Free up used memory */
    	GSM_FreeStateMachine(s);

    	return return_value;
    }

    /* Editor configuration
     * vim: noexpandtab sw=8 ts=8 sts=8 tw=72:
     */

## Sending Long SMS message

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

    GSM_StateMachine *s;
    INI_Section *cfg;
    GSM_Error error;
    volatile GSM_Error sms_send_status;
    volatile gboolean gshutdown = FALSE;

    /* Handler for SMS send reply */
    void send_sms_callback (GSM_StateMachine *sm, int status, int MessageReference, void * user_data)
    {
    	printf("Sent SMS on device: \"%s\"\n", GSM_GetConfig(sm, -1)->Device);
    	if (status==0) {
    		printf("..OK");
    		sms_send_status = ERR_NONE;
    	} else {
    		printf("..error %i", status);
    		sms_send_status = ERR_UNKNOWN;
    	}
    	printf(", message reference=%d\n", MessageReference);
    }

    /* Function to handle errors */
    void error_handler(void)
    {
    	if (error != ERR_NONE) {
    		printf("ERROR: %s\n", GSM_ErrorString(error));
    		if (GSM_IsConnected(s))
    			GSM_TerminateConnection(s);
    		exit(error);
    	}
    }

    /* Interrupt signal handler */
    void interrupt(int sign)
    {
    	signal(sign, SIG_IGN);
    	gshutdown = TRUE;
    }

    int main(int argc UNUSED, char **argv UNUSED)
    {
    	GSM_MultiSMSMessage SMS;
    	int i;
    	GSM_MultiPartSMSInfo SMSInfo;
    	GSM_SMSC PhoneSMSC;
    	char recipient_number[] = "+1234567890";
    	char message_text[] = "Very long example Gammu message to show how to construct concatenated messages using libGammu. Very long example Gammu message to show how to construct concatenated messages using libGammu.";
    	unsigned char message_unicode[(sizeof(message_text) + 1) * 2];
    	GSM_Debug_Info *debug_info;
    	int return_value = 0;

    	/* Register signal handler */
    	signal(SIGINT, interrupt);
    	signal(SIGTERM, interrupt);

    	/*
    	 * We don't need gettext, but need to set locales so that
    	 * charset conversion works.
    	 */
    	GSM_InitLocales(NULL);

    	/* Enable global debugging to stderr */
    	debug_info = GSM_GetGlobalDebug();
    	GSM_SetDebugFileDescriptor(stderr, TRUE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/*
    	 * Fill in SMS info structure which will be used to generate
    	 * messages.
    	 */
    	GSM_ClearMultiPartSMSInfo(&SMSInfo);
    	/* Class 1 message (normal) */
    	SMSInfo.Class = 1;
    	/* Message will be consist of one part */
    	SMSInfo.EntriesNum = 1;
    	/* No unicode */
    	SMSInfo.UnicodeCoding = FALSE;
    	/* The part has type long text */
    	SMSInfo.Entries[0].ID = SMS_ConcatenatedTextLong;
    	/* Encode message text */
    	EncodeUnicode(message_unicode, message_text, strlen(message_text));
    	SMSInfo.Entries[0].Buffer = message_unicode;

    	printf("%s\n", DecodeUnicodeConsole(SMSInfo.Entries[0].Buffer));

    	/* Encode message into PDU parts */
    	error = GSM_EncodeMultiPartSMS(debug_info, &SMSInfo, &SMS);
    	error_handler();

    	/* Allocates state machine */
    	s = GSM_AllocStateMachine();
    	if (s == NULL)
    		return 3;

    	/*
    	 * Enable state machine debugging to stderr
    	 * Same could be achieved by just using global debug config.
    	 */
    	debug_info = GSM_GetDebug(s);
    	GSM_SetDebugGlobal(FALSE, debug_info);
    	GSM_SetDebugFileDescriptor(stderr, TRUE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/*
    	 * Find configuration file (first command line parameter or
    	 * defaults)
    	 */
    	error = GSM_FindGammuRC(&cfg, argc == 2 ? argv[1] : NULL);
    	error_handler();

    	/* Read it */
    	error = GSM_ReadConfig(cfg, GSM_GetConfig(s, 0), 0);
    	error_handler();

    	/* Free config file structures */
    	INI_Free(cfg);

    	/* We have one valid configuration */
    	GSM_SetConfigNum(s, 1);

    	/* Connect to phone */
    	/* 1 means number of replies you want to wait for */
    	error = GSM_InitConnection(s, 1);
    	error_handler();

    	/* Set callback for message sending */
    	/* This needs to be done after initiating connection */
    	GSM_SetSendSMSStatusCallback(s, send_sms_callback, NULL);

    	/* We need to know SMSC number */
    	PhoneSMSC.Location = 1;
    	error = GSM_GetSMSC(s, &PhoneSMSC);
    	error_handler();

    	/* Send message parts */
    	for (i = 0; i < SMS.Number; i++) {
    		/* Set SMSC number in message */
    		CopyUnicodeString(SMS.SMS[i].SMSC.Number, PhoneSMSC.Number);

    		/* Prepare message */
    		/* Encode recipient number */
    		EncodeUnicode(SMS.SMS[i].Number, recipient_number, strlen(recipient_number));
    		/* We want to submit message */
    		SMS.SMS[i].PDU = SMS_Submit;

    		/*
    		 * Set flag before callind SendSMS, some phones might give
    		 * instant response
    		 */
    		sms_send_status = ERR_TIMEOUT;

    		/* Send message */
    		error = GSM_SendSMS(s, &SMS.SMS[i]);
    		error_handler();

    		/* Wait for network reply */
    		while (!gshutdown) {
    			GSM_ReadDevice(s, TRUE);
    			if (sms_send_status == ERR_NONE) {
    				/* Message sent OK */
    				return_value = 0;
    				break;
    			}
    			if (sms_send_status != ERR_TIMEOUT) {
    				/* Message sending failed */
    				return_value = 100;
    				break;
    			}
    		}
    	}

    	/* Terminate connection */
    	error = GSM_TerminateConnection(s);
    	error_handler();

    	/* Free up used memory */
    	GSM_FreeStateMachine(s);

    	return return_value;
    }

    /* Editor configuration
     * vim: noexpandtab sw=8 ts=8 sts=8 tw=72:
     */

## SMSD example

    /* Simple C program to start SMSD without all magic normal gammu-smsd does */
    #include <gammu-smsd.h>
    #include <assert.h>

    int main(int argc UNUSED, char **argv UNUSED)
    {
    	GSM_SMSDConfig *config;
        GSM_Error error;
        char *config_file = NULL; /* Use default compiled in path */

    	/*
    	 * We don't need gettext, but need to set locales so that
    	 * charset conversion works.
    	 */
    	GSM_InitLocales(NULL);

        /* Initialize configuration with program name */
    	config = SMSD_NewConfig("smsd-example");
    	assert(config != NULL);

        /* Read configuration file */
    	error = SMSD_ReadConfig(config_file, config, TRUE);
    	if (error != ERR_NONE) {
    		printf("Failed to read config!\n");
    		SMSD_FreeConfig(config);
    		return 2;
    	}

        /* Start main SMSD loop which processes messages */
        /*
         * This normally never terminates, you need to signal it
         * by SMSD_Shutdown(config); (for example from signal handler)
         * to make it stop.
         */
    	error = SMSD_MainLoop(config, FALSE, 0);
    	if (error != ERR_NONE) {
    		printf("Failed to run SMSD!\n");
    		SMSD_FreeConfig(config);
    		return 2;
    	}

        /* Free configuration structure */
    	SMSD_FreeConfig(config);

        return 0;
    }

## Custom configuration

    /*
     * libGammu example to show how to set configuration manually instead
     * of parsing ~/.gammurc
     */
    #include <gammu.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>

    GSM_StateMachine *s;
    GSM_Error error;
    char buffer[100];

    /* Function to handle errors */
    void error_handler(void)
    {
    	if (error != ERR_NONE) {
    		printf("ERROR: %s\n", GSM_ErrorString(error));
    		if (GSM_IsConnected(s))
    			GSM_TerminateConnection(s);
    		exit(error);
    	}
    }

    int main(int argc, char **argv)
    {
    	GSM_Debug_Info *debug_info;
    	GSM_Config *cfg;

    	if (argc != 4) {
    		printf("Usage: custom-config DEVICE CONNECTION MODEL\n");
    	}

    	/*
    	 * We don't need gettext, but need to set locales so that
    	 * charset conversion works.
    	 */
    	GSM_InitLocales(NULL);

    	/* Enable global debugging to stderr */
    	debug_info = GSM_GetGlobalDebug();
    	GSM_SetDebugFileDescriptor(stderr, FALSE, debug_info);
    	GSM_SetDebugLevel("textall", debug_info);

    	/* Allocates state machine */
    	s = GSM_AllocStateMachine();
    	if (s == NULL)
    		return 3;

    	/*
    	 * Enable state machine debugging to same config as global one.
    	 */
    	debug_info = GSM_GetDebug(s);
    	GSM_SetDebugGlobal(TRUE, debug_info);

    	/*
    	 * Get pointer to config structure.
    	 */
    	cfg = GSM_GetConfig(s, 0);

    	/*
    	 * Set configuration, first freeing old values.
    	 */
    	free(cfg->Device);
    	cfg->Device = strdup(argv[1]);
    	free(cfg->Connection);
    	cfg->Connection = strdup(argv[2]);
    	/* For historical reasons this is not a pointer */
    	strcpy(cfg->Model, argv[3]);

    	/* We have one valid configuration */
    	GSM_SetConfigNum(s, 1);

    	/* Connect to phone */
    	/* 1 means number of replies you want to wait for */
    	error = GSM_InitConnection(s, 1);
    	error_handler();

    	/* Here you can do some stuff with phone... */

    	/* As an example we read some information about phone: */

    	/* Manufacturer name */
    	error = GSM_GetManufacturer(s, buffer);
    	error_handler();
    	printf("Manufacturer  : %s\n", buffer);

    	/* Model name */
    	error = GSM_GetModel(s, buffer);
    	error_handler();
    	printf("Model         : %s (%s)\n",
    		GSM_GetModelInfo(s)->model,
    		buffer);

    	/* Terminate connection */
    	error = GSM_TerminateConnection(s);
    	error_handler();

    	/* Free up used memory */
    	GSM_FreeStateMachine(s);

    	return 0;
    }

    /* Editor configuration
     * vim: noexpandtab sw=8 ts=8 sts=8 tw=72:
     */