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

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.

Related

How to constantly get IR Sensor's data from Server to client via Socket

I am working with raspberry pi and want to send data from server (i.e. Raspberry Pi) to client (PC tkinter app). I am using sockets for this purpose. But the thing is that the server end is not sending data constantly to client. It just sends data one time and then stops sending.
I ran the code without transmitting data and it works fine. But as soon as I say, "conn.sendall(str.encode(msg))" it sends it the first time and then stops.
Here is the code from server end (Raspberry Pi).
def ir_sensor(conn):
while True:
if(GPIO.input(8)==True):
print("Obstacle Not detected")
reply = "Obstacle Not detected"
if(GPIO.input(8)==False):
reply = "Obstacle detected"
print("Obstacle detected")
conn.sendall(str.encode(reply))
print("Data has been sent!")
time.sleep(1)
conn.close()
GPIO.cleanup()
And here is the code from client end (PC)
def ir_switch():
global ir_is_on
if ir_is_on:
ir_on_button.config(image=off)
label23.config(text="Obstacle Sensor",fg="red")
ir_is_on =False
get_ir_sensor()
else:
ir_on_button.config(image=on)
label23.config(text="Obstacle Sensor",fg="green")
ir_is_on =True
time.sleep(1)
get_ir_sensor()
def get_ir_sensor():
global ir_is_on
if ir_is_on:
print("getting ir sensor data")
reply = s.recv(1024)
print(reply.decode("utf-8"))
else:
print("Sensor Off")
#root.after(1000, get_ir_sensor)
Please tell me where I'm wrong. The IR sensor is getting the data constantly. But I cannot transmit it to PC.

Python pySerial on Raspberry Pi Zero W: detecting a disconnected serial device

In my project, there's a Raspberry Pi Zero W, linked with Arduino Pro Micro over the serial TX/RX lines (through 5 - 3.3V logic level converter). At power-on, the Arduino starts sending "are you there" command over the serial, until Pi has finished booting and launched a python program that listens on serial port, and it replies with "yes". Then Arduino proceeds with sending regular updates with sensor data.
For some reason not yet understood, the Arduino can disconnect and reboot, while the Pi is still running. And, for some reason, the connection on the Python end is severed in a way that does not raise exception if connection.in_waiting is read.
import serial
import time
ser = serial.Serial('/dev/serial0')
ser.baudrate = 9600
cmd = b''
while True:
time.sleep(1)
print(ser.is_open)
while ser.in_waiting:
ch = ser.read()
if ch == b'\n':
print('New command:', cmd)
cmd = b''
ser.write(b'OK\n')
continue
else:
cmd = cmd + ch
I have tested with this simple code, but in my tests, if I disconnect the Arduino and connect it back, the ser.is_open never is False, and the old connection works just fine also with reconnected Arduino. So, unfortunately I can not exactly replicate the loss of connection scenario when the data stop coming after disconnection. However, in order to investigate further, I'd like to add some monitoring code that would log serial disconnection incidents in file. But is there a way? If connection.is_open is always true, even without Arduino connected, then how one can detect if there is no connection?
The port remains open if there's a disconnection so your example code will loop continuously.
import serial
def connect(port):
return serial.Serial(port, baudrate=9600, timeout=1)
ser = connect('/dev/serial0')
buf = bytearray()
while True:
i = buf.find(b'\n')
if i >= 0:
buf = buf[i + 1:]
ser.write('OK\n')
num_bytes = max(1, min(1024, ser.in_waiting))
data = ser.read(num_bytes)
if data:
buf.extend(data)
else:
# no data to read aka disconnection has occurred
ser = connect('/dev/serial0')
if ser.isOpen():
continue
else:
# could not reconnect
break

GSM modem sends SMS including some AT command in the text

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

How do i debug this USB-Serial connection?

I am trying to talk to a Stanford Research Systems SR760 spectrum analyzer on my mac (10.7.5) via Serial, using a Serial-to-USB adapter to connect to my laptop. I am using the Prolific USB-serial driver. Not sure which but I installed it recently. It probably is the PL2303 one.
Using Python, here's some sample code
import time
import serial
# configure the serial connections (the parameters differs on the device you
# are connecting to)
ser = serial.Serial(
port='/dev/cu.PL2303-0000201A',
baudrate=19200,
parity=serial.PARITY_NONE,
bytesize=serial.EIGHTBITS,
stopbits=serial.STOPBITS_ONE,
rtscts=0,
dsrdtr=0,
timeout=2,
)
if ser.isOpen():
ser.flushInput()
ser.flushOutput()
print """Enter your commands below.\r\nInsert "exit" to leave the
application."""
while 1:
# get keyboard input
input = raw_input(">> ")
if input == 'exit':
ser.close()
exit()
else:
ser.write(input + '\r')
out = ''
# let's wait one second before reading output (let's give device
# time to answer)
lines = 0
while 1:
time.sleep(1)
out = out + ser.readline()
lines = lines + 1
if lines > 5:
break
print "read data: " + out
Using the SR760's manual, I send it: *IDN?, a basic "identify" command. I expect for something to pop up in my terminal, nothing does. It just times out. However, if I look at the send queue on the SR760, it will show the identity string, and in fact responds to a bunch of different commands. I'm just not getting anything on my computer and that is the problem. I know it is supposed to work that way because my colleague wrote code that words on his computer (a windows laptop).
How do I even start debugging this? I've tweaked the timeout, and confirmed the sr760 had the same parameters I was expecting.

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).

Categories