воскресенье, 24 апреля 2011 г.

Отправка SMS через usb-модем с использованием Python

После окончательного перехода на убунту отказалась работать .NET-фреймворковская программка, через которую работала отправка SMS-сообщений. Возникла естественная мысль переписать её, скажем, на питоне. Благодаря подсказкам это оказалось совсем тривиально:

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import serial
import time
import random

# процедура для отправки строки в модем и получения ответа
def str_send (ser, textline):
print "<<" + textline
ser.write(textline)

out = ''
N = 10
while N > 0:
time.sleep(1)
while ser.inWaiting() > 0:
out += ser.read(1)

if ('OK' in out) or ('ERROR' in out) or ('>' in out):
print ">>" + out
N = 1

N -= 1

# функция преобразования телефонного номера в формат, пригодный для SMS
def PhoneNumberToSMS(number):
number += 'F'
result = '0B' + '91'
i = 0
while i < len(number):
result += number[i+1] + number[i]
i += 2
return result

# функция, кодирующая юникодную строку в формат SMS
def TextToSMS(text):
b = text
result = ''
i = 0
while i < len(b):
o = ord(b[i])
result += ("%0.2X" % (o/256)) + ("%0.2X" % (o%256))
i += 1
return result

# вводим с консоли сообщение и переводим его в юникод
message = raw_input('Текст сообщения:\n')
message = message.decode('utf-8')

# если сообщение большое - режем его на кусочки для механизма конкатенации SMS
chunks = []

if len(message) > 70:
while len(message) > 66:
chunks.append(message[:66])
message = message[66:]

if len(message) > 0:
chunks.append(message)

# готовим номер группы сообщений и устанавливаем 6-й бит SMS_SUBMIT_PDU
SMS_SUBMIT_PDU = "11"
CSMS_reference_number = ""
if len(chunks) > 1:
SMS_SUBMIT_PDU = "51"
CSMS_reference_number = "%0.4X" % random.randrange(1,65536)

# связываемся с модемом
ser = serial.Serial("/dev/ttyUSB0", 115200, timeout=1)
ser.open()

# устанавливаем нужный формат передачи данных
str_send(ser, 'AT+CMGF=0\r')

# передаем кусочки сообщения
i = 1
for chunk in chunks:
emessage = TextToSMS(chunk)
if CSMS_reference_number != "":
emessage = "06" + "08" + "04" + CSMS_reference_number + \
("%0.2X" % len(chunks)) + ("%0.2X" % i) + emessage
sms = \
"00" + \
SMS_SUBMIT_PDU + \
"00" + \
PhoneNumberToSMS("7383XXXXXXX") + \
"00" + \
"08" + \
"AA" + \
"%0.2X" % (len(emessage)/2) + \
emessage
str_send(ser, 'AT+CMGS=' + str(len(sms)/2-1) + '\r')
str_send(ser, sms + '\x1A')
i += 1

# отвязываемся от модема
ser.close()

NB. import serial заработает только если будет установлен модуль pySerial (aptitude install python-serial)

Комментариев нет:

Отправить комментарий