Can anyone help me to send and receive SMS using AT commands in Python?
In case it matters, I'm using Fedora 8.
Which phone will be better with Linux (Nokia, Sony Ericson, Samsung,.....)?
Will all phones support sending and receiving SMS using AT commands?
Here's some example code that should get you started (in Python 3000):
import time
import serial
recipient = "+1234567890"
message = "Hello, World!"
phone = serial.Serial("/dev/ttyACM0", 460800, timeout=5)
try:
time.sleep(0.5)
phone.write(b'ATZ\r')
time.sleep(0.5)
phone.write(b'AT+CMGF=1\r')
time.sleep(0.5)
phone.write(b'AT+CMGS="' + recipient.encode() + b'"\r')
time.sleep(0.5)
phone.write(message.encode() + b"\r")
time.sleep(0.5)
phone.write(bytes([26]))
time.sleep(0.5)
finally:
phone.close()
You need to do two additional things:
Encode the message in the appropriate format (mostly GSM 03.38, there's a handy translation table at unicode.org). If you really don't care about any characters other than ASCII, you can just check if every character is in string.printable.
Check the length of the message (I'm not sure if it's to do with the encoding, but it's sometimes 140 characters, sometimes 160).
You can use phone.readall() to check for errors, but it's best to make sure your message is OK before you send it off to the phone. Note also that the sleeps seem to be necessary.
Most phones will understand this. In order to get my old Nokia C5 to open up the serial connection, I had to select "PC Suite" from the menu that pops up when you insert the USB cable. This should work equally well over Bluetooth.
The code uses the PySerial package, available for python 2 and 3.
See also:
How do i go about writting a program to send and receive sms using python?
to see send sms using At command this will help.
import serial
import time
class TextMessage:
def __init__(self, recipient="+2348065777685", 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('COM70', 460800, timeout=5, xonxoff = False, rtscts = False, bytesize = serial.EIGHTBITS, parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE)
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("+2348063796720","Mummy i sent this message from my computer")
sms.connectPhone()
sms.sendMessage()
sms.disconnectPhone()
print "message sent successfully"
To recieve sms using At command this should help
import serial
import time
import sys
class HuaweiModem(object):
def __init__(self):
self.open()
def open(self):
self.ser = serial.Serial('COM70', 406800, timeout=5)
self.SendCommand('ATZ\r')
self.SendCommand('AT+CMGF=1\r')
def SendCommand(self,command, getline=True):
self.ser.write(command)
data = ''
if getline:
data=self.ReadLine()
return data
def ReadLine(self):
data = self.ser.readline()
print data
return data
def GetAllSMS(self):
self.ser.flushInput()
self.ser.flushOutput()
command = 'AT+CMGL="REC UNREAD"\r\n'#gets incoming sms that has not been read
print self.SendCommand(command,getline=True)
data = self.ser.readall()
print data
h = HuaweiModem()
h.GetAllSMS()
Talking to the phone is easy. You just need to open the appropriate /dev/ttyACM* device and talk to it. Which phone is trickier. Any phone that supports "tethering" and the full AT command set for SMS messages should be fine.
I would suggest replace the time.sleep with condition loop waiting for the response from the modem "OK" before continue next state.
Related
I am playing around with bidirectional serial communication between my PC and a STM32 development board. I am using Python 3.7 with PySerial 3.4 to open the serial port and receive/transceive messages from/to the dev board. Everything is working as expected except when I try to read and print multiline messages. In this case I only get the first line of the message.
The program on the microcontroller is such, that I get a multiline help-message back, if I send 'H' via serial to the controller board.
The multiline message the dev board is sending back looks like this:
"HELP\r\nList of commands:\r\nH: Display list of commands\r\nS: Start the application"
So I am expecting to see the following printout:
HELP
List of commands:
H: Display list of commands
S: Start the application
But instead I only get:
HELP
If I connect to the port with PuTTY and send 'H' manually, I get the full message; so I know that it is not a problem of my microcontroller program.
My python code looks like this:
import serial
import io
class mySerial:
def __init__(self, port, baud_rate):
self.serial = serial.Serial(port, baud_rate, timeout=1)
self.serial_io_wrapped = io.TextIOWrapper(io.BufferedRWPair(self.serial, self.serial))
# receive message via serial
def read(self):
read_out = None
if self.serial.in_waiting > 0:
read_out = self.serial_io_wrapped.readline()
return read_out
# send message via serial
def write(self, message):
self.serial.write(message)
# flush the buffer
def flush(self):
self.serial.flush()
commandToSend = 'H'
ser = mySerial('COM9', 115200)
ser.flush()
ser.write(str(commandToSend).encode() + b"\n")
while True:
incomingMessage = ser.read()
if incomingMessage is not None:
print(incomingMessage)
Any help would be much appreciated.
You need to wait for new data after each line. Based on that, your read method need to be modified as below:
def read(self):
read_out = None
timeout = time.time() + 0.1
while ((self.serial.in_waiting > 0) and (timeout > time.time())):
pass
if self.serial.in_waiting > 0:
read_out = self.serial_io_wrapped.readline()
return read_out
I'm using today for a project a GSM/GPRS RSPI module. My job is to send, with AT commands, files to a FTP server (it's working by a simple program in Python or with putty by sending all AT commands one by one).
Today, to simplify my code, i chose to translate the code in object.
Also, i create my class with all my methods like send SMS, connectGPRS, sendFTP... (these methods do not appear to simplify the code)
But when i'm launching my program, i don't receive my confirm's reply from the module.
When isReady() start, the program send serial command to test the module. But i don't have any reply. My serial port configuration seems like right (debug() return ttyAMA0), and i can control my module by using Putty. But when i'm doing a short circuit with Tx and Rx, i can't see the request from the program on Putty.
Then my program stop in line sys.exit(0) with ser.isReady() returning false.
So my question is : It is possible to use Serial port, like i used it, in object programming ? Or do i make a mistake in my code ?
Regards. (sry btw for my frenchglish)
import serial
print("Reset du module")
resetModem()
time.sleep(5)
ser = ConnexionModule(SERIAL_PORT, 9600, 5)
if not ser.isReady():
print("Failed reboot, maybe a another program connected on serial, or the device isn't lauched")
sys.exit(0)
#debug() is a print function
def debug(text):
if VERBOSE:
print("Debug:---", text)
# This class is in reality in a another file imported in main
class ConnexionModule():
def __init__(self,serial_port,baudrate,timeout):
self.ser = serial.Serial(serial_port, baudrate, timeout)
# Testing if the module is ready to be used
def isReady(self):
# Resetting to defaults
cmd = 'ATZ\r'
# When i send 'ATZ' the module return 'OK'
debug("Cmd: " + cmd)
self.serialwrite(cmd,2)
reply = self.ser.read(self.ser.inWaiting())
reply = reply.decode("utf-8")
time.sleep(8) # Waiting for a reply
debug("Reply: " + reply)
return ("OK" in reply)
def serialwrite(self,cmd,slp):
debug("Sending:")
debug(self.ser.port)
debug(cmd)
self.ser.write(cmd.encode())
time.sleep(slp)
This code working :
import serial
print("Reset du module")
resetModem()
ser = serial.Serial(SERIAL_PORT, baudrate = 9600, timeout = 5)
if not isReady(ser):
print("Fail reboot")
sys.exit(0)
def isReady(pserial):
# Resetting to defaults
cmd = 'ATZ\r'
debug("Cmd: " + cmd)
serialwrite(pserial,cmd,2)
reply = pserial.read(pserial.inWaiting())
reply = reply.decode("utf-8")
time.sleep(8)
debug("Reply: " + reply)
return ("OK" in reply)
def debug(text):
if VERBOSE:
print("Debug:---", text)
def resetModem():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(P_RESET, GPIO.OUT)
GPIO.output(P_RESET, GPIO.LOW)
time.sleep(0.5)
GPIO.output(P_RESET, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(P_RESET, GPIO.LOW)
time.sleep(3)
I start learning socket programming and I created a simple server that should replay everything I send to him back to me.
And its work work and I manage to telnet to it and write things.
but I have two problems with my code:
First, every sigh I hit on the keyboard get immediately send and I get it back. it doesn't wait until I press enter.
Second, when I print to the client 'Welcome to the server. Type something and hit enter\n\n' the client see the cmd imput cursor in the middle of the new line, and not in the start of it.
here is part of my code:
#server in local host
class ClientConnection(threading.Thread):
def __init__(self,conn):
threading.Thread.__init__(self)
self.conn = conn
def run(self):
clientthread(self.conn)
#create a new thread for each connection
def clientthread(conn):
conn.send('Welcome to the server. Type something and hit enter\n\n'.encode())
while True:
data = conn.recv(2048).decode()
replay = 'OK....' + data
if not data:
break
conn.sendall(replay.encode())
conn.close()
... #socket get close in the end
How do I make the server response only if I the client press enter? I try to check if the recive = '\n' but it doesn't seem to work.
I will appreciate any help and tips
edit: my second question answard simply
Yes, the client will often send you data as the user types rather then only when the user hits return. Thus, it is up to you to check if the data has a return, and only respond if it does.
data = ""
while True:
chunk = conn.recv(2048).decode()
if not data:
break
# try to separate the chunk by newline, to see if you got one.
while True:
split = chunk.split("\r\n", num=1)
data += split[0]
if len(split) == 1:
break
# Now we have a completed newline, so send the response
replay = 'OK....' + data
conn.sendall(replay.encode())
data = ""
conn.close()
I've tried looking about for an answer but I can't seem to find one that answers my specific problem.
Perhaps I don't know how to articulate the problem correctly.
I think I've pinpointed what it is, but the thing is I just don't know how to fix it.
EDIT: I was trying to use two clients on one TCP Socket. Can't do that. I'll have to think of another way. Solved, I guess.
So what I've got is are
1: Two Clients
2: One Server
The objective is this:
Have the server distribute new usernames to all the clients as they connect.
This is what happens when I run the program:
Server: Define Host, and Port, initialize it. Check
Client 1: Connects to the server. Check
Client 1: Once connected, sends a string to the server. Check
Server: Receives a string, checks if the string is in a list is created. If it is: Pass, if it's not, send to everyone the new string. Check
Client 1: [Now waiting to receive data] Recieves data, checks if the string received matches the one it sent. If it does, print("It's one of ours!"), else, make the new string = to Client 2 Username. Check
Client 2: Connects to server: Check
Server: [If it receives a string, prints it.] (Works) Checks if the new string is in the list. [It isn't] So It sends the new username to everyone, and then prints ("Sent to everyone") Check
But, when client 2 receives the string, it prints it. However, client 1 never recives the string.
And when running client one in IDLE, I noticed something went wrong as Client 1 tried to receive the data. (The while loop that the data = s.recv began looping real fast, instead of waiting)
I've asked around in chat, but it seems nobody's around right now. I've tried looking this up but I really can't find an answer. What I suspect is happening is that when my server sends to 'connection' the second time, it somehow overrides the original client connection.
Here's my server code:
from socket import *
import threading
import os
import csv
Username_List = []
host = input("Host: ")
port = input("Port: ")
ss = socket(AF_INET,SOCK_STREAM)
ss.bind((host,int(port)))
ss.listen(2)
while True:
try:
connection,address = ss.accept()
data = connection.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data in Username_List:
pass
else:
Username_List.append(translated_data)
connection.sendall(translated_data.encode())
print("Sent new username to everyone")
except IOError:
connection.close()
print("An exception with a connected user occured")
break
And here is my client code: [The only difference between client 1 and 2 is I changed the username variable]
# Sample Username Client Service Handler.
from socket import *
import threading
import os
import csv
Username = ("Owatch")
host = input("Host: ")
port = input("Port: ")
try:
ss = socket(AF_INET,SOCK_STREAM)
ss.connect((host,int(port)))
except IOError:
print("Aw no man")
ss.send(Username.encode())
while True:
try:
print("Waiting to Recieve Data")
data = ss.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data == Username:
print("It's one of ours!")
else:
Client_Username = translated_data
print (Client_Username)
except Exception as e:
print (vars(e))
If you could please help I'd be grateful.
If you know of an answer to my question that's already been asked, please tell me and I'll remove this post to avoid breaking rules. Thanks!
Right then I started with what you had then changed it till it worked what I've done is created a client class which starts a thread with each connection and adds it to a list of threads (please if I'm doing something horribly wrong smarter people correct me), the thread runs gets some data checks if that's in the list of user names if its not sends out a message to all the clients in the thread list with that name then the thread just chills out. Anyway on to the code.
SERVER!!!
import csv
class client(threading.Thread):
Username_List = []
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
def run(self):
print "Client thread started"
data = self.conn.recv(1024)
print "Received: {0}".format(data)
if data in client.Username_List:
self.send_msg("Welcome Back!")
else:
for cnt in threadz:
cnt.send_msg(data)
print("Sent new username to everyone")
client.Username_List.append(data)
while True:
# dont need nothing now
pass
def send_msg(self,msg):
self.conn.send(msg)
host = input("Host: ")
port = input("Port: ")
ss = socket() #AF_INET,SOCK_STREAM)
ss.bind((host,int(port)))
print "Server Opening on port: {0}".format(port)
ss.listen(2)
threadz = []
print "Begining Wait for connections"
while True:
try:
connection, address = ss.accept()
print "Got ONE!"
c = client(connection)
print "Recevied connection from:{0} On port:{1}".format(address[0],address[1])
c.start()
threadz.append(c)
print "Client appended to threadz, currently {0} threadz active".format(len(threadz))
except IOError,KeyboardInterrupt:
connection.close()
print("An exception with a connected user occured")
break
The CLIENT:
# Sample Username Client Service Handler.
from socket import *
import threading
import os
import csv
Username = ("ShyGuy")
host = input("Host: ")
port = input("Port: ")
try:
ss = socket() #AF_INET,SOCK_STREAM)
ss.connect((host,int(port))) #I was using ("localhost",1234) for testing
ss.send(Username)
except IOError:
print("Aw no man")
print("Waiting to Recieve Data")
while True:
try:
data = ss.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data == Username:
print"Name: {0} has been registered on server!".format(translated_data)
else:
Client_Username = translated_data
print "New client name received: {0}".format(Client_Username)
except Exception as e:
print (vars(e))
That works on python 2.7 with two clients locally. Needs to use a semaphore to stop the threads printing at the same time as the main server loop prints: http://en.wikipedia.org/wiki/Semaphore_(programming)
This code does nothing graceful with client disconnects, but once you can work with the exceptions that a raised when that happens I'm sure you'll learn some more.
I found this code for a simple chat that uses serial ports to communicate, and I wanted to see it work. I googled for a while and found com0com to simulate the RS-232 connection as I don't have a cable, but now I'm stumped and have no idea how to actually make this work
The code (in python):
from serial import *
from threading import Thread
class Receiver(Thread):
def __init__(self, serialPort):
Thread.__init__(self)
self.serialPort = serialPort
def run(self):
text = ""
while (text != "exit\n"):
text = serialPort.readline()
print ("\n machine1: " + text)
self.serialPort.close()
class Sender(Thread):
def __init__(self, serialPort):
Thread.__init__(self)
self.serialPort = serialPort
def run(self):
text = ""
while(text != "exit\n"):
text = raw_input("Type your message>>") + "\n"
self.serialPort.write(text)
self.serialPort.close()
serialPort = Serial("\\\\.\\CNCA0")
send = Sender(serialPort)
receive = Receiver(serialPort)
send.start()
receive.start()
Thanks in advance.
You first need to use com0com to create a serial port with a loop-back, i.e. the output of the port is connected back to the input. This way, everything you send from the Serial Port will received back.
The code snippet uses the Sender class to read the command prompt input. Whatever you write is sent through the serial port. The Receiver class spawns a thread and waits something to be received from the serial port. When a full line is received, it is typed in the command prompt.
Things to notice:
Make sure your serial port is actually named CNCA0
Press Enter for a message to appear
Type 'exit' and Enter to stop the program
I'm also interested in similar code.
Unfortunately till tomorrow I will be unable to test it on 2 computers.
Working only on Tx, On Rx is not working yet.
import serial
from threading import Thread
serialPort = serial.Serial(port='/dev/ttyUSB0', baudrate=9600)
class Receiver(Thread):
def __init__(self, serialPort):
Thread.__init__(self)
self.serialPort = serialPort
def run(self):
text = ""
while (text != "exit\n"):
text = serialPort.readline()
print ("\n machine1: " + text)
class Sender(Thread):
def __init__(self, serialPort):
Thread.__init__(self)
self.serialPort = serialPort
def run(self):
text = ""
while(text != "exit\n"):
text = raw_input("$:")
self.serialPort.write(' ' + text + '\n')
send = Sender(serialPort)
receive = Receiver(serialPort)
send.start()
receive.start()