Objavljeno: 31.3.2005 08:38 | Avtor: Dalibor Kranjčič | Monitor Julij 2004

Programsko pošiljanje sporočil SMS

Sporočila SMS (Short Message Service) so danes povsem normalen način komunikacije, zlasti pri mlajši generaciji uporabnikov prenosnih telefonov. Prednost pošiljanja sporočil SMS je razmeroma nizka cena, slabost pa čas, potreben za pisanje sporočila - a to ni ovira, če se sporočilo pošlje z namenskim programom. Ta način obveščanja se najpogosteje uporablja za posredovanje alarmov in dogodkov na področjih procesne avtomatike, telekomunikacij in sistemske administracije.

Za računalniško pošiljanje sporočil SMS potrebujemo osebni računalnik, modem GSM ter namenski program za pošiljanje sporočil SMS.

Modem GSM

Modeme GSM povezujemo z osebnim računalnikom z zaporednim ali USB priključkom. Slednji potrebuje za svoje delovanje ustrezen gonilnik. Trg ponuja precej modelov, od katerih se najpogosteje srečujemo z modemi GSM podjetij Siemens in Wavecom.

Kot zgled pošiljanja sporočil SMS lahko uporabimo modem GSM podjetja Siemens, model TC35, ki uporablja zaporedni (COM) priključek za povezovanje. Za delovanje modema potrebujemo še kartico SIM izbranega ponudnika storitev GSM, podobno kot pri navadnem prenosnem telefonu.

Modem GSM Siemens TC35

Komunikacija modemov GSM z osebnim računalnikom poteka ob pomoči Hayesovih ukazov oziroma ukazov AT. Gospod Hayes je leta 1977 postavil temelj modemski komunikaciji. Načelo le-te temelji na izmenjevanju podatkovnega (data mode) in ukaznega (command mode) prenosa podatkov. Ukaze AT pošiljamo v ukaznem načinu za inicializacijo začetnih nastavitev, spreminjanje hitrosti prenosa podatkov, klic nove telefonske številke itn. V podatkovnem načinu prenašamo čiste podatke, na primer prenos datotek in elektronsko pošto.

Ukaz AT izhaja od angleške besede attention (pozor) in opozarja, da za nizom AT sledi ukaz modemu.

Za pošiljanje sporočila SMS potrebujemo le dva osnovna ukaza AT, ki ju posredujemo modemu s terminalskim programom, na primer Hyperterminal (Windows) ali Minicom (Linux).

Nastavitve terminalskega programa naj bodo naslednje:

Baudna hitrost: 38400

Število podatkovnih bitov: 8

Število končnih bitov: 1

Pariteta: nobena

Krmiljenje toka: nobeno

Priporočam, da predhodno nastavite kartico SIM modema GSM na vašem prenosnem telefonu, tako da ob vklopu ne bo preverjala kode PIN. V nasprotnem primeru bo potrebna programska nastavitev kode PIN s pomočjo ustreznega ukaza AT. Prav tako se prepričajte, da je na kartici SIM nastavljena številka SMS centra (Mobitel: +38641001333, Simobil: +38640441000).

Za pošiljanje sporočila SMS vtipkajte naslednje ukaze AT v terminalskem programu:

AT+CMGF=1

AT+CMGS="+38640111222" (Telefonska številka, na katero pošiljamo sporočilo SMS.)

> To je sporocilo SMS (Sporočilo vtipkajte in nato pošljite s hkratnim pritiskom

tipk CTRL in Z.)       

Zgled komunikacije v minicomu:

Welcome to minicom 2.00.0

OPTIONS: History Buffer, F-key Macros, Search History Buffer, I18n

Compiled on Mar 14 2003, 01:20:23.

Press CTRL-A Z for help on special keys

AT S7=45 S0=0 L1 V1 X4 &c1 E1 Q0

OK

AT+CMGF=1

OK

AT+CMGS="+38640111222"

> To je sporocilo SMS

+CMGS: 73

OK

Pomen ukazov AT je naslednji:

AT+CMGF=1

Nastavi tekstovni način pošiljanja (text mode).

AT+CMGF=0

Nastavi protokolni način pošiljanja (PDU mode).

AT+CMGF?

Vrne način prenosa (tekst ali PDU).

AT+CMGS="Številka"

Pošlje SMS sporočilo.

AT+CPIN=PIN

Vnos kode PIN.

AT+CPIN?

Vrne kodo PIN.

AT+CSCA="Številka"

Vnos številke SMS centra (prej uporabi ukaz CMGF=1).

AT+CSCA?

Vrne številko SMS centra.

ATE0

Izklopi odmev (echo off), vrnitev vtipkanega ukaza.

Programska rešitev pošiljanja sporočil SMS

