Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Read long SMS with python-gsmmodem (and send SMS with same running script)

Read long SMS with python-gsmmodem (and send SMS with same running script)

I spend a lot of time to replace gammu with python-gsmmodem for my Huawei E3531.

The python exemple is just an exemple, it's incomplete. It does not read sms in the memory (if you receive a sms before starting the script). And it does not concat multiple parts sms (it will print unordered parts).
Also, as your live read sms script is running, you cannot send sms with another script because the dongle is busy.

Here is my own script to read all kind of SMS and send in same time.

Install python-gsmmodem-new

Don't use python-gsmmodem that is deprecated but python-gsmmodem-new

Install dependencies

Install Pyro4:

pip  install  Pyro4

Install threaded:

pip install threaded

Start scripts

Listen for new SMS

$> python2.7 python-gsmmodem-advanced-read.py
Initializing modem...
Waiting for new SMS message...
Object <__main__.RemoteSMSHandler object at 0x764e9910>:
uri = PYRO:RemoteSMSHandler@127.0.0.1:9091
Pyro daemon running.

Keep this process running in background, for exemple with screen

Send SMS:

$> python2.7 python-gsmmodem-advanced-send.py --to=<receipient_number> --message=<your_message>
#!/usr/bin/env python
from __future__ import print_function
from datetime import datetime
from gsmmodem.modem import GsmModem, Sms
from gsmmodem.pdu import Concatenation
import logging
import Pyro4.core
import threading
PORT = '/dev/ttyUSB0'
BAUDRATE = 115200
PIN = None # SIM card PIN (if any)
concat_sms = {}
@Pyro4.expose
class RemoteSMSHandler(object):
def __init__(self, m):
self.modem = m
def sendSMS(self, to, message):
try:
self.modem.sendSms(to, message)
return "Message sent to {0}.\n".format(to)
except Exception, e:
return "Failed to send SMS: " + str(e)
def handleSms(sms):
concat = None
message = None
for i in sms.udh:
if isinstance(i, Concatenation):
concat = i
break
if concat:
if concat_sms.has_key(concat.reference) == False:
concat_sms[concat.reference] = {} #numpy.empty(concat.parts, dtype=string)
concat_sms[concat.reference][concat.number] = sms.text
print(u'== Partial message received ==\n[{0}/{1}] reference{2}\n'.format(len(concat_sms[concat.reference]), concat.parts, concat.reference))
if len(concat_sms[concat.reference]) == concat.parts:
sortedParts = sorted(concat_sms[concat.reference].iteritems())
message = "".join([x[1] for x in sortedParts])
del concat_sms[concat.reference]
else:
message = sms.text
if message:
print(u'== SMS message received ==\nFrom: {0}\nTime: {1}\nMessage:\n{2}\n'.format(sms.number, sms.time, message))
date = datetime.today().strftime('%Y%m%d%H%M%S%f')
# Uncomment to save the SMS in a file
#with open('/path/to/messages/' + date + '.txt', 'w') as the_file:
# the_file.write('{0}:{1}'.format(sms.number, sms.text))
def checkStoredSms(modem):
# print('Processing stored SMS...')
modem.processStoredSms(False)
threading.Timer(10.0, checkStoredSms, [modem]).start()
def main():
print('Initializing modem...')
# Uncomment the following line to see what the modem is doing:
#logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
modem = GsmModem(PORT, BAUDRATE, smsReceivedCallbackFunc=handleSms)
modem.smsTextMode = False
modem.connect(PIN)
threading.Timer(10.0, checkStoredSms, [modem]).start()
print('Waiting for new SMS message...')
myRemoteSMSHandler = RemoteSMSHandler(modem)
daemon = Pyro4.Daemon.serveSimple({
myRemoteSMSHandler: 'RemoteSMSHandler',
}, host="127.0.0.1", port=9091, ns=False, verbose=False)
daemon.requestLoop()
if __name__ == '__main__':
main()
#!/usr/bin/env python
import Pyro4
import sys, getopt
myRemoteSMSHandler = None
def sendSMS(to, message):
print(myRemoteSMSHandler.sendSMS(to, message))
def main(argv):
global myRemoteSMSHandler
myRemoteSMSHandler = Pyro4.Proxy("PYRO:RemoteSMSHandler@127.0.0.1:9091")
messageReceipt = ''
messageText = ''
try:
opts, args = getopt.getopt(argv,"ht:m:",["to=","message="])
except getopt.GetoptError:
print 'sendsms.py --to=<receipient_number> --message=<your_message>'
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print 'sendsms.py --to=<receipient_number> --message=<your_message>'
sys.exit()
elif opt in ("-t", "--to"):
messageReceipt = arg.strip()
elif opt in ("-m", "--message"):
messageText = arg.decode("string_escape")
sendSMS(messageReceipt, messageText)
if __name__ == "__main__":
main(sys.argv[1:])
@BernardOOO

