Introduction
Telit provides example code and documentation to support opening a socket to a server and passing data back and forth. This is great if you’re looking to deploy a bunch of data collection points, but what if you need it to connect to a module with a telnet session? This article will cover how to open a listening socket and how to pass data to the serial port after the socket has connected.
Setup
The GPRS connection is how the module talks to the internet. Depending on the carrier and your individual plan, the module may or may not have a dynamic IP address. A few items are needed from your carrier before you can proceed.
- APN name
- USERID
- PASSWORD
Most phones use a generic APN for internet access. AT&T can setup a custom APN for your use with any special requirements and data plans needed for larger projects. They can provide things like Static IPs or Gateway connections to internal LANS. Other carriers have similar options but I only have experience with AT&T.
def make_connection():
"Establishes connection over internet."
MDM.send('AT#GPRS=0\r', 2)
MDM.receive(5)
MDM.send('AT+CGDCONT=1,"IP","INTERNETTRIAL"\r', 2)
MDM.receive(5)
MDM.send('AT#USERID="trial488@INTERNETTRIAL"\r', 2)
MDM.receive(5)
MDM.send('AT#PASSW="trialpass488"\r', 2)
MDM.receive(5)
MDM.send('AT#FRWL=1,"192.168.1.1","255.255.255.0"\r', 5)
MDM.receive(5)
AT#GPRS=0 disconnects any existing connection. Then the information previously obtained from your provider can be saved to the device. This information is not stored in NVM so you need to include it in your code and provide it after every reboot.
The #FRWL command is important. The device will only allow incoming data from entries that are in the Firewall. If you only have one server, this can be hard coded into the program like this example or what I did was write a list to the NVM and read it every time I reboot the device. I used SMS messages to change that list.
########################################################################
# Firewall Service Processor & Subroutines
def process_FIREWALL(number, SMSmessage):
"Modifies the firewall settings from command."
settings = load_firewall()
if contains(SMSmessage, 'add'):
reply = add_to_firewall(SMSmessage, settings)
elif contains(SMSmessage, 'list'):
reply = list_firewall_settings(settings)
elif contains(SMSmessage, 'rem'):
reply = remove_from_firewall(SMSmessage, settings)
else:
reply = 'Invalid Command'
save_firewall(settings)
sendSMS(number, reply)
MDM.send('AT#SL=1,1,1700\r', 5)
def load_firewall():
"Retrieves the firewall settings."
try:
file = open('FRWL', 'rb')
except IOError:
return []
else:
file_contents = file.read()
file.close()
non_microsoft = file_contents.replace('\r\n', '\n')
non_macintosh = non_microsoft.replace('\r', '\n')
settings = filter(None, non_macintosh.split('\n'))
return settings
def add_to_firewall(SMSmessage, settings):
"Adds IP address to the firewall settings."
start = SMSmessage.index('add')
address = SMSmessage[start+4:start+19].strip()
settings.append(address)
return address + ' added to firewall'
def list_firewall_settings(settings):
"Concatenates the settings for a reply."
reply = ';'.join(settings)
MOD.sleep(15)
return reply
def remove_from_firewall(SMSmessage, settings):
"Removes IP address from the firewall settings."
start = SMSmessage.index('rem')
address = SMSmessage[start+4:start+19].strip()
while address in settings:
settings.remove(address)
return address + ' removed from firewall'
def save_firewall(settings):
"Stores the IP addresses in a file."
MDM.send('AT#FRWL=2,"192.168.4.1","225.255.255.0"\r', 5)
MDM.receive(5)
file = open('FRWL', 'wb')
for address in settings:
MDM.send('AT#FRWL=1,"%s","255.255.255.0"\r' % address, 5)
MDM.receive(5)
file.write(address + '\r\n')
MOD.sleep(5)
file.close()
########################################################################
I’m not going to get into too much detail here because this is just simple file access in Python and SMS message handling was already covered here. In my situation, I wanted to use our external static address to be hardcoded into the module. Other temporary IPs are added and removed as needed. The file FRWL is stored on the module and stays in NVM so the list stays active even after a reboot.
GPRS Connection
After the connection settings and the firewall are in place, all it takes to create the connection is the command AT#GPRS=1.
def request_GPRS_context():
"Activates the GPRS context for internet."
while True:
MDM.send('AT#GPRS=1\r', 5)
MOD.sleep(20)
if MDM.receive(5).find('IP') != -1:
return
The module is not always successful in creating the GPRS connection on the first try. It returns an error unless connection is made. If successful, the module will display the IP address. This can be captured and stored for use in dynamic IP situations. I was using a static IP so that was not needed here.
Now you are connected to the internet. This allows you to access FTP sites or anything else you need to do over the internet connection. I needed the device to wait for my telnet session then pass that info to the serial port. To do this, we first need to open the listening socket.
def open_listening_socket():
"Opens server socket for connections."
while True:
MDM.send('AT#SL=1,1,23\r', 2)
MOD.sleep(20)
if MDM.receive(5).find('OK') != -1:
return
AT#SL opens or closes the socket. 1,1,23 starts listening on port 23 with socket ID1. The socket closure type can also be defined refer to the AT command reference from Telit for more information. I left it at the default which closes the connection when the host disconnects. Something of note that can be frustrating is that the socket will stay open as long as nothing happens. I had problems with it disappearing after an SMS message was received. So after processing each SMS message, I reinitialize the listening port with AT#SL=1,1,23.
Answering the socket is easy. AT#SA answers the connection. The MDM interface will display ‘SRING
’ when a connection is attempted.
########################################################################
# Socket Connection Handlers
def handle_socket_call():
"Forwards socket data over MDM and SER."
MDM.send('AT#SA=1,0\r', 2)
forward = True
while forward:
forward_messages()
MDM2.send('AT#SS\r', 5)
forward_messages()
print forward
forward = MDM2.receive(5).find('#SS: 1,0') == -1
print forward
forward_messages()
MDM.send('AT#SL=1,1,23\r', 5)
def forward_messages(timeout=2):
"Transfers data two ways across MDM and SER."
SER.send(MDM.receive(timeout))
MDM.send(SER.read(), timeout)
########################################################################
In my application, I didn’t want to talk to the module, I needed to talk to external equipment and use it as a WAN to serial gateway. The connection status is checked with AT#SS and this is done on MDM2 interface because the data going back and forth between the module and the WAN connections is on the MDM interface. AT#SS returns a list of all sockets that are open and a closed socket is represented by ‘ID’,0. So scanning for ‘1,0’ tells me when the connecting computer disconnects and I can return the module to listening mode. Passing the data around is simply passing the incoming MDM data to the SER instance and vice versa.
Conclusion
The GRPS connection is a powerful tool for the Telit family of modules. They can be used to poll data or control a facility in a remote location, or just check to see if you left your iron on. This code was written for the GC864-PY module and was only tested on it. Other modules and firmware versions may vary. More information on all the AT commands can be found in the Telit AT Command reference for your particular module. Please refer to my previous articles for more information on using python and handling SMS messages.
History
- 8th November, 2010: Initial version