Podali bomo programsko rešitev pošiljanja sporočil SMS v programskem jeziku C. Izvedba programa bo narejena v operacijskem sistemu Linux.

Program je sestavljen iz dveh delov. V prvem izvajamo inicializacijo zaporednih vrat oziroma datoteko naprave /dev/ttyS0, ki predstavlja prva zaporedna vrata (COM1). V drugem delu pošiljamo ukaze AT v neskončni zanki while. Do pošiljanja pride ob spremembi vsebine datoteke sms_dat (glej makro #define SMSFILE), ki vsebuje sporočilo SMS.

Inicializacijo zaporednih vrat omogočajo knjižnice termios, ki vsebujejo številne funkcije za nadzor asinhrone zaporedne povezave. Večina funkcij uporablja kot parameter kazalec na strukturo termios, ki vsebuje naslednje člane:

tcflag_t c_iflag; /* vhodni načini */

tcflag_t c_oflag; /* izhodni načini */

tcflag_t c_cflag; /* kontrolni načini */

tcflag_t c_lflag; /* lokalni načini */

cc_t c_cc[NCCS]; /* kontrolni znaki */

Zaporedna vrata najprej odpremo s funkcijo open, ki vrne njihov datotečni deskriptor. Ta se bo nanašal na zaporedna vrata v drugih funkcijah. Funkcija tcgetattr() prebere obstoječe parametre zaporednih vrat, na katere se sklicuje datotečni deskriptor, ter jih shrani v spremenljivki strukture termios (my_termios).

Sledi nastavljanje kontrolnih načinov (c_cflag) v vrstici kode:

my_termios.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

Pomen izbranih kontrolnih načinov je naslednji:

BAUDRATE: baudna hitrost

CRTSCTS: omogoči (RTS/CTS) strojno krmiljenje toka.

CS8: število podatkovnih bitov

CLOCAL: ignorira modemske statusne linije.

CREAD: aktivira sprejemnik.

Izklop odmeva odposlanih znakov ter izklop ustvarjanja kontrolnih signalov izvedemo v vrstici kode:

my_termios.c_lflag = 0;

Pri nastavljanju vhodnih načinov izberemo možnost IGNPAR, ki ignorira podatkovne paritetne napake (parity error) ter napake na podatkovnih okvirih (framing error).

Izhodni načini (c_oflag) so nastavljeni tako, da se znaki oddajajo neposredno brez vpletanja (obdelave) operacijskega sistema (raw output).

Podatke, ki so bili sprejeti, a niso prebrani, zavrže funkcija tcflush. Inicializacijo končamo s funkcijo tcsetattr, ki dejansko nastavi parametre zaporednih vrat.

Do pošiljanja sporočila SMS pride, če je datoteka sms_dat (makro SMSFILE), ki vsebuje sporočilo, polna (število znakov je večje od 0).

Programska koda:

/*** Datoteka: sms.c ***/

/*** Pošlje SMS sporočilo na GSM modem Siemens TC35 ***/

/*** Sporočilo prebere iz datoteke sms_dat ***/

#include <fcntl.h>

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <time.h>

#include <termios.h>

#include <string.h>

#include <sys/times.h>

#include <errno.h>

#define MODEM_PORT "/dev/ttyS0" // Zaporedna vrata COM 1

#define BSIZE 200 // Velikost ukaza AT

#define SMSSIZE 160 // Velikost sporočila SMS

#define BAUDRATE B38400 // Hitrost prenosa

// Modemski AT ukazi

#define ECHO_OFF "ATE0"

#define NO_PDU "AT+CMGF=1"

// Telefonska stevilka na katero posiljamo SMS

#define SEND_SMS "AT+CMGS=\"+38640111222\""

// Lokacija SMS datoteke sms_dat

#define SMSFILE "/home/dalibor/sms_dat"

#define TRUE 1

#define FALSE 0

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

/*** Funkcije ***/

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

// Odpre datoteko

FILE* open_file(const char *path, const char *mode)

{

FILE* fd = fopen(path, mode);

if (fd == NULL)

printf("Odpiranje porta %d %s\n", errno, strerror(errno));

return (fd);

}

// Vpiši podatke na zaporedna vrata

void write_modem(char *psz_buf, int fds)

{

// Poslani niz končujemo z znakom \n (0x0d)

// za novo vrstico ter \r (0x0a) za začetek vrstice

psz_buf[strlen(psz_buf)] = 0x0d;

psz_buf[strlen(psz_buf)+1] = 0x0a;

if (write(fds, psz_buf, strlen(psz_buf)) < 0)

fprintf(stderr, " Error writing... \n");

}

// Bere podatke z zaporednih vrat

void read_modem(int fds)

{

char sz_inbuf[BSIZE]; // Izhodni ukaz

memset(sz_inbuf, 0, BSIZE);

usleep(1000000); // Počakaj trenutek

if (read(fds, sz_inbuf, sizeof(sz_inbuf)) < 0)

fprintf(stderr, "Napaka pri citanju... \n");

printf ("Sprejeti niz je:%s \n", sz_inbuf);

}

// Pošlje ukaz AT

void send_AT_recv(char *psz_buf, int fds)

{

printf ("Pošiljam ukaz < %s >. \n", psz_buf);

write_modem(psz_buf, fds);

read_modem(fds);

memset (psz_buf, 0, BSIZE);

}

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

/*** Konec funkcij ***/

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

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

/*** Glavni program ***/

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

int main()

{

int fd; // datotečni deskriptor za zaporedna vrata

int n_file_full = FALSE;

int nch = 0, ch = 0;

FILE *fds;

struct termios my_termios;

char sz_at_com[BSIZE]; // ukaz AT

char sz_sms[SMSSIZE]; // SMS

// Odpiranje zaporednih vrat

if ((fd = open(MODEM_PORT, O_RDWR | O_NOCTTY)))

printf("Odpiranje porta: %d %s\n", errno, strerror(errno));

// Odpiranje SMS datoteke

fds = open_file(SMSFILE, "r");

//*** Konfiguriranje modema ***

// Prebere obstoječe parametre vrat

tcgetattr(fd, &my_termios);

// Nastavi: baudno hitrost, strojno krmiljenje, število podatkovnih bitov

// Ignorira modemske statusne linije ter aktivira sprejemnik.

my_termios.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

// Izklopi odmev in ne ustvarjaj kontrolnih signalov

my_termios.c_lflag = 0;

// Ignorira paritetne napake in napake na okvirih

my_termios.c_iflag = IGNPAR;

// Direktno pošiljanje brez procesiranja (raw output)

my_termios.c_oflag = 0;

tcflush(fd, TCIFLUSH);

// Nastavi parametre vrat

tcsetattr(fd, TCSAFLUSH, &my_termios);

// *** Konec konfiguracije modema ***

// Pošlji SMS, ko je datoteka SMSFILE polna

while (TRUE) {

if (n_file_full) {

fds = open_file(SMSFILE, "r");

n_file_full = FALSE;

}

// Preštej znake

while ((ch = getc(fds)) != EOF) nch++;

// Pošlji SMS, če datoteka ni prazna

if (nch > TRUE) {

n_file_full = TRUE;

// Preberi vsebino datoteke od začetka

memset (sz_sms, 0, 160);

fseek(fds, 0, SEEK_SET);

fread (sz_sms, 1, 160, fds);

// Ponastavi vrednosti

nch = ch = 0;

printf ("SMS vsebina: %s \n", sz_sms);

// Izbriši datoteko z vnovičnim odpiranjem

fds = open_file(SMSFILE, "w");

fclose (fds);

// Pošlji ATE0 - ugasni odmev (echo off)

sprintf (sz_at_com, ECHO_OFF);

send_AT_recv(sz_at_com, fd);

// Nastavi tekstovni način pošiljanja

sprintf (sz_at_com, NO_PDU);

send_AT_recv(sz_at_com, fd);

// Pošlji sporočilo SMS

sprintf (sz_at_com, SEND_SMS);

send_AT_recv(sz_at_com, fd);

// Dejansko pošiljanje sporočila SMS

sprintf(sz_at_com, "%s %c ", sz_sms, 26);

send_AT_recv(sz_at_com, fd);

}

}

close (fd);

} // END

Program prevedemo in poženemo kot root uporabnik v lupini shell na naslednji način:

# gcc sms.c -o sms

# ./sms

Pred zagonom programa ustvarite prazno datoteko sms_dat, definirano z makrom SMSFILE. Sporočilo dejansko pošljete s pisanjem v to datoteko, in sicer na naslednji način:

# echo To je sporočilo SMS > /lokacija datoteke (glej makro SMSFILE)

Program bo ustvaril naslednji izpis ob pošiljanju sporočila SMS:

SMS vsebina: To je sporočilo SMS

Pošiljam ukaz < ATE0 >.

Sprejeti niz je:

OK

OK

Pošiljam ukaz < AT+CMGF=1 >.

Sprejeti niz je:

OK

Pošiljam ukaz < AT+CMGS="+38640111222" >.

Sprejeti niz je:

>

Pošiljam ukaz < To je sporočilo SMS

>.

Sprejeti niz je:

+CMGS: 128

Izvirna koda je na voljo na spletnem naslovu http://www.monitor.si/datoteke/sms-c.zip.

Naroči se na redna tedenska ali mesečna obvestila o novih prispevkih na naši spletni strani!

Komentirajo lahko le prijavljeni uporabniki

 
  • Polja označena z * je potrebno obvezno izpolniti
  • Pošlji