I've got a working script that is using PySerial to communicate with a modem using AT commands. However, this communication is cluttering my formatted output as all AT commands sent and modem responses are echoed to stdout:
serial.write("ATE1\r")
Result on stdout:
ATE1
OK
I've tried to create my own output class which redirects sys.stdout and sys.stderr to my own descriptors, which works well with all output except for modem comm.
What I want to achieve is that all comm. is performed behind the scene so to speak. Perhaps I'm missing a parameter or something when setting up PySerial? Does anyone know how to suppress this output? Any ideas greatly appreciated!
Thanks
/C
Related
When using print method I am receiving log output I haven't seen before.
I guess it's coming from Twisted module which seems to be a part of Scrapyd. I am not using this kind of logging elsewhere and I haven't started it explicitely.
Does anyone know how to supress/deactivate this kind of log messages?
collective internet,
I am a very new programmer that has given myself a specific project to teach myself coding. I work with a lot of equipment that can take TCP commands so I set out to build a system of buttons that will send different commands per each button. I got myself a Raspberry Pi 3b and took online classes on Python. I've got reasonably far on my own (I've got the buttons working how I want!) but where I've been stuck is sending TCP commands.
To be more specific: I am sending data and it is being received but the string command is not being encoded properly. The commands are functional when I execute them in a telnet session, but obviously I want them executed as part of my script. The commands don't specify that they need to be received over a telnet session and, by other means, I've had these commands work as TCP commands exterior to a telnet session. I read about a telnet module for Python but I don't think I should need it.
I verified packet delivery with wireshark. I captured the packets sent by my script and the packets sent by the telnet session and they're similar but not the same. Horseshoes and hand grenades, right? My current method has been to just preface the string (within ') with a lower case b. I also tried putting .encode() after the string (omitting the b in that situation).
The string command has the format:
setInput "InputName" Value
So for my use case, I'm setting the input named "One" to a value of 1:
setInput "One" 1
So as you can see in my script (inserted below) I ended up using:
s.sendall(b'setInput "One" 1')
But it's not quite sending the right information because it is not working and it doesn't look the same in wireshark.
TL;DR: I'm trying to send packets via TCP but they're not being encoded properly.
Ultimately, my question is if I am even headed in the right direction using these commands and just need a different means to encode the string or if I need to explore another direction entirely (perhaps the telnet module?)
Here is the script I've been using to test and the wireshark output of my script:
import socket
import time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.100.40', 3040))
print('connected')
time.sleep(2)
s.sendall(b'setInput "One" 1')
print('sent increase')
time.sleep(2)
s.sendall(b'setInput "One" 0')
print('sent decrease')
Wireshark log of my script
Here is the wireshark output of the telnet session that was successful:
Wireshark log of the telnet session
Any and all help is appreciated. I looked far and wide and can't seem to find any cases similar to mine.
EDITS: Sorry for the poor formatting. I appreciate the advice on how better to present posts. This is my first post here and I'm just getting the hang of it. My photos are still links due to my lack of privileges here. Sorry if I was too wordy, I just wanted to supply as much information as possible so as to help people understand my problem and, if a solution is found, to help people with a similar issue find this.
The telnet tcp data includes a carriage return and a linefeed and the end of the data. Apparently the receiving part needs this to be included to make things work. So change your Python string to
b'setInput "One" 1\r\n'
after many unsuccessful researches I've decided to ask my question here so maybe someone will provide me an answer or a lead for a problem I got.
I have a Python script that runs as a background process on an embedded device (the OS is a Linux distro). This script do important measurements and because of that, it can not be terminated or restarted.
I was wondering if it was possible to implement a chunk of code that will redirect the print() outputs to a Putty SSH console when we send it a command via a messaging protocol (MQTT).
So the situation will be like this:
Device receive a command, set a variable to 1
Print() outputs will now be visible on the current root session opened by Putty SSH client.
I don't know if it is possible but I'm opened to suggestions.
Thank you in advance for your answers, and sorry for my bad english.
As suggested by GhostCat, I've decided to go for a logging solution so anyone who can connect to the device by SSH can just "tail -F" the log file and see the debug messages.
I've removed all the print() statements in the code and replaced them by logging calls (which is, indeed, a more professional approach)
If someone had the same question as I, you can read this : http://www.blog.pythonlibrary.org/2014/02/11/python-how-to-create-rotating-logs/
or this : https://docs.python.org/2/howto/logging.html#logging-basic-tutorial
to help you solve your issue.
Thanks again to GhostCat and Tripleee for their help.
A lot of resources, including the example in the official documentation at telnetlib suggest that at the end before you do a read_all(), you need to write exit after the command as:
tn.write("ls\n")
tn.write("exit\n")
Can someone please help me understand why is this needed ?
If I try doing it without the exit, the telnet connection hangs (or at least looks like it is hung) as the output of the command executed does not show on the terminal.
Also, another way of making it work, as I found in some resources was to use 'exec' to fire up the command and then you don't need the exit thing anymore.
Please help me understand this as well.
read_all() reads all the output until EOF. In other words, it waits until remote server closes connection and returns you all the data it has sent. If you have not previously notified the server with an "exit" command that you have no more commands for it, it will wait for them. And a deadlock occurs: you are holding open connection because you are waiting for server to tell you that it has sent everything it intended to say, and server waits for new orders from you and is ready to add more data to it's output.
I am trying to control a console application (JTAG app from Segger) from Python using the subprocess module. The application behaves correctly for stdout, but stdin doesn't seem to be read. If enable the shell, I can type into the input and control the application, but I need to do this programmatically. The same code works fine for issuing commands to something like cmd.exe.
I'm guessing that the keyboard is being read directly instead of stdin. Any ideas how I can send the application input?
from subprocess import Popen, PIPE, STDOUT
jtag = Popen('"C:/Program Files/SEGGER/JLinkARM_V402e/JLink.exe"', shell=True,
universal_newlines=True,
stdin=PIPE,
stdout=PIPE,
stderr=STDOUT)
jtag.stdin.write('usb\n')
jtag.stdin.flush()
print "Stdout:"
while True:
s = jtag.stdout.readline()
if not s:
break
print s,
jtag.terminate()
As shoosh says, I'd try to verify that the application really is looking for keyboard input. If it is, you can try Win32 message passing, or sending it keyboard input via automation.
For the message passing route, you could use the EnumWindows function via ctypes to find the window you're after, then using PostMessage to send it WM_KEYDOWN messages.
You can also send keyboard input via pywinauto, or the ActiveX control of AutoIt via win32com.
Using AutoIt:
from win32com.client import Dispatch
auto = Dispatch("AutoItX3.Control")
auto.WinActivate("The window's title", "")
auto.WinWaitActive("The window's title", "", 10)
auto.Send("The input")
I'm guessing that the keyboard is being read directly instead of stdin
This is a pretty strong assumption and before stitching a solution you should try to verify it somehow. There are different levels of doing this. Actually two I can think of right now:
Waiting for keyboard events from the main windows loop. if this is the case then you can simulate a keyboard simply by sending the window the right kind of message. these can be wither WM_KEYDOWN or WM_CHAR or perhaps some other related variants.
Actually polling the hardware, for instance using GetAsyncKeyState(). This is somewhat unlikely and if this is really what's going on, I doubt you can do anything to simulate it programatically.
Another take on this is trying to use the on-screen keyboard and see if it works with the application. if it does, figure out how to simulate what it does.
Some tools which might be helpful -
Spy++ (comes with Visual Studio) - allows you to see what messages go into a window
strace allows you to see what syscalls a process is making.