This comment has been minimized.

Copy link

BernardOOO commented Nov 11, 2019

Hi,
thanks for your scripts.
I have an issue with the send script :
Here is the message :

pi@alarme:~ $ python2.7 python-gsmmodem-advanced-send.py --to=06XXXXXXX --message=message3
Traceback (most recent call last):
File "python-gsmmodem-advanced-send.py", line 33, in
main(sys.argv[1:])
File "python-gsmmodem-advanced-send.py", line 30, in main
sendSMS(messageReceipt, messageText)
File "python-gsmmodem-advanced-send.py", line 9, in sendSMS
print(myRemoteSMSHandler.sendSMS(to, message))
File "/home/pi/.local/lib/python2.7/site-packages/Pyro4/core.py", line 185, in call
return self.__send(self.__name, args, kwargs)
File "/home/pi/.local/lib/python2.7/site-packages/Pyro4/core.py", line 467, in _pyroInvoke
data = serializer.deserializeData(msg.data, compressed=msg.flags & message.FLAGS_COMPRESSED)
File "/home/pi/.local/lib/python2.7/site-packages/Pyro4/util.py", line 171, in deserializeData
return self.loads(data)
File "/home/pi/.local/lib/python2.7/site-packages/Pyro4/util.py", line 614, in loads
return self.recreate_classes(serpent.loads(data))
File "/home/pi/.local/lib/python2.7/site-packages/Pyro4/util.py", line 416, in recreate_classes
return self.dict_to_class(literal)
File "/home/pi/.local/lib/python2.7/site-packages/Pyro4/util.py", line 633, in dict_to_class
return super(SerpentSerializer, cls).dict_to_class(data)
File "/home/pi/.local/lib/python2.7/site-packages/Pyro4/util.py", line 395, in dict_to_class
raise errors.SerializeError("unsupported serialized class: " + classname)
Pyro4.errors.SerializeError: unsupported serialized class: gsmmodem.exceptions.CommandError
pi@alarme:~ $

Can you help me please?
Thanks,
Bernard.

@stevecohenfr

This comment has been minimized.

Copy link
Owner Author

stevecohenfr commented Nov 11, 2019

@BernardOOO can you please check your Pyro4 version ?

$> sudo pip freeze | grep Pyro4
Pyro4==4.76

If you haven't this Pyro version please try to replace your version by this one :

pip uninstall Pyro4
pip install --upgrade Pyro4==4.76

Edit

It seems that the modem returns an error in response to an AT command. I updated python-gsmmodem-advanced-read.py to catch the exception and display it to the send command. Please try again and you will see what's wrong.

Steve

@BernardOOO

This comment has been minimized.

Copy link

BernardOOO commented Nov 12, 2019

Hi Steve,
thank you to consider my problem.

1 - Pyro4 installed version is 4.77
2 - Successfully installed version 4.76
And ... same problem.

3 - installed updated version of python-gsmmodem-advanced-read.py :
(after a reboot to kill any Pyro4 instance)
pi@alarme:~ $ python2.7 python-gsmmodem-advanced-read.py &
[1] 654
pi@alarme:~ $ Initializing modem...
Waiting for new SMS message...

Note : messages are NOT received ! (With prior version, messages were received normally)

pi@alarme:~ $ python2.7 python-gsmmodem-advanced-send.py --to=06XXXXXX --message=message3
Failed to send SMS: 0021000AA16058840938000008EDF27C1E3E9767

Does it says anything to you ?

Bernard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.