Script python para enviar SMS en GSM (Telcel, Movistar)

0
(0)

Existen excelentes programas para enviar SMS desde el escritorio como Wammu, entre otros.

¿Pero, que sucede si se desea enviar SMS desde aplicaciones incrustadas (¿embebidas?), o simplemente se requiere mas grado de control?

El siguiente script envia SMS via puerto serial virtual Bluetooth, codificando el texto en modo PDU.
Es importante mencionar que el modo texto para envío de SMS (que es mucho mas sencillo de implementar) no siempre está disponible en todas las terminales.

El código es muy perfectible, solamente cuenta con un manejo básico de errores y no está muy a la “manera pythonica”, pero por otra parte, funciona con todo el alfabeto GSM de 7 bits y permite enviar caracteres no ingleses, como la ñ y Ñ.

Si resulta de interés, posteriormente pondré a su consideración, otras formas de codificación SMS como la UTF (que es la razón de que en ocasiones las compañías celulares nos cobren varios SMS por envío por los mismos 160 caracteres). Codificar UTF requiere modo PDU hasta donde mi conocimiento me permite saber.

Bienvenidos los comentarios, quejas y sugerencias a Idea Versátil

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
# Python script to send SMS in PDU MODE.
# It is using 7 bit default alphabet as specified by GSM 03.38, even chars as ñ or Ñ
# Check www.ideaversatil.com for comments. Script provided as is. NO WARRANTIES OF ANY KIND!!!
 
import string
from time import sleep
import serial
 
def reverseMe(s):
    return s[::-1]
 
def int2bin(n, count=24):
    # (int2bin Author: adomas) http://www.sourcesnippets.com/python-decimal-to-binary-conversion.html
    return "".join([str((n >> y) & 1) for y in range(count-1, -1, -1)])
 
def bin2hex(b):
    return ( "%X" % int(b,2) ).zfill(2)
 
gsm7 = {'@':'0', u'£':'1', '$':'2', u'¥':'3', u'è':'4', u'é':'5', u'ù':'6', u'ì':'7', u'ò':'8', u'Ç':'9', '\n':'10', u'Ø':'11', u'ø':'12', '\r':'13', u'Å':'14', u'å':'15', u'Δ':'16', '_':'17', u'Φ':'18', u'Γ':'19', u'Λ':'20', u'Ω':'21', u'Π':'22', u'Ψ':'23', u'Σ':'24', u'Θ':'25', u'Ξ':'26', '\f':'27##10', '^':'27##20', '{':'27##40', '}':'27##41', '\\':'27##47', '[':'27##60', '~':'27##61', ']':'27##62', '|':'27##64', u'€':'27##101', u'Æ':'28', u'æ':'29', u'ß':'30', u'É':'31', ' ':'32', u'!':'33', '"':'34', '#':'35', u'¤':'36', '%':'37', '&':'38', '\'':'39', '(':'40', ')':'41', '*':'42', '+':'43', ',':'44', '-':'45', '.':'46', '/':'47', '0':'48', '1':'49', '2':'50', '3':'51', '4':'52', '5':'53', '6':'54', '7':'55', '8':'56', '9':'57', ':':'58', ';':'59', '<':'60', '=':'61', '>':'62', '?':'63', u'¡':'64', 'A':'65', 'B':'66', 'C':'67', 'D':'68', 'E':'69', 'F':'70', 'G':'71', 'H':'72', 'I':'73', 'J':'74', 'K':'75', 'L':'76', 'M':'77', 'N':'78', 'O':'79', 'P':'80', 'Q':'81', 'R':'82', 'S':'83', 'T':'84', 'U':'85', 'V':'86', 'W':'87', 'X':'88', 'Y':'89', 'Z':'90', u'Ä':'91', u'Ö':'92', u'Ñ':'93', u'Ü':'94', u'§':'95', u'¿':'96', 'a':'97', 'b':'98', 'c':'99', 'd':'100', 'e':'101', 'f':'102', 'g':'103', 'h':'104', 'i':'105', 'j':'106', 'k':'107', 'l':'108', 'm':'109', 'n':'110', 'o':'111', 'p':'112', 'q':'113', 'r':'114', 's':'115', 't':'116', 'u':'117', 'v':'118', 'w':'119', 'x':'120', 'y':'121', 'z':'122', u'ä':'123', u'ö':'124', u'ñ':'125', u'ü':'126', u'à':'127'}
rvphone = ""
i = 0
txtBin = ""
txtHex = ""
 
txt = unicode(raw_input("Text to send: "),'utf-8')
phone = raw_input("Phone number: ")
lensms = len(txt)
 
if (len(phone) % 2) > 0:
    phone = phone + "F"
 
while i < len(phone):
    rvphone += reverseMe(phone[i:i+2])
    i += 2
phone = rvphone
 
for c in reverseMe(txt):
 
    try:
         word = gsm7[c]
    except Exception, e:
        print '%s Not found, Exception: %s' % (c,e)
        word = '63' # Using ? as wildcard
    bytes = word.split('##')
 
    if len(bytes) > 1:
        txtBin += int2bin(int(bytes[1]),7)
        lensms += 1
    txtBin += int2bin(int(bytes[0]),7)
 
mlen = len(txtBin)
txt8 =  txtBin.zfill(mlen + (8 - mlen % 8))
mlen8 = len(txt8)
i = 0
 
while i < mlen8:
    txtHex = bin2hex(txt8[i:i+8]) + txtHex
    i += 8
#Composing GSM PDU
pdu = "001100"
pdu +=  ("%X" % len(phone)).zfill(2)
pdu +=  "81" + phone
pdu += "0000AA%s%s" % ( ("%X" % (lensms)).zfill(2),txtHex )
print "AT+CMGS=%s\n%s" % ((len(pdu) / 2) - 1 ,pdu.upper()) #Printing command to send sms
 
try:
    s = serial.Serial('/dev/rfcomm0', 9600, timeout=1)
    #AT commands tested successfully on Sony Ericsson, Nokia and Motorola terminals
    s.write('ATZ\r') # Back to default phone settings
    sleep(1)
    s.write('ATE=0\r') #Turn Off Local Echo
    sleep(1)
    s.write('AT+CPMS="ME","ME"\r')#Using Phone's Memory as workspace
    sleep(1)
    s.write('AT+CMGF=0\r') #Enabling PDU Mode. AT+CMGF=1 for Text Mode
    print "Sending..."
    sleep(1)
    s.write("AT+CMGW=%s\r" % ((len(pdu) / 2) - 1 )) #Writing SMS to phone instead of actually sending SMS (debug Mode),
                                                    #change this command to AT+CMGS when  you are ready to send SMS
    sleep(1)
    s.write(pdu.upper())
    s.write(chr(26)) # CTRL+Z
    sleep(1)
    print s.read(1024) #Reading phone answers
 
    s.close()
 
except Exception, e:
    print "Unable to open /dev/rfcomm0, Exception: %s" % e

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

3 thoughts on “Script python para enviar SMS en GSM (Telcel, Movistar)

  1. Oye POP, hay un error cuando se publican fuentes, en las condicionales cuando se usan simbolos como el “mayor que, menor que, ampersand” (>,<,&) se reemplaza por un gt; lt; amp; respectivamente, espero se pueda resolver pronto.. Saludos!!

Leave a Reply