Not able to read anything from serial using pyserial - pyserial

I have written a python script to communicate to my RS232 device,
after execution i am able to write to terminal but i am not getting any output.If i open my teraterm i am able to see cmnd passed thru pyserial(with out any output print).
code :
import serial
port = "COM1"
baud = 115200
ser = serial.Serial(port, baud, timeout=1)
if ser.isOpen():
print(ser.name + ' is open...')
cmd = input("Enter command or 'exit':")
if cmd == 'exit':
ser.close()
exit()
else:
ser.write(cmd.encode()+b'\r\n')
out = ser.read()
print('Receiving...'+out.decode())
following is the output from console :
COM1 is open...
Enter command or 'exit':ls
Receiving...l

Receiving...l
This is what I'd expect from your program. The default value for read()'s size parameter is 1. This means that one byte will be read.
If the other end echoes your input 'ls', the first byte will be an 'l'.
Try the readline() method (don't forget to add a timeout, or it might block forever). Or handle the protocol some other way, by repeatedly calling read(), for example.

Related

Redirect stio and still printing in the terminal

Thanks to this great answer from #Przemyslaw Szufel, we can easily redirect stdio output into a file providing its path.
I wanted to know if it is possible to both redirect stio output to a file and still continue print it in the terminal. That is probably an easy feature to achieve but I could not find it!
And obviously not running the code twice :)
You need a Tee Stream such as https://github.com/fredrikekre/TeeStreams.jl/.
Unfortunately the interface of redirect_stdio does not accept abstract IO for its sink. It requires it to be an IOStream which is a concrete Julia type.
So it seems like there is no good way with the redirect_stdio via streams.
However redirect_stdio does accept sockets and named pipes and this is a way you could consider (yet too complex for this simple tasks - maybe someone finds a more elegant solution).
First you need to create a pipe server that will be running asynchronously in your REPL session (this is code for Windows for Linux you will probably need to remove \\.\pipe\ from the pipe name):
using Sockets
srv = Sockets.listen(raw"\\.\pipe\TeePipe")
mystdout = stdout
#async begin
open("log.txt", "w") do f
sock = accept(srv)
while !eof(sock)
line = readline(sock)
println(mystdout, line)
flush(mystdout)
println(f, line)
flush(f)
end
end
end
Now at the same REPL session you create the client:
teelogger = Sockets.connect(raw"\\.\pipe\TeePipe")
And here is a sample REPL session showing that this works:
julia> redirect_stdio(stdout=teelogger) do
println("Line1")
println("Line2")
#show 3+4
end
Line1
Line2
3 + 4 = 7
7
shell> more log.txt
Line1
Line2
3 + 4 = 7

