Python code for sending SMS messages via a USB connected mobile phone

I have a spare mobile phone (Samsung G600 to be exact) and I though it would be nice to use this phone for text alerts, be it system down, download complete, whatever. I also have a data cable with my phone meaning that this shouldn't be too difficult. So I started searching the web for way's in which to do this. There are many many mobile apps out there and many things claiming to be able to do what I want but nothing seemed to work. Then I realised that a mobile phone is effectively a modem, and that the AT commands might be able to do this.

I stumbled across an article on Design Build Test Repeat which showed how to do this using a 3G USB dongle and went from there.

I basically took the code from the above link and modified it to suite my needs. The code in the above example didn't work but it did appear to be the best starting point. I ended up having to add the sleep(1) "commands" because without them the phone wouldn't send any messages. The AT commands were being sent too quickly.

Here is the resulting code.

#!/usr/bin/env python
"""
sms.py - Used to send txt messages.
"""
import serial
import time
 
class TextMessage:
    def __init__(self, recipient="0123456789", message="TextMessage.content not set."):
        self.recipient = recipient
        self.content = message
 
    def setRecipient(self, number):
        self.recipient = number
 
    def setContent(self, message):
        self.content = message
 
    def connectPhone(self):
        self.ser = serial.Serial('/dev/ttyACM0', 460800, timeout=5)
        time.sleep(1)
 
    def sendMessage(self):
        self.ser.write('ATZ\r')
        time.sleep(1)
        self.ser.write('AT+CMGF=1\r')
        time.sleep(1)
        self.ser.write('''AT+CMGS="''' + self.recipient + '''"\r''')
        time.sleep(1)
        self.ser.write(self.content + "\r")
        time.sleep(1)
        self.ser.write(chr(26))
        time.sleep(1)
 
    def disconnectPhone(self):
        self.ser.close()

And it's called like this:

sms = TextMessage("0123456789","This is the message to send.")
sms.connectPhone()
sms.sendMessage()
sms.disconnectPhone()



SMS and Phonecalls with python and AT commands

The below was sent to me by matogrosso who adapted my initial example (above) to suit his needs. He kindly shared his work so that others out there could benefit.

Working from home and want to use a handset in the office? Or maybe you are in the office but feeling too lazy to type numbers and letters in a tiny handset keyboard.

The scripts below use AT commands and were tested on Nokia 6700. Should work on most Nokias and Sony Ericsson running Symbian. Do not work on Android or Iphone as they do not support AT commands.

  1. Connect a Nokia handset to your linux box using a USB cable.
  2. On the Nokia handset select "PC suite".
  3. On your linux machine:

To make a voice call to number 384005 type:

     [root@machine pyscripts]# python voice_call.py 384005

To end a voice call type:

     [root@machine pyscripts]# python end_call.py

To send a text message (e.g. "This is the message") to number 384005 type:

     [root@machine pyscripts]# python send_sms.py 384005 This is the message

To use this you need to install the following packages:

# yum -y install python-setuptools
# easy_install pyserial

AUTOMATICALLY ANSWER THE VOICE CALL by using an android phone as the dialled subscriber:

  1. Goto to Android Market -> Donwload and install the free application "Lazy Car".
  2. Set Lazy Car to answer all calls. Automatic SMS reply is also supported.
at_cmds.py
#!/usr/bin/env python
"""
at_cmds_v4.py - All AT commands and all classes are here. Call them from outside. 
"""
## The packges below must be installed in advance
## yum -y install python-setuptools
## easy_install pyserial
 
import serial
import time
 
class ATcommands:
    def setDialledNumber(self, number):
        self.dialledNumber = number
 
    def setRecipient(self, number):
        self.recipient = number
 
    def setContent(self, message):
        self.content = message
 
    def connectPhone(self):
        self.ser = serial.Serial('/dev/ttyACM0', 460800, timeout=5)
        time.sleep(1)
 
    def disconnectPhone(self):
        self.ser.close()
 
 
