GSM modem sends SMS including some AT command in the text - python

In our SMS server we have an old GSM modem(Siemens iRZ ES75iT) connected by COM port.
We have a python script which allows to send SMS messages.
Here is the code of sms sender function:
def sendsms(to, message):
message = message.replace('#', '\0')
if (len(message) > 140 ):
message = message[0:140]
print "Connecting phone"
ser = serial.Serial('/dev/ttyS0', 115200, timeout=12)
time.sleep(1)
ser.write('AT\r')
time.sleep(1)
print "AT"
ser.write('AT+CMGD="ALL"\r')
time.sleep(2)
print "AT+CMGDA=DEL ALL"
ser.write('AT+CMGF=1\r')
time.sleep(1)
print "AT+CMGF=1, text mode"
ser.write('''AT+CMGS="''' + to + '''"\r''')
time.sleep(2)
ser.write(message + "\r")
time.sleep(3)
ser.write(chr(26))
time.sleep(1)
print message
print "disconnecting"
ser.flush()
ser.close()
The script usually working as expected but sometimes we get SMS containing "AT" string in the text, like
"**AT** <text we expect to see>"
or
"<text we expect to see> **AT**"
The question is why we are getting such text in the message and how to avoid it? Thanks in advance.

This is an issue related to at command echo, every time you send an AT command it is echoed on serial. We have python scripts for sending sms.
what we normally do is disable the echo before sending any AT command.
send this command
ser.write('ATE0\r')
This command will turn off the echo
before sending
ser.write('AT')
Hope this helps

Related

Using Python to Automate SMS reply using Raspberry pi w/ Quectel EC25

I made a 4g hotspot last year with a Quectel ec25 and raspberry pi, it has worked just fine for this purpose. Earlier this year I wanted to expand its capabilities to automatically reply to text messages with status updates for certain systems. I was able to figure out sending and receiving a text message with AT commands just fine but I am having trouble getting python to recognize and respond to a text message with key words. I found this code,
http://www.python-exemplary.com/index_en.php?inhalt_links=navigation_en.inc.php&inhalt_mitte=raspi/en/gsm.inc.php, and have modified it slightly to make the EC25 work with the USB serial.
I have 2 SSH sessions going at once, one with the command line up and the other with a minicom session to monitor serial. the EC25 is sending indications to the Pi that it is receiving a message, its output when a message is received is "+CMTI: "ME",0" but the pi has no response to it. The code seems to be unresponsive on this part. it will print "listening for incoming SMS..." but then it will never go beyond that, even when it receives text messages.
reply = ser.read(ser.inWaiting())# Clean buf
print "Listening for incoming SMS..."
while True:
reply = ser.read(ser.inWaiting())
if reply != "":
I have tried it with just ser.read() and ser.inWaiting() but that sends it into a bad feedback loop.
Here is my code.
# SIMSMS1.py
# pip install pyserial
import RPi.GPIO as GPIO
import serial
import time, sys
import datetime
P_BUTTON = 24 # Button, adapt to your wiring
def setup():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(P_BUTTON, GPIO.IN, GPIO.PUD_UP)
SERIAL_PORT = "/dev/ttyUSB3" # Raspberry Pi 3
ser = serial.Serial(SERIAL_PORT, baudrate = 115200, timeout = 5)
setup()
ser.write("AT+CMGF=1\r") # set to text mode
time.sleep(1)
ser.write('AT+QURCCFG="urcport","usbmodem"\r') #set URC Indication
time.sleep(1)
ser.write('AT+CPMS="ME","ME","ME"\r') #set memory to Mobile equipment message storage
time.sleep(1)
ser.write('AT+CMGD=1,4\r') # delete all SMS
time.sleep(1)
reply = ser.read(ser.inWaiting())# Clean buf
print "Listening for incoming SMS..."
while True:
reply = ser.read(ser.inWaiting())
if reply != "":
ser.write("AT+CMGR=1\r") # read message
time.sleep(3)
reply = [ser.read(ser.inWaiting())]
print "SMS received. Content:"
print reply
if "getStatus" in reply:
t = str(datetime.datetime.now())
if GPIO.input(P_BUTTON) == GPIO.HIGH:
state = "Button released"
else:
state = "Button pressed"
ser.write('AT+CMGS="+1xxxxxxxxxx"\r') #designate phone number
time.sleep(3)
msg = "Sending status at " + t + ":--" + state
print "Sending SMS with status info:" + msg
ser.write(msg + chr(26))
time.sleep(3)
ser.write('AT+CMGD=1,4\r') # delete all messages
time.sleep(3)
ser.read(ser.inWaiting()) # Clear buf
time.sleep(5)
this is the output of on the serial, the last line is a message being received
AT+CMGF=1
OK
AT+QURCCFG="urcport","usbmodem"
OK
AT+CPMS="ME","ME","ME"
+CPMS: 0,255,0,255,0,255
OK
AT+CMGD=1,4
OK
+CMTI: "ME",0
I know it has something to do with the "reply = ser.read(ser.inWaiting())" but i cant figure out what to write to make it work. Thank you in advance
The easiest way might be polling the message received.
Maybe the EC25 has some possible gpio. Once any message comes, the gpio would generate a pulse signal.

