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 *cfg;
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 UNUSED, char **argv UNUSED)
{
	GSM_Debug_Info *debug_info;

	/*
	 * 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(&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();

	/* 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:
 */

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 contatenated messages using libGammu. Very long example Gammu message to show how to construct contatenated 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);

    /* Initalize 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:
 */