class TextMessage:
    def __init__(self, recipient="0000000", message="TextMessage.content not set."):
        self.recipient = recipient
        self.content = message
 
    def sendMessage(self):
        self.ser = serial.Serial('/dev/ttyACM0', 460800, timeout=5)
        self.ser.write('ATZ\r')
        time.sleep(1)
        self.ser.write('AT+CMGF=1\r')
        time.sleep(1)
        self.ser.write('''AT+CMGS="''' + self.recipient + '''"\r''')
        time.sleep(1)
        self.ser.write(self.content + "\r")
        time.sleep(1)
        self.ser.write(chr(26))
        time.sleep(1)
 
 
class VoiceCall:
    def __init__(self, dialledNumber='000000'):
        self.dialledNumber = dialledNumber
 
    def dialNumber(self):
        self.ser = serial.Serial('/dev/ttyACM0', 460800, timeout=5)
        self.ser.write('ATZ\r')
                ## ATZ : Restore profile ##
        time.sleep(1)
        self.ser.write('ATD ' + self.dialledNumber + ';\r')
                ## ATD : Dial command ##
                ## semicolon : voice call ##
        time.sleep(1)
        time.sleep(1)
        self.ser.write(chr(26))
        time.sleep(1)
        time.sleep(1)
        time.sleep(1)
 
    def endCall(self):
        self.ser = serial.Serial('/dev/ttyACM0', 460800, timeout=5)
        self.ser.write('ATZ\r')
        time.sleep(1)
        self.ser.write('AT+CHUP\r')
        time.sleep(1)
        self.ser.write(chr(26))
        time.sleep(1)
 
 
 
 
#Main function that calls other functions - Makes script reusable
def main():
	pass
 
if __name__ == "__main__":
	main()
send_sms.py
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
"""
Use this to call the sms function
It is for sending SMS using AT commands - version v3
"""
## The packges below must be installed in advance
## yum -y install python-setuptools
## easy_install pyserial
 
import serial
import time
import sys
 
from at_cmds import ATcommands
from at_cmds import TextMessage
 
if len(sys.argv) > 1:
	phoneNumber = sys.argv[1]
	message = ""	
	if len(sys.argv) >= 2:
		for i in range(2, len(sys.argv)):
			message = message + " " + sys.argv[i] 
 
		message = message.strip()
	print "number = " + phoneNumber + ", message = " + message
	sms = TextMessage(phoneNumber, message)
else:
	sms = TextMessage()	
 
usb_serial = ATcommands()
 
usb_serial.connectPhone()
sms.sendMessage()
usb_serial.disconnectPhone()
 
#Main function that calls other functions - Makes script reusable
def main():
	pass
 
if __name__ == "__main__":
	main()
voice_call.py
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
"""
Voice call using AT commands
Calls the at_cmds class definitions - version v3
"""
## The packges below must be installed in advance
## yum -y install python-setuptools
## easy_install pyserial
 
import serial
import time
import sys
from at_cmds import ATcommands
from at_cmds import VoiceCall
 
 
if len(sys.argv) > 1:
	phoneNumber = sys.argv[1]
	callPhone = VoiceCall(phoneNumber)
else:
	callPhone = VoiceCall()	
 
usb_serial = ATcommands()
 
usb_serial.connectPhone()
callPhone.dialNumber()
usb_serial.disconnectPhone()
 
#Main function that calls other functions - Makes script reusable
def main():
	pass
 
if __name__ == "__main__":
	main()
end_call.py
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
"""
Terminate voice call using AT commands
Calls the at_cmds class definitions - version v4
"""
## The packges below must be installed in advance
## yum -y install python-setuptools
## easy_install pyserial
 
import serial
import time
import sys
from at_cmds import ATcommands
from at_cmds import VoiceCall
 
currentCall = VoiceCall()
usb_serial = ATcommands()
 
usb_serial.connectPhone()
currentCall.endCall()
usb_serial.disconnectPhone()
 
#Main function that calls other functions - Makes script reusable
def main():
	pass
 
if __name__ == "__main__":
	main()
Burtronix Banner W3C Banner