Pyserial read from serial port and write to C program - python

I want to read some data using pyserial and then send the output to a C program using subprocess.
Here is my code (in progress):
from serial import Serial
import subprocess
process = subprocess.Popen("./print",stdin=subprocess.PIPE)
ser = Serial("/dev/ttyAMA0",9600,timeout=2)
while True:
if ser.inWaiting!=0:
ser.read()
where print is the C program that simply prints the output (a stepping stone to what I actually want to do).
How do I get it so that I can write the result of ser.read() to the C program?
How do I interpret or use that input?

Write to stdin of Popen. It's a file object.
process.stdin.write(ser.read())

Related

What is the "send" button on the Arduino serial monitor doing?

This has been resolved!!
I have to wait a few seconds after opening serial port.
I want to execute the python program that is being done with the send button on the Arduino serial monitor.
if (Serial.available() > 0){
Serial.print(hoge);
}
is written in arduino, and I want to make Serial.available ()> 0 by python program.
I tried...
1.
If I send something like A or 3 on the IDE serial monitor, the contents of hoge will be output on the serial monitor.
2.
Using pyserial
ser = serial.Serial('/dev/ttyACM0', 115200,timeout=None)
ser.write(str.encode('A'))
data = ser.readline()
print(data)
When this is executed, it waits for reception before ser.read ().
After deleting the if (Serial.available ()> 0) of the program on Arduino and executing it, the contents of hoge were printed properly on the terminal.
The contents of hoge are
b'0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\r\n'
What do I need to write to do the same thing as 'send'? How do I get Serial.available ()> 0 ...?
It would be very helpful if you could tell someone.
The first data of 'hoge[]' is NULL character. Therefore there's no chance for 'Serial.print()' function to print out the whole content.
Serial.print(hoge) immediately returns because the first character is NULL character.
ser.readline() is waiting forever because there's no newline incoming from Arduino.
Simply changing the content will solve this issue or use write() function (but if you keep the same content then you need to adapt your python code as well without using readline()).
In your python code, you need to add "time.sleep()" before "ser.write()" so that Arduino is ready to receive the serial data. More than 1 seconds would be required.

Why doesn't pyserial write on Linux?

I've coded a simple script for Windows that works fine and I have adapted it to Linux (Ubuntu). The problem is that it doesn't read the byte sent.
I tried all the different serial ports available according to the Arduino IDE but the problem persists.I also used \n and \r without success and different encodings.
Code working on win10:
import serial
import time
import keyboard
arduino = serial.Serial('COM4', 9600, timeout=0)
while True:
arduino.write('a'.encode())
time.sleep(0.1)
print(arduino.readline())
Code not working on Ubuntu:
import serial, time
arduino = serial.Serial('/dev/ttyAMC0', 9600, timeout = 0)
while True:
arduino.write('a'.encode())
time.sleep(0.1)
print(arduino.readline())
So the first script prints continuously a\r\n, the second doesn't. Simply shows b'' continuously. So I think it doesn't simply write the letter.
Solved. No idea what exactly was thr issue but worked sending capital letter.

Automate input to brute-force a program running in cli with Python

I'm currently trying to complete all levels on Over the Wire's Bandit 'wargame'.
One of the levels (level 24), requires that I connect to a port, on which a daemon is running. This daemon asks to input a password and a 4-digit pin. The password is already known (it is provided at the end of the previous level), the pin is unknown. The indication is that it's necessary to 'brute-force' it.
Entering a wrong pin results in this message: "Wrong! Please enter the correct pincode. Try again.".
I decided to write a python script that automates the process. The script would:
1) Connect to the port via netcat
2) Enter the password and a randomly generated pin
3) Read the output, and, if the word 'again' is in it (meaning the pin is wrong), repeat via a loop, until the pin is guessed.
But although my script runs and connects, it fails to communicate with the daemon, once the connection to its port is established.
All I get is the daemon's prompt, requesting password and pin.
This is my code:
import subprocess
import random
# Initialise variables
pin = ''
output = "Wrong! Please enter the correct pincode. Try again."
# Connect to the port
def connect_to_port():
subprocess.call(["nc localhost 30002"], shell=True)
# Generate pin
# TO DO: skip pins that were proven incorrect
def generate_pin():
pin = ''
pin_len = 0
while pin_len < 4:
pin += str(random.randint(0, 9))
pin_len += 1
return pin
# Connect to port
# Loop: check if 'again' is in 'output',
# if it is, generate a pin and input password and pin
def main():
connect_to_port()
while 'again' in output:
pin = generate_pin()
out = subprocess.check_output(["UoMYTrfrBFHyQXmg6gzctqAwOmw1IohZ", pin])
output = out.decode("utf-8")
main()
I suspect I'm not using the subprocess module correctly, but I can't really understand how. Why is my script not working?
Forgive my rudimentary use of the relevant terminology.
EDIT: I see the use of subprocess.check_out() is all wrong. What I'd need, as suggested in the answers and comments, is to open a PIPE and use communicate() to write to the subprocess's stdin (modifying the pin each time) and read its stdout, but I'm not sure how to go about that.
The netcat needs to be opened once during the conversation and then multiple reads and writes need to be performed.
If you want to be able to read and write data to the subprocess, you will need to create a PIPE so use the Popen interface, then you can use communicate().
Given how trivial this is, why not just open a socket directly in python?
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('localhost', 30002))
data = sock.recv(64)
sock.send(pin)

How to communicate with command line program using python?

import subprocess
import sys
proc = subprocess.Popen(["program.exe"], stdin=subprocess.PIPE) #the cmd program opens
proc.communicate(input="filename.txt") #here the filename should be entered (runs)
#then the program asks to enter a number:
proc.communicate(input="1") #(the cmd stops here and nothing is passed)
proc.communicate(input="2") # (same not passing anything)
how do i pass and communicate with the cmd using python.
Thanks. (using windows platform)
The docs on communicate() explain this:
Interact with process: Send data to stdin. Read data from stdout and
stderr, until end-of-file is reached. Wait for process to terminate.
communicate() blocks once the input has been sent until the program finishes executing. In your example, the program waits for more input after you send "1", but Python waits for it to exit before it gets to the next line, meaning the whole thing deadlocks.
If you want to read and write a lot interchangeably, make pipes to stdin/stdout and write/read to/from them.

How to read stdout output of ongoing process in Python?

Hello I'm really new to the Python programming language and i have encountered a problem writing one script. I want to save the output from stdout that i obtain when i run a tcpdump command in a variable in a Python script, but i want the tpcdump command to run continuously because i want to gather the length from all packets transferred that get filtered by tcpdump(with the filter i wrote).
I tried :
fin, fout = os.popen4(comand)
result = fout.read()
return result
But it just hangs.
I'm guessing that it hangs because os.popen4 doesn't return until the child process exits. You should be using subprocess.Popen instead.
import subprocess
import shlex #just so you don't need break "comand" into a list yourself ;)
p=subprocess.Popen(shlex.split(comand),stdout=subprocess.PIPE)
first_line_of_output=p.stdout.readline()
second_line_of_output=p.stdout.readline()
...

Categories

Resources