+CME ERROR: invalid paremeter

I'm trying to send SMS from my RaspberryPi using my own script in python. I'm using serial port on GPIO on the RPi to communicate with GSM modem. I have selected TEXT MODE sms format, listed smses, etc and it all works fine until it comes to sending a sms. When I want to send it I get error like in the tittle.
To quit sending a message I press esc button, press enter (to send it via serial) and it works great (modem sends back 'OK')
I know that to send a message, after the message content I have to send ctrl-z. Ofc in linux when i press ctrl-z i stop the program so it's impossible to press those keys and then enter. Thats why i made a function to send sms where i put ctrl-z char/sign.
When i run the program modem responds with an error like in the tittle(+CME ERROR: invalid paremeter or if you'd like the error code: +CME ERROR: 3518) I know this may seem stupid but I've been looking for an answer for two days and I've tried chr(26).encode(), "\x1a", "\x1A" (don't even know if there's a difference), I've tried to send it with a message content, separatly but nothing works
I may do something wrong but I have no idea what. So I post some code and datasheet screen how to send a message.
Sending a sms:
def sendSMS(self, phoneNumber=111111111, smsContent=""):
# if phoneNumber==0:
if phoneNumber!=111111111:
print("Type phone number in: (without prefix +48): ", end="")
phoneNumber = input()
try:
phoneNumber = int(phoneNumber)
except Exception:
print("Type in an integer")
time.sleep(1)
self.sendSMS()
print("Type text message content (press ENTER to send): ")
smsContent = str(input())
char_CtrlZ = "\x1a"
quote = "\""
command = "AT+CMGS=" + quote + str(phoneNumber) + quote + "," + quote + "129" + quote
message = smsContent + char_CtrlZ
self.serialConnection.send(command)
time.sleep(1)
self.serialConnection.receive()
time.sleep(1)
if self.checkModemResponse()==True: #here I send empty string (few times, if needed) until modem responses with '>'
print("No '>' in modem response")
print("Message did not send")
else:
self.serialConnection.send(message, True, False)
time.sleep(2)
self.serialConnection.receive(True, True, True)
time.sleep(1)
if self.serialConnection.responseState=="COMPLETE_OK":
print("Your message has been sent!")
def checkModemResponse(self, attempt=3):
#I have 5 states of response: UNKNOWN; COMPLETE_OK - modem responses with OK; COMPLETE_ERROR - modem responses with ERROR; UNCOMPLETE - modem responses correctly but without ERROR or OK; EMPTY modem responds correctly but with empty string
isUncomplete = True
if self.serialConnection.responseState!="UNCOMPLETE":
isUncomplete = False
attempt -= 1
if attempt > 0:
print("Trying again..")
someString = "attempt: " + str(attempt)
self.serialConnection.send(someString)
time.sleep(1)
self.serialConnection.receive(True, True, True)
time.sleep(1)
if self.serialConnection.responseState!="UNCOMPLETE":
self.checkModemResponse(attempt)
return isUncomplete
And sending a command over serial:
def send(self, messageToSend, printWhatIsSent=True, addCR=True):
if addCR==False:
command = messageToSend
else:
command = messageToSend + "\r"
if self.serialState==self.SERIAL_STATE[IDLE] and self.serialConnection.isOpen():
self.responseState = self.RESPONSE_STATE[UNKNOWN]
self.serialState = self.SERIAL_STATE[SENDING]
commandToSendInBytes = self.str2byte(command)
self.serialConnection.write(commandToSendInBytes)
self.serialState = self.SERIAL_STATE[IDLE]
if printWhatIsSent==True:
print(">>>>> command sent: " + messageToSend)
else:
print("!!!ERROR: COMMAND DID NOT SEND!!!")
self.serialConnection.flushOutput()
How to send an SMS: +CMGS datesheet screenshot

Python sending sms via usb serial huawei dongle

I'm currently sending sms in python using this code, but sometimes it is unstable. It went straight to "send successfully" but the other party did not receive any message. Is there any other ways to send sms through the dongle? Much appreciated.
This is the code.
class TextMessage:
def __init__(self, recipient="XXXXXXXX", 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/ttyUSBSMS', 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()
sms = TextMessage("XXXXXXXX","This is the message to send.")
sms.connectPhone()
sms.sendMessage()
sms.disconnectPhone()
print "sent successfully"
Good python gsm modem library:
https://github.com/faucamp/python-gsmmodem
You say that sometimes it is unstable, so I assume that it does sometimes send correctly. On that basis, I imagine that the code is fine. The answer at Python sending many sms via usb serial uses slightly different arguments, which may be worth investigating.
Unless you have a commercial plan, SMS is not guaranteed to arrive in any particular hurry. You can send two messages a minute apart, and have the second one arrive immediately and the first one arrive 5 hours later. Have you waited for a 24 hour period to see if the messages ever arrive?

Python: socket.recv() doesn't receive push messages

Python: socket.recv() doesn't receive push messages
Hello,
I'm coding a socket based IMAP client in Python3 which successfully establishes a connection to the server, succussfully transmits the IDLE command but then fails to receive incoming data from the server.
If you are wondering why I do not use libimap or sth., the answer is easy: I just want to implement an IDLE command-supporting python client which must be written without that library.
An extract:
import socket
def runIMAPPeek():
#socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(29 * 60)
#connection
s.connect((IMAP_SERVER , 443))
#login
data = b"a1 LOGIN " + USER + b" " + PASSWORD + b"\n"
s.sendall(data)
reply = read(s)
#Idle loop
#As in RFC 3501 connection will be reinitialized every 29 minutes
while True:
# Idle command
print("#Sending IDLE...")
data = b"a2 IDLE\n"
s.sendall(data)
reply = read(s)
if reply.startswith("+ idling"):
print(" #idling.")
else:
print(" #Unexpected answer: {}".format(reply))
#sys.exit()
# waiting for incoming mails ----------------------------------
try:
push_msg = read(s)
# got push message = new message arrived
getNewEnvelope(s, push_msg)
except socket.timeout:
# timeout
print(" #timeout. Reinitializing IDLE...")
#TODO: except (KeyboardInterrupt, SystemExit)
# Quit Idle
data = b"DONE\n"
write(s, data)
reply = read(s)
if reply.startswith(prefix_str + " OK"):
print(" #quit idling.")
else:
print(" #Unexpected answer: {}".format(reply))
#sys.exit()
def read(s):
"""Read socket data, print it, convert to string, replace new lines
and return it.
"""
print("#Receiving...", end=" ")
reply = s.recv(4096)
reply = str(reply)[2:-1] #convert and remove byte indicators
reply = reply.replace("\\r\\n", "\n")
print(reply)
return reply
The problem is marked with the "----". Although messages are received in the mailbox, python does not react but remains in the idling/receiving state. In fact, the print line above the s.recv() command isn't even printed.
I tried everything successfully with Telnet, so there is no server problem.
In addition to my comment above, you have never selected INBOX. You will not receive any push messages, because you haven't told it what folder you want. Technically, IDLE is not valid in the unselected state.
Constructs like this one:
if reply.startswith("+ idling"):
are completely non-compliant. The IDLE RFC specifies that the client shall expect a continuation request, not this particular string (which also happens to be a continuation request).

Serial communication between two Linux running laptops using Python

I'm trying to send and receive messages between two Linux running laptops via serial communication using Python. The receiver system must see the message "waiting for the message" until it receives the message from the sender. I was searching for sample code to test this. The sample code I have for the sender is as follows:
import serial
com = serial.Serial('/dev/ttyUSB0',baudrate=115200)
com.write('2')
com.close()
But I cannot figure out what to put for the receiver code, where it will display a message on the receivers display as "waiting" and once the message is received it should display "received".
Does anyone have a sample code to work this out?
Reading a serial device is as easy as reading a file:
import serial
com = serial.Serial('/dev/ttyUSB0',baudrate=115200)
print "Waiting for message"
char = com.read(1)
print char
com.close()

Categories