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
Leave a Reply
You must be logged in to post a comment.