Python - pySerials inWaiting() always return 0 - python-3.x

I'm trying to make a small program that receives messages from the serial port, and doing it periodically. Right now I'm not saving anything, I'm just trying to see if I get anything at all, so I tried this code:
def ReceiveRS():
global ser
while ser.inWaiting() > 0:
print(ser.read(1))
ser is the serial port, which is correctly initialized, as it has worked before and I can send stuff. After trying some different things I have found out that inWaiting() never seems to return anything but 0. Anyone have any ideas as to why and how to fix it?
Oh, and I'm using Python 3.2.3, with pySerial on a Raspberry PI.

This was embarrassing. I had another older version running in the background (on autostart so I didn't remember it was running) that was taking all the received bytes and leaving none for the newer script. So, anyone know how to remove questions?

try this
while (True):
if ser.inWaiting() > 0:
print(ser.read(1))
should be working now as expected.

Related

Python3.10.4 serial readline() not displaying prompts

Right now, I am connecting to a device using Tera Term and manually running over 50 tests. My goal is to automate these tests. Currently I am trying to do this through python using the pyserial library. The issue I am running into is readline() will display everything until the login prompt appears. It stops on the line before.
What it should look like
Booting: 2022.08
CPU: cpu_id
In: serial
OUT: serial
Normal Boot
Hit any key to stop autoboot: 0
Starting Kernel ...
Enter your credentials
cpu_id login:
what readline() is displaying:
Booting: 2022.08
CPU: cpu_id
In: serial
OUT: serial
Normal Boot
Hit any key to stop autoboot: 0
Starting Kernel ...
Enter your credentials
Here is the code I am currently playing with:
Any insight would help. Or, if you know of another way to run tests through a serial port, I'm all ears.Thanks!
Thanks to the comments of #ShadowRanger I was able find a work around. I ended the readline() loop the line before the login prompt. I then logged in and ran a test blind then started reading again afterwards. Here is the code I used:
This is not the cleanest code but it explains the process well enough.

How to subprocess a pymodbus tcp server in a python unit test and terminate it after all the tests have been executed?

I will try to give you some context before presenting the issue I am facing.
I have a component called Actuator which relies on the module pymodbus. When I tested this component, I did it in the easiest possible way using a modbus TCP server based on pymodbus. Basically, I run the server as a python script (which is exactly this one: https://pymodbus.readthedocs.io/en/latest/source/example/synchronous_server.html) in a new shell and my application, which includes the Actuator, in another shell. Everything works like a charm.
What I want to do now, is to write a unit test for the Actuator, using python unittest and pymodbus and try to automate what I was doing before. My idea was to run the modbus server as a subprocess (consider that I do not need the output from the server) in the setUp method, use it in my test suite and then terminate it in the tearDown method, like this:
class TestActuator(unittest.TestCase):
"""Class to test the actuator module"""
def setUp(self):
"""
Setup a real Actuator object with a modbus server running
in background for tests
"""
modbus_server_path = "path/to/modbus_server.py"
cmd = "python3 {}".format(modbus_server_path)
self.modbus_server = Popen(cmd.split(), shell=False, stdout=DEVNULL, stderr=DEVNULL)
# other stuff
def test1(self):
def test2(self):
def tearDown(self):
"""Cleanup everything before exiting"""
self.modbus_server.terminate()
if __name__ == '__main__':
unittest.main()
Unfortunately, it seems more challenging than I expected.
Everything I tried from other topics on stackoverflow failed:
Use Popen.kill() instead of terminate. I tried also to "del" after kill or terminate or to use os.kill(self.modbus_server.pid, SIGTERM) instead.
Add or change args to the Popen command, such as shell=True instead of shell=False and close_fds=True.
Use the other variants of subprocess Popen, like check_output, run, call, etc...
Use os.spawnl instead of subprocess Popen.
None of these worked. What happens most of the times is that the server fails to start properly, so all the other tests fail and the modbus_server process is not terminated (I have to kill it manually).
Do you have any idea? Thank you.
I will share how I solved my issue and what I learned so far:
About the attempt to make the modbus TCP server running as a subprocess while running tests, you need to change a few things to make it work decently.
The first thing is to use "setUpClass" and "tearDownClass" instead of setUp and tearDown, (you can use also both of them but in my case I needed the first two) so that you can run the setup of your server just once for all the test suite and not before and after each test case. Unfortunately, the syntax for setUpClass and tearDownClass is not so straightforward. This answer helped me a lot: Run setUp only once for a set of automated tests
The second thing is about the TCP socket. Basically, I wanted to be sure that my tests worked fine and run them a few times in a row. So, sometimes everything worked fine, other times they failed. After a while I found that if I run the tests without waiting at least one minute before trying again, they will fail.
This is due to the TIME_WAIT (set to 60 seconds by default) of the TCP socket bound by the modbus server on the local address and port 5020 in my case. If you want to re-bind a socket on the same TCP address and port you used before, you will have to wait 60 seconds. This answer was useful to understand why this happens: Setting TIME_WAIT TCP
After I figure out how to make all that stuff work together, I decided to use mocks because my solution seemed too hacky for my tastes.

Python tempfile.TemporaryFile hangs on Windows when no write privilege

My environment is Python 3.7.2, running on Windows 10. I'm working on a directory-selection widget, and I'm looking for the cleanest+surest method to test whether the selected directory path allows write privilege.
Previously I'd been opening a named file by the usual open() method, writing a few bytes to it, then deleting it -- putting the whole thing in a try-except block. This was OK but it ran the risk of leaving behind an unwanted file. Recently I came across the documentation for tempfile.TemporaryFile(), and this seemed cleaner way to get the same result, with no risk of leaving junk files on the system.
The problem is, tempfile.TemporaryFile() hangs on my system when it's given a dir parameter that's a read-only folder. I've googled around and found this very old bug, but it was written against Python 2.4 and was fixed long ago.
Here's a test script I put together to illustrate the issue. (Note that I've omitted the file-delete that my actual app performs, as it's not relevant for the illustration.)
import os, tempfile
def normOpen(checkPath):
try:
with open(os.path.join(checkPath,'x.txt'),'wb') as tf:
tf.write(b'ABC')
except Exception as e:
print('Write disabled for '+checkPath)
print(str(e))
else:
print('Write enabled for '+checkPath)
def tfOpen(checkPath):
try:
with tempfile.TemporaryFile(dir=checkPath) as tf:
tf.write(b'ABC')
except Exception as e:
print('Write disabled for '+checkPath)
print(str(e))
else:
print('Write enabled for '+checkPath)
tryPath1 = 'C:\\JDM\\Dev_Python\\TMPV\\canwrite' #Full control path
tryPath2 = 'C:\\JDM\\Dev_Python\\TMPV\\nowrite' #Read-only path
print('First method - normal file-open')
normOpen(tryPath1)
normOpen(tryPath2)
print('Second method - TemporaryFile')
tfOpen(tryPath1)
tfOpen(tryPath2)
When I run this script, it hangs on the last line and just sits there (Task Manager shows Python consuming about 10-15% CPU).
Does anyone know what the problem might be? Particularly is this a Python bug, or is there something wrong with my usage of TemporaryFile?
In case it helps, below is the specific privileges Windows shows for each of these folders:
A deeper dive than I'd initially done, turned up the answer. This is indeed a Python bug, reported some time ago but which remains to be addressed.
The comments from eryksun describe the details -- and it's what prompted me to take a closer look at the Python bug database -- so ultimately that's where credit is due. I'm just filling it in here to get the question answered and closed out.
The bug affects only Windows environments, but unfortunately it has the result of rendering tempfile.TemporaryFile unusable on Windows for this common use case.

node-serialport 6.x.x doesn't receive data or errors on Windows (but does on Mac)

I am using the following library to connect via USB to an external device:
https://github.com/node-serialport/node-serialport
I set up the following sample project to narrow down where the issue might be:
https://github.com/nyoung697/node-serial-test
This code works on my Mac. The device I am connecting to accepts an ascii command and the carriage return to terminate that command.
In the example project, I am passing in 'V\r' and am expecting the version of the device to be returned. When I run this code on my Mac, I get the expected response.
However, when I run it on my Windows 10 machine, I do not get any response at all. Neither the port.on('data') or port.on('error') events are hit.
I tested downgrading the serialport library to version 4.0.7 and it does work.
Does anyone have any ideas what might have changed between 4 => 6?
P.S. I edited this question, as I originally thought it had something to do with Electron, however after doing this simple test with only node.js, I believe I have narrowed it down to this version of the library on Windows.
Okay... I just figured this out.
All I needed to do was add the property 'rtscts' to the openOptions object I pass in to the constructor and set it to true.
const SERIAL_PORT_SETTINGS = {
baudRate: 115200,
rtscts: true
};
let port = new SerialPort(devicePath, SERIAL_PORT_SETTINGS);
I figured this out by digging around in the release notes. I noticed that from v5.x.x to 6.0.0 the breaking changes included making this value default to false.
windows: We previously hard coded to have RTS on for windows at all times it now default to off.

SocketNER freezes in Stanford NER

Or, The Mystery of Line #2598.
I was trying to run Stanford-NER on a local server. I wrote some scripts, using a bit of PyNER. I then downloaded some of Sherlock Holmes' books off Project Gutenberg, and started running the program. Set up a server on the PC with a 1000MB RAM and used this
tagger = ner.SocketNER(host='192.168.xxx.xxx', port=xxxx)
The code runs smoothly, till it reaches line#2598. After that, without raising any error, or even terminating, the program does not proceed. I thought it would be an issue with the processing capacity/memory of the server, so I set up a friend's PC with the same configurations, and ran the script to hit both the servers alternately.
if count % 2:
get_entities(str(l), tagger_1)
else:
get_entities(str(l), tagger_2)
Still, it froze at Line#2598. Not the one to give up, I did this
if count % 2:
tagger_1 = ner.SocketNER(host='192.168.xxx.xxx', port=xx)#k
get_entities(str(l), tagger_1)
del tagger_1
else:
tagger_2 = ner.SocketNER(host='192.168.xxx.yyy', port=xx)#v
get_entities(str(l), tagger_2)
del tagger_2
Still, Line #2598 freezes. On another book, it is line#2212, so it's not the number of times I connect. Neither is it the number of characters. The lack of errors baffles me. Is there an underlying limit enforced on the network? Thank you for any hint. The issue stays the same for IDLE as well as ST3.

Resources