How to write a test to confirm that a perl script waits (or doesn't wait) for interactive user input (based on supplied options)

I have a perl script for which I would like to write a few tests. If the perl script gets supplied a specific option, the user is allowed to paste or type out multi-line input and end their input using control-d.
These are the tests I want to write:
The script (when an interactive flag is supplied) waits for (multiple lines of) input on STDIN until the user hits control-d
[this test is already implemented - but provided for completeness] The script (when a flag is supplied that indicates a redirect/pipe) consumes all input on STDIN and does not wait for control-d
The script (when no input flag is provided [interactive or redirect]) does not wait for interactive user input
Test 1 toy example
I wrote a test for test 1 that confirms input was received (it works by the parent test script printing to the child's input handle and the child modifies and prints that input back out), but that test doesn't wait for an end of input signal (e.g. control-d) (which I don't know how to send anyway). So in other words, I can confirm it receives input, but I don't know how to confirm that it waits for the user to intentionally end the input entry. I.e. How do I know that the input consumption won't stop until the user types control-d?
Here's what I have so far for test 1. I wrote a 3rd little IO::Pipe::Consumer module to be able to send input to the child process that I'm testing and I wrote a toy example of the script that allows input on STDIN from a tty.
Here is a toy version of the script I'm testing:
>perl -e 'while(<STDIN>){print("*$_")}'
test
*test
^d
>
And here is the toy test code (that I want to improve) for the above script:
>perl -e '
use IO::Pipe::Consumer;
$obj = new IO::Pipe::Consumer;
$si = $obj->getSubroutineConsumer(
sub { while(<STDIN>) print("*$_") } }
);
print $si "test\n"
'
*test
>
I thought the parent would have to print an EOF (e.g. like what you get from "control-d") to end the input in the test, but the test ends immediately even though I'm not sending any such end-of-input character. I can see that it's getting, modifying, and printing the input. Is that sufficient to confirm that the script will wait for user input (and that the user will be able to intentionally end the input) or is there something else I should do to confirm it waits for all user input until the user intends to end it?
Test 2 - done
Test 3 toy - don't know how to write it...
Even if modified input spit back out is sufficient proof of "waiting for input" for test 1, I also wish to test that a script doesn't consume input on STDIN when no input option (interactive or redirect) is provided - but since it doesn't seem to wait even when I do send it input without an end-of-input signal, how would I test that the script wouldn't hang waiting for input? Note, the script has other options for consuming redirected or piped input, so my intent is specifically to know if it's waiting on input from the tty. All of the STDIN consumption options (whether from the tty or via redirect/pipe) are optional, which is why I want to write these tests.
My manual testing shows everything works as intended. I would just like some tests to assure that behavior for the future.
IO::Pipe::Consumer
I feel like the thing I'm missing is not relevant to IO::Pipe::Consumer, so WRT that, I'll just describe it instead of paste in 30 or so lines of code... All it does is it sets a pipe to the child's STDIN and gives that handle back to the parent for it to print to. I haven't put it on cpan. I'm just experimenting to see if I can use it to write these tests.
IO::Pipe::Consumer is basically the opposite of IO::Pipe::Producer (a module I published on cpan looong ago, say 2001-ish, when I was new to perl, or programming for that matter). The main difference, aside from swapping STDIN for STDOUT and Reader with Writer (and vice versa), is that the open is open(STDIN,"<",\${$stdin_pipe}).
I thought the parent would have to print an "end-of-input" (e.g. "control-d") character to end the input in the test,
Ctrl-D doesn't produce an "end of input character"; it causes the terminal to return EOF.
I don't know what IO::Pipe::Consumer is —it's not on CPAN— but I presume it creates a pipe. Exiting the program causes the writer end of the pipe to be closed and thus cause the reader end to return EOF.
is there something else I should do to confirm it waits for all user input until the user intends to end it?
<> reads until one of the following things happen:
A line feed is encountered (returning what was read including the line feed)
EOF is encountered (returning what was read up to an including the line feed)
An error is encountered (returning false).
You can confirm it waits by putting sleep statements between what you send. Be aware that buffering may interfere.

How to send hexadecimal commands to a monitor over a Serial Port with PowerShell

Okay this is a bit of a weird one but due to my complete lack of knowledge on how to use Serial Ports or PowerShell i couldn't think of anywhere else to go.
What I'm trying to do is send basic commands to a monitor that has a RS232 port on it that can be used to control the properties of the monitor, i.e. Brightness, Contrast, Backlight etc.
I'm attempting to use PowerShell to do this for testing purposes. I can create the $port in PowerShell and assign it to the relevant COM# that the monitor is connected to but I'm at a loss as to how to actually send the command to it as it must be Hexadecimal for the controller on the monitor to understand it.
The monitor is capable of returning an acknowledgement using the same Hex layout but I'm unable to find a way of showing that response on the Powershell console.
This is what I have been able to get so far.
PS C:\Users\Kingdel> [System.IO.Ports.SerialPort]::getportnames()
COM1
COM2
COM3
COM4
COM5
COM6
PS C:\Users\Kingdel> $port= new-Object System.IO.Ports.SerialPort COM1,9600,None,8,one
PS C:\Users\Kingdel> $port.open()
PS C:\Users\Kingdel> $port.WriteLine("0xA6,0x01,0x00,0x00,0x00,0x03,0x01,0x31,0x94")
PS C:\Users\Kingdel>
Anyone able to point me in the right direction as to how I can send this command to the monitor and to view the returned acknowledgement.
I am open to trying different terminals, I have tried PuTTy and Termite and neither of them were successful as far as I can tell.
That's a really good question. Maybe I can help with this.
The SerialPort.WriteLine() method takes in a string to write to the output buffer, so using this, you're essentially sending an argument of strings.
To send something over to the [System.IO.Ports.SerialPort] object, you need to use SerialPort.Write() with a Byte[] argument. The Write() method can take in a number of bytes to the serial port using data from a buffer.
You also need to send it three arguments which are buffer Byte[], offset Int32, and a count Int32. So in your case, you can do the following:
[Byte[]] $hex = 0xA6,0x01,0x00,0x00,0x00,0x03,0x01,0x31,0x94
$port.Write($hex, 0, $hex.Count)
The buffer argument is the array that contains the data to write to the port, offset is the zero-based byte offset in the buffer array at which to begin copying the bytes to the port, and the count is the number of bytes to write.

Python Main Function Command Line Argument Long List

I'm trying to make a simple main function for a Caesars Shift cryptography program, however I'm not quite sure how to configure all this command line opt/arg stuff. I want to configure the program to accept command line arguments like so:
./caesars.py -e 13 message to encrypt
with 13 being the amount of shifts and the following lines to be the message to encrypt. I have the functions defined, but I am just not sure how to configure the opt arg stuff to accept the first argument after argv[1] to be the key, then everything after that to get split into a list/long string. Here is what I have so far:
def main():
global decoder
global encoder
if not len(sys.argv[1:]):
usage()
# read the commandline options
try:
opts, args = getopt.getopt(sys.argv[1:],"hd:e:", ¬
["help","decode","encode"])
except getopt.GetoptError as err:
print str(err)
usage()
for o,a in opts:
if o in ("-h","--help"):
usage()
elif o in ("-d","--decode"):
decode = True
elif o in ("-e", "--encode"):
encode = True
else:
assert False,"Unhandled Option"
Thanks in advance.
If you haven't already, you should look into docopt. While I have never used it myself, it's very popular and should be perfect for you.

Spotify Tech Puzzle - stdin in Python

I'm trying to solve the bilateral problem on Spotify's Tech Puzzles. http://www.spotify.com/us/jobs/tech/bilateral-projects/ I have something that is working on my computer that reads input from a file input.txt, and it outputs to ouput.txt. My problem is that I cannot figure out how to make my code work when I submit it where it must read from stdin. I have looked at several other posts and I don't see anything that makes sense to me. I see some people just use raw_input - but this produces a user prompt?? Not sure what to do. Here is the protion of my code that is suposed to read the input, and write the output. Any suggestions on how this might need changed? Also how would I test the code once it is changed to read from stdin? How can I put test data in stdin? The error i get back from spotify says Run Time Error - NameError.
import sys
# Read input
Input = []
for line in sys.stdin.readlines():
if len(line) <9:
teamCount = int(line)
if len(line) > 8:
subList = []
a = line[0:4]
b = line[5:9]
subList.append(a)
subList.append(b)
Input.append(subList)
##### algorithm here
#write output
print listLength
for empWin in win:
print empWin
You are actually doing ok.
for line in sys.stdin.readlines():
will read lines from stdin. It can however be shortened to:
for line in sys.stdin:
I don't use Windows, but to test your solution from a command line, you should run it like this:
python bilateral.py < input.txt > output.txt
If I run your code above like that, I see the error message
Traceback (most recent call last):
File "bilateral.py", line 20, in <module>
print listLength
NameError: name 'listLength' is not defined
which by accident (because I guess you didn't send in that) was the error the Spotify puzzle checker discovered. You have probably just misspelled a variable somewhere.