I have a GSM modem that disconnect after a while, maybe because of low signal. I am just wondering is there an AT command that can detect the disconnection and re-establish a reconnection.
Is there a way in code (preferably python) I can detect the disconnection and re-establish a reconnection?
Gath
Depending on what type of connection, circuit switched (CS) or packet switched (PS), the monitoring will be a little bit different. To detect a disconnect you can enable UR (unsolicited result) code AT+CPSB=1 to monitor PDP context activity (aka packet switched connections). For circuit switched calls you can monitor with the +CIEV: UR code enabled with AT+CMER=3,0,0,2.
To re-establish the connection you have to set up the connection again. For CS you will either have to know the phone number dialed, or you can use the special form of ATD, ATDL [1] which will dial the last dialed number. You can use ATDL for PS as well if the call was started with ATD (i.e. "ATD*99*....") which is quite common, but I do not think there is any way if started with AT+CGDATA for instance.
However, none of the above related to ATD matters, because it is not what you want. For CS you might set up a call from your python script, but then so what? After receiving CONNECT all the data traffic would be coming on the serial connection that your python script are using. And for PS the connection will not even finish successfully unless the phone receives PPP traffic from the PC as part of connection establishment. Do you intend your python script to supply that?
What you really want is to trigger your PC to try to connect again, whether this is standard operating system dial up networking or some special application launching it. So monitor the modem with a python script and then take appropriate action on the PC side to re-establish the connection.
[1]
Side note to ATDL: notice that if you want to repeat the last voice call you should still terminate with a semicolon, i.e. ATDL;, otherwise you would start a data call.
Here is how I do it with Telit devices:
I use AT+CGREG=1 to subscribe to unsolicited messages. Extract from documentation:
+CGREG - GPRS Network Registration Status
AT+CGREG=[<n>]
Set command controls the presentation of an unsolicited result code
+CGREG: (see format below).
Parameter:
<n> - result code presentation mode
0 - disable network registration unsolicited result code
1 - enable network registration unsolicited result code; if there is a change in the terminal GPRS network registration status, it is issued the unsolicited result code:
+CGREG: <stat>
And I wait on the modem's serial line for +CGREG messages. When something comes I check to see if stat is 1 (connected to the home network) or 5 (connected in roaming).
NOTE: A different response +CGREG comes when issuing the AT+CGREG? which is not hard to isolate.
You can try to check the signal strength on a regular basis with AT+CSQ. If the signal goes under a given threshold consider that you are disconnected and force a new connection.
You can try the very nice pyserial http://pyserial.sourceforge.net/ Python library to send the AT commands to the modem.
I hope it helps
Related
I want to generate some Modbus traffic, but I can't find any examples. In other words, I want to create a Modbus Simulator.
A good start would be to look at the examples folder.
An easy way to have something up and running is to follow these steps, assuming you have pymodbus installed:
Download and run the syncronous_server.py example from the command line
Download and run on a different command window the syncronous_client.py example.
You are done, from the output of both command lines you will be able to see the Modbus transactions that took place.
If you want to have a continuous stream of Modbus exchanges you can just modify the client to loop somewhere, for instance:
while True:
rr = client.read_holding_registers(1, 1, unit=UNIT)
time.sleep(1)
will keep reading a holding register about once every second.
There is no need to change anything on the server, it will be always listening until you kill it with Ctrl+C
Nothing will prevent you from having a different computer for the server and client as long as both are connected to the same network and you modify the client to point to the server address. In particular (line 70 on the example):
client = ModbusClient('localhost', port=5020)
Change localhost to your server's IP address, maybe something like 192.168.x.y.
In case you are not aware there are many alternatives to pymodbus to generate Modbus traffic. Modpoll is a classic, but you can also look at qModMaster.
If this is a stupid question, please don't mind me. But I spent some time trying to find the answer but I couldn't get anything solid. Maybe this is a hardware question, but I figured I'd try here first.
Does Serial Communication only work one to one? The reason this came up is because I had an arduino board listening for communication on its serial port. I had a python script feed bytes to the port as well. However, whenever I opened up the arduino's serial monitor, the connection with the python script failed. The serial monitor also connects to the serial port for communication for its little text input field.
So what's the deal? Does serial communication only work between a single client and a single server? Is there a way to get multiple clients writing to the server? I appreciate your suggestions.
Multiple clients (e.g. Arduinos) communicating with one server (e.g. a desktop computer) is commonly done with the serial variant:
RS-485
This is a simple method widely used in industrial settings where you want to have many devices connected to one computer via one serial port. This type of arrangement is also called multi-drop, because one cable strings around a building with Tees that tap in and drop lines to each device.
The hardware for this is widely available. You can buy USB serial adapters that provide the hardware interface for a computer. Programmatically the port looks just like an RS232 port. For the Arduino you would just add a transceiver chip. A sea of serial transceivers exists, e.g.
Example computer USB adapter with 485 interface
Sample RS485 transceiver chip from Element14
All the devices hang on the same bus listening at the same time. A simple communication protocol used is just add a device address before every command. For example:
001SETLIGHT1 <- tells Arduino "001" to turn on the light
013SETLIGHT0 <- tells "013" to turn off the light
Any device hanging on the cable ignores commands that do not start with their address. When a device responds, it prepends its address.
001SETLIGHT1DONE <- response from device "001" that the command has been received and executed
The address in the response lets the receiving party know which device was talking.
Well, your question can be quite wide, so I'm going to layer my answer:
On the hardware side, the same pair of wires can work be shared with many devices. It is mostly a question of electronics (maintaining the signal in the good voltage range), and not having all devices writing to the serial port at the same time (or you'll get wreckage).
On the software side, on the host, yes you can share the same serial connection to a device with multiple processes. But that's not straight forward. I'll assume you're using an unix (macos or linux):
in unix, everything is a file, your serial connection is one too: /dev/ttyACM0 on linux, for example.
When you have a process opening that file, it will block it (using ioctl, iirc) so no other process can mess with that file too.
Then, you can input and output to that file using the process that opened it, that's all.
But hopefully, it is still possible to share the connection between processes. One of them would simply be to use the tee command, that will be able to get input from one process, and give it back output, and copy the output to another process. You can also do it from within python, by duplicating the file descriptor.
To easily output stuff that can be redirected the unix way (using pipes), you can use socat: http://www.dest-unreach.org/socat/
here's an usage example:
socat -,raw,echo=0,escape=0x0f /dev/ttyACM0,raw,echo=0,crnl
you may want to tweak it for your needs.
Edit:
I forgot about RS-485, which 'jdr5ca' was smart enough to recommend. My explanation below is restricted to RS-232, the more "garden variety" serial port. As 'jdr5ca' points out, RS-485 is a much better alternative for the described problem.
Original:
To expand on zmo's answer a bit, it is possible to share serial at the hardware level, and it has been done before, but it is rarely done in practice.
Likewise, at the software driver level, it is again theoretically possible to share, but you run into similar problems as the hardware level, i.e. how to "share" the link to prevent collisions, etc.
A "typical" setup would be two serial (hardware) devices attached to each other 1:1. Each would run a single software process that would manage sending/receiving data on the link.
If it is desired to share the serial link amongst multiple processes (on either side), the software process that manages the link would also need to manage passing the received data to each reading process (keeping track of which data each process had read) and also arbitrate which sending process gets access to the link during "writes".
If there are multiple read/write processes on each end of the link, the handshaking/coordination of all this gets deep as some sort of meta-signaling arrangement may be needed to coordinate the comms between the process on each end.
Either a real mess or a fun challenge, depending on your needs and how you view such things.
Short version of my question:
How do I design a single Python script that can listen and respond to inputs received via HTTP or a serial port, and also initiate communications via these channels on its own? My problem is that I don't understand how to design a single script that both (i) uses a web framework to listen on some port for HTTP inputs, and (ii) also does other work that's independent of incoming HTTP requests.
Long version:
I want to use Python to design a system that does the following:
Listens to a serial port for occasional reports. Specifically, I have a network of JeeNode sensors (wireless Arduino-compatible modules) that talk to a central JeeLink, which connects to my computer via USB and talks to my Python script via pySerial.
Listens to a web URL for occasional inputs. Specifically, users send commands to the system via SMS to a Twilio number. Twilio intercepts the SMS messages and posts them to a URL I designate, and I use the Bottle micro web-framework to listen for new HTTP requests.
Responds to both types (serial and HTTP) of inputs. For example, if a user texts the command "Sleep", I want to (i) tell the sensors to go to sleep via the serial port -> JeeLink (which will then forward the command onto the remotes); and (ii) reply to the sender -- and maybe other users -- that the command has been received and is being executed.
Occasionally initiates its own communications to users (via HTTP -> Twilio -> SMS) or remote sensors (via serial -> JeeLink) without any precipitating input event. Two examples: (1) I want to report out to users or remote sensors every N minutes even if I haven't received any new inputs. (2) I want to tell users remotes have actually entered Sleep mode. Because the remotes are battery-powered, they spend most of the time in an inaccessible low-power mode. They can only receive new commands from the JeeLink when they initiate a wireless "check-in" every 5 min. So while technically remotes go to sleep (or wake up, etc.) in response to a user command, commands and responses are effectively independent.
My problem is that all of usage examples of web frameworks I've seen seem to assume that all precipitating events occur via HTTP requests. I can create a Bottle object, and use decorators to bind code to that object that get executed whenever it sees an HTTP request that matches some specified URL path. But I don't know how to do that while simultaneously doing other work that's independent of HTTP events, for example, listening to the serial port.
After struggling a lot, the potential solutions I'm considering now are:
Splitting the functionality into separate scripts. A.py listens for text messages via HTTP and writes the relevant information to some database; B.py continuously reads the database for new records and reacts accordingly, as well as listening to the serial monitor and doing other work. This seems like it would work fine, but it feels inelegant, and I suspect there's a simpler solution I'm unaware of.
Maybe the answer is related to Python decorators? I use various decorators to specify the URL paths that, when a matching HTTP request comes in, execute the code bound to the decorator. So I'm guessing that maybe there's a way to specify some other kind of decorator that, rather than listening for HTTP requests, gets executed when my "main" Python code tells it to? But I don't know enough about decorators to know if this is true.
It seems like you are trying to write an asynchronous application to manage your network of nodes via HTTP. You want to respond to incoming communications on multiple channels as they occur, you want to initiate communications on a schedule, on multiple channels, and you want those two forms of communication to interact. All of these communications are with an outside world that is slow, so it behooves you not to block if you don't need to.
It will probably be easiest to maintain your system if you organize your code into several Python modules, split by their area of concern - serial interface code, HTTP interface code, common processing code-paths, etc. Weave those components together in a central control module, which imports your libraries, and knows how to start and stop cleanly. Then you can test the serial interface independent of the web interface, and potentially reuse some of those Python modules in other projects.
I have a Python test program for testing features of another software component, let's call the latter the component under test (COT).
The Python test program is connected to the COT via a persistent TCP connection.
The Python program is using the Python socket API for this.
Now in order to simulate a failure of the physical link, I'd like to have the Python program shut the socket down, but without disconnecting appropriately.
I.e. I don't want anything to be sent on the TCP channel any more, including any TCP SYN/ACK/FIN. I just want the socket to go silent. It must not respond to the remote packets any more.
This is not as easy as it seems, since calling close on a socket will send TCP FIN packets to the remote end. (graceful disconnection).
So how can I kill the socket without sending any packets out?
I cannot shut down the Python program itself, because it needs to maintain other connections to other components.
For information, the socket runs in a separate thread. So I thought of abruptly killing the thread, but this is also not so easy. (Is there any way to kill a Thread?)
Any ideas?
You can't do that from a userland process since in-kernel network stack still holds resources and state related to given TCP connection. Event if you kill your whole process the kernel is going to send a FIN to the other side since it knows what file descriptors your process had and will try to clean them up properly.
One way to get around this is to engage firewall software (on local or intermediate machine). Call a script that tells the firewall to drop all packets from/to given IP and port (that of course would need appropriate administrative privileges).
Contrary to Nikolai's answer, there is indeed a way to reset the connection from userland such that an RST is sent and pending data discarded, rather than a FIN after all the pending data. However as it is more abused than used, I won't publish it here. And I don't know whether it can be done from Python. Setting one of the three possible SO_LINGER configurations and closing will do it. I won't say more than that, and I will say that this technique should only be used for the purpose outlined in the question.
I am using xmpppy libary to write a XMPP IM robot.
I want to act on disconnects, but I don't know how to detect disconnects. This could happen if your Jabber server crashes or if you have lost your internet connection.
I found the callback, RegisterDisconnectHandler(self, DisconnectHandler), but it didn't work for the network failure, it only works when I explicitly call the method "disconnect".
How do I detect a network failure or server crash?
Did you try waiting 30 minutes after the network failure? Depending on your network stack's settings, it could take this long to detect. However, if you're not periodically sending on the socket, you may never detect the outage. This is why many XMPP stacks periodically send a single space character, using an algorithm like:
Set timer to N seconds
On sending a stanza, reset the timer to N
When the timer fires, send a space.