How to iterate lines from a text file in python? - python

I update my question because At first I think that I have the best solution However, I don't have it until now.It was my mistake in execution. I think that the error comes from the loop while in the file C.
I am trying to read lines from a text file"Plaintext.txt".
e0370734313198a2885a308d3243f6a8
ccddeeff8899aabb4455667700112233
8e73b0f7da0e6452c810f32bc4567a22
It contains now tow lines, I put just two in order to make simple test, but I must put more then 1000 texts (means more than 1000 lines) I want to read each line then send it to the uart where I will do encryption for every plaintext (The encryption algorithm is in C): This is my script:
I edit it as you tell me but I still have the encryption of one line
import string
import serial
import time
from array import array
import struct
import binascii
ser = serial.Serial(
port='COM4',\
baudrate=230400,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=0)
f = open(r'C:\\Users\\user\\Plaintxt.txt', 'r')
for a in f:
plaintxt_16b=a[0:32]
plaintext=binascii.unhexlify(plaintxt_16b)
clear_msg=b'\x24'+b'\x73'+b'\x10'+plaintext
ser.write(clear_msg)
time.sleep(0.4)
while True:
print(ser.read(70))
ser.close() # close ports
In the C file:
while(1)
{
int rx_length = dev_uart_ptr->uart_read((void*)rx_buffer, 19);
if (rx_length <19)
{
if (rx_buffer[0]=='\x24')
{
if (rx_buffer[1]=='\x73')
{
if (rx_buffer[2]=='\x10')
{
plaintext[0] = (rx_buffer[3] << 24) |
(rx_buffer[4] << 16) |
(rx_buffer[5] << 8) |
rx_buffer[6];
plaintext[1] = (rx_buffer[7] << 24) |
(rx_buffer[8] << 16) |
(rx_buffer[9] << 8) |
rx_buffer[10];
plaintext[2] = (rx_buffer[11] << 24) |
(rx_buffer[12] << 16) |
(rx_buffer[13] << 8) |
rx_buffer[14];
plaintext[3] = (rx_buffer[15] << 24) |
(rx_buffer[16] << 16) |
(rx_buffer[17] << 8) |
rx_buffer[18];
xprintf("**************************\n");
xprintf("%8x %8x %8x %8x \n",plaintext[0],plaintext[1],plaintext[2],plaintext[3]);
aes2_set_msg((unsigned int *)plaintext); /** Reset AES message buffer */
aes2_set_key128((unsigned int *)key128); /** Put the key 128 into AES */
/** Configure AES register to enable IRQ and ENCODE */
regs_aes2_ptr-> CFG = AES2_CFG_ENC_DEC_BIT | AES2_CFG_IRQ_MASK_BIT;
/** Reset AES internaly */
regs_aes2_ptr-> CTRL = AES2_CTRL_SWRESET_BIT;
#if DEBUG
xprintf("Go encrypt..\n");
#endif
/** Start the ENCODE function */
regs_aes2_ptr-> CTRL = AES2_CTRL_START_BIT;
while(!aes2_irq_flag); /** Wait for irq flag */
aes2_irq_flag=0; /** Reset irq flag */
#if DEBUG
xprintf("Encrypt done..\n");
#endif
aes2_get_msg((unsigned int *)ciphertext); /** Retrieve encrypted message */
xprintf("%8x %8x %8x %8x \n",ciphertext[0],ciphertext[1],ciphertext[2],ciphertext[3]);
xprintf("**************************\n");
}
else
{
printf ("false");
}
}
else
{
printf ("false");
}
}
}
}// End While
}//end of C_Entry
So the problem is that It takes just the last line and repeat all the time the same encryption of that line:
$**************************
ccddeeff 8899aabb 44556677 112233
Go encrypt..
Encrypt do
ne..
d6e4d64b 27d8d055 c5c7573a 8df4e9aa
**************************
******************
********
ccddeeff 8899aabb 44556677 112233
Go encrypt..
Encrypt done..
d6e4d64b 27d
8d055 c5c7573a 8df4e9aa
**************************
**************************
ccddeeff
8899aabb 44556677 112233
Go encrypt..
Encrypt done..
d6e4d64b 27d8d055 c5c7573a 8df
4e9aa
**************************
**************************
ccddeeff 8899aabb 44556677
112233
Go encrypt..
Encrypt done..
d6e4d64b 27d8d055 c5c7573a 8df4e9aa
**********
****************
**************************
ccddeeff 8899aabb 44556677 112233
Go enc
rypt..
Encrypt done..
d6e4d64b 27d8d055 c5c7573a 8df4e9aa
....................
I would be very grateful if you could help me.

You may want to do as following:
f = open("your_file", "r")
for line in f:
do_something(line)
f.close()
or as the comment pointed out:
with open("your_file", "r") as f:
for line in f:
do_something(line)
Python will iterate over every line and give the string of the line as variable line here. You can handle every line in the file this way. Also, doing so, python reads one line each time, so it is effective for larger files.

During your for loop
for a in range (0,2):
line_array=lines[a]
plaintxt_16b=line_array[0:32]
plaintext=binascii.unhexlify(plaintxt_16b)
clear_msg=b'\x24'+b'\x73'+b'\x10'+plaintext
your overwrite the variable clear_msg in each iteration.
Once you leave the loop it contains the last value. In your case the last line (encrypted). Then you send the variable clear_msg several times without changing its content.
You need to indent the following block as well:
print(clear_msg)
ser.write(clear_msg)
time.sleep(0.4)

According to this, calling readlines() makes your code slower, less explicit, less concise, for absolutely no benefit.
A good approach to open a file without the need of closing it is by using while
with open(file) as f:
line = f.read().splitlines()
line is a list that contains all the lines of your file. You can iterate and get any entry as you would do in a list

The problem was spaces in python file: the for loop must contains
ser.write(clear_msg)
time.sleep(0.4)
print(ser.read(70))
By that way, it will not take just the last plaintext from the plaintext file.
import string
import serial
import time
from array import array
import struct
import binascii
ser = serial.Serial(
port='COM4',\
baudrate=230400,\
parity=serial.PARITY_NONE,\
stopbits=serial.STOPBITS_ONE,\
bytesize=serial.EIGHTBITS,\
timeout=0)
f = open(r'C:\\Users\\user\\Plaintxt.txt', 'r')
for a in f:
plaintxt_16b=a[0:32]
plaintext=binascii.unhexlify(plaintxt_16b)
clear_msg=b'\x24'+b'\x73'+b'\x10'+plaintext
ser.write(clear_msg)
time.sleep(0.4)
print(ser.read(70))
ser.close() # close ports
My problem is resolved. Thank you very much for your help.

Related

Slow serial communication with Arduino and Python

In a project of mine, I have to take a picture from a camera connected to a Sony Spresense Arduino board which is linked to my computer via an USB port. I am not very experienced in Arduino and serial communication, not at all in fact, so I am asking for some help.
I want to read the data from the camera which is sent in hexadecimal from the Arduino to my computer via a Serial.begin at a given baud rate, processed by a Python program in order to collect the hex code, correct it (there have been some print errors which are now solved), and convert it to a JPEG image.
I am able to do it, but the serial communication part of my program where Python collects the data from the Arduino is significantly slow, it takes 34 seconds to obtain an image that weighs "only" 100 ko (I don't know if it's a lot to handle for an Arduino), at a baud rate of 115200. If I try to increase this number, the hex code collected shows some errors and the image can not be converted. I can also change the pixel resolution of the image, but I'd like to be able to work with HD pictures.
In detail, here is the code from the Arduino, I have found no other way than this to get the data from the camera (there is no designed function in the Spresense library for serial communication). The relevant part is at the end :
#include <SDHCI.h>
#include <stdio.h> /* for sprintf */
#include <Camera.h>
#define BAUDRATE (115200)
/**
* Print error message
*/
void printError(enum CamErr err)
{
Serial.print("Error: ");
switch (err)
{
case CAM_ERR_NO_DEVICE:
Serial.println("No Device");
break;
case CAM_ERR_ILLEGAL_DEVERR:
Serial.println("Illegal device error");
break;
case CAM_ERR_ALREADY_INITIALIZED:
Serial.println("Already initialized");
break;
case CAM_ERR_NOT_INITIALIZED:
Serial.println("Not initialized");
break;
case CAM_ERR_NOT_STILL_INITIALIZED:
Serial.println("Still picture not initialized");
break;
case CAM_ERR_CANT_CREATE_THREAD:
Serial.println("Failed to create thread");
break;
case CAM_ERR_INVALID_PARAM:
Serial.println("Invalid parameter");
break;
case CAM_ERR_NO_MEMORY:
Serial.println("No memory");
break;
case CAM_ERR_USR_INUSED:
Serial.println("Buffer already in use");
break;
case CAM_ERR_NOT_PERMITTED:
Serial.println("Operation not permitted");
break;
default:
break;
}
}
void CamCB(CamImage img)
{
/* Check the img instance is available or not. */
if (img.isAvailable())
{
/* If you want RGB565 data, convert image data format to RGB565 */
img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);
}
else
{
Serial.print("Failed to get video stream image\n");
}
}
/**
* #brief Initialize camera
*/
void setup()
{
CamErr err;
/* Open serial communications and wait for port to open */
Serial.begin(BAUDRATE);
while (!Serial)
{
; /* wait for serial port to connect. Needed for native USB port only */
}
/* begin() without parameters means that
* number of buffers = 1, 30FPS, QVGA, YUV 4:2:2 format */
Serial.println("Prepare camera");
err = theCamera.begin();
if (err != CAM_ERR_SUCCESS)
{
printError(err);
}
/* Start video stream.
* If received video stream data from camera device,
* camera library call CamCB.
*/
Serial.println("Start streaming");
err = theCamera.startStreaming(true, CamCB);
if (err != CAM_ERR_SUCCESS)
{
printError(err);
}
/* Auto white balance configuration */
// Serial.println("Set Auto white balance parameter");
err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);
if (err != CAM_ERR_SUCCESS)
{
printError(err);
}
/* Set parameters about still picture.
* In the following case, QUADVGA and JPEG.
*/
Serial.println("Set still picture format");
// err = theCamera.setStillPictureImageFormat(
// CAM_IMGSIZE_QUADVGA_H,
// CAM_IMGSIZE_QUADVGA_V,
// CAM_IMAGE_PIX_FMT_JPG);
//err = theCamera.setStillPictureImageFormat(320, 240, CAM_IMAGE_PIX_FMT_JPG);
err = theCamera.setStillPictureImageFormat(CAM_IMGSIZE_QUADVGA_H, CAM_IMGSIZE_QUADVGA_V, CAM_IMAGE_PIX_FMT_JPG);
if (err != CAM_ERR_SUCCESS)
{
printError(err);
}
/**
* #brief Take picture with format JPEG per second
*/
/******** Affichage serie ********/
/* une ligne de vide et l'image */
Serial.println(" ");
CamImage img = theCamera.takePicture();
/* Check availability of the img instance. */
/* If any error was occured, the img is not available. */
if (img.isAvailable())
{
/*Indicateur de debut img : FFD8FF (Magic number of the jpeg format) */
for(int i=0;i<img.getImgSize();i++)
{
Serial.print(*(img.getImgBuff()+i),HEX); //img.getImgBuff() gets the data address of the picture, so the * before.
Serial.print(";");
}
/*End indicator : FFD9FF (Magic number of jpeg format) */
}
}
void loop()
{
// put your main code here, to run repeatedly:
sleep(1);
}
And here is the Python code :
## Serial collecting the data of the picture taken by the camera
import serial
from serial import Serial
import binascii
import string
from PIL import Image
import time
start_time = time.time()
ser = serial.Serial('COM3', baudrate=115200, timeout=1)
# writing the data in a text file
data = open("data.txt", "w")
data.write(str(ser.readlines()))
## Correcting the data
data = open("data.txt", "r")
string = str(data.readlines())
# spliting the string into a list
# I chose to use the ";" to split the different hex couples in the Arduino program
tab=string.split(";")
tab[0] = 'FF'
tab.pop(-1)
N = len(tab)
# correcting the arguments that are not couples :
# Indeed, when Arduino encounter a couple starting with a 0,
# it omits it, so I have to add it back manually
for i in range(N):
if len(tab[i]) == 1:
tab[i] = '0' + tab[i]
newdata = open("newdata.txt", "w")
# writing the new data in a text file
for s in tab:
newdata.write(s)
newdata.close()
data.close()
## Converting the hex data into a JPEG file
file = open("newdata.txt", "r")
data= file.read()
# conversion
data = binascii.a2b_hex(data)
# creation of the JPEG file
with open('imagenew.jpg', 'wb') as image_file:
image_file.write(data)
file.close()
img = Image.open('imagenew.jpg')
img.show()
print("--- %s seconds ---" % (time.time() - start_time))
If you have any idea or any advice in order to speed up this process I am taking it. I heard that there are some flow control and buffer stories here and there, but I am quite lost when I try to find something relevant to my situation. Thanks in advance.

Python I2C communication TTP229

I need to read 2 different bytes from TTP229 (16 keys or 8 keys touch pad detector).
I use I2C In Python. TTP229 datasheet PDF.
I can't read the second byte, but I can get the first byte.
Python code:
import smbus
bus = smbus.SMBus(1)
adressTTP229 = 0x57 #0xAF>>1
byte1 = bus.read_byte(adressTTP229)
byte2 = bus.read_byte(adressTTP229)
byte1 is always equal to byte2.
This Arduino code, works ok:
#include <Wire.h>
#define ttp229 (0xAF>>1)
void setup() {
Serial.begin(9600); // start serial for output
Wire.begin();
}
void loop() {
delay(50);
bool isNewData = false;
Wire.requestFrom(ttp229,2,true);
while (Wire.available()) {
uint16_t b1 = Wire.read(); // receive a first byte
uint16_t b2 = Wire.read(); // receive a second byte
if (b1==b2 && b2==0) {break;}
//...
}
}
How do I use Arduino's requestFrom() function in Python?
try:
import smbus, time
bus = smbus.SMBus(1)
while True:
print bus.read_word(0xAF)
time.sleep(0.1)
dont change address, bus doe the conversion, and if you read byte you will always get the same first byte. you want to read a word = 2 bytes at once
not tested, but might work, have it ordered and will test

Windows pipes: Write from C - read in Python

I'd like to transmit a few bytes of data though a pipe to plot it from python.
I started with some snippets I found here but I cant get them working.
I've created the pipe like this:
int main(void){
HANDLE hPipe;
char buffer[24];
DWORD dwRead;
hPipe = CreateNamedPipe(TEXT("\\\\.\\pipe\\Pipe"),
PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
PIPE_WAIT,
1,
24 * 16,
24 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
while (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE) // wait for someone to connect to the pipe
{
while (ReadFile(hPipe, buffer, sizeof(buffer) - 1, &dwRead, NULL) != FALSE)
{
/* add terminating zero */
buffer[dwRead] = '\0';
/* do something with data in buffer */
printf("%s", buffer);
}
}
DisconnectNamedPipe(hPipe);
}
return 0;}
If I execute the following code it writes but the read part blocks:
import time
import struct
f = open(r'\\.\\pipe\\Pipe', 'r+b', 0)
i = 1
sss='ccccc'
while True:
s = sss.format(i)
i += 1
f.write(struct.pack('I', len(s)) + s) # Write str length and str
f.seek(0) # EDIT: This is also necessary
print 'Wrote:', s
n = struct.unpack('I', f.read(4))[0] # Read str length
s = f.read(n) # Read str
f.seek(0) # Important!!!
print 'Read:', s
time.sleep(2)
I tried commenting the ReadFile part in the C code but It did not work. Is there any other way to achieve this? I want to write from C and read from python. I tried writing into the pipe with CreateFile (from C) and it worked as expected. I only need the read part with python.
On most systems pipe is one-directional and you use two pipes to get two-directional (bidirectional) connection.
In your Python code you can open two connections
and then you don't need seek
import time
import struct
wf = open(r'Pipe', 'wb', 0)
rf = open(r'Pipe', 'rb', 0)
i = 0
template = 'Hello World {}'
while True:
i += 1
text = template.format(i)
# write text length and text
wf.write(struct.pack('I', len(text)))
wf.write(text)
print 'Wrote:', text
# read text length and text
n = struct.unpack('I', rf.read(4))[0]
read = rf.read(n)
print 'Read:', read
time.sleep(2)
EDIT: tested on Linux Mint 17, Python 3.4 & 2.7
I've solved it with PyWin32(http://sourceforge.net/projects/pywin32/files/) which seems to be the right tool for windows. I would rather use something more cross-plataform oriented but it has solved the problem.

Can Python read from a Windows Powershell namedpipe?

I have the following named pipe created in Windows Powershell.
# .NET 3.5 is required to use the System.IO.Pipes namespace
[reflection.Assembly]::LoadWithPartialName("system.core") | Out-Null
$pipeName = "pipename"
$pipeDir = [System.IO.Pipes.PipeDirection]::InOut
$pipe = New-Object system.IO.Pipes.NamedPipeServerStream( $pipeName, $pipeDir )
Now, what i need is some Python code snippet to read from the above named pipe created. Can Python do that ?
Thanks in advance !
Courtesy :http://jonathonreinhart.blogspot.com/2012/12/named-pipes-between-c-and-python.html
Here's the C# Code
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
class PipeServer
{
static void Main()
{
var server = new NamedPipeServerStream("NPtest");
Console.WriteLine("Waiting for connection...");
server.WaitForConnection();
Console.WriteLine("Connected.");
var br = new BinaryReader(server);
var bw = new BinaryWriter(server);
while (true)
{
try
{
var len = (int)br.ReadUInt32(); // Read string length
var str = new string(br.ReadChars(len)); // Read string
Console.WriteLine("Read: \"{0}\"", str);
//str = new string(str.Reverse().ToArray()); // Aravind's edit: since Reverse() is not working, might require some import. Felt it as irrelevant
var buf = Encoding.ASCII.GetBytes(str); // Get ASCII byte array
bw.Write((uint)buf.Length); // Write string length
bw.Write(buf); // Write string
Console.WriteLine("Wrote: \"{0}\"", str);
}
catch (EndOfStreamException)
{
break; // When client disconnects
}
}
}
}
And here's the Python code:
import time
import struct
f = open(r'\\.\pipe\NPtest', 'r+b', 0)
i = 1
while True:
s = 'Message[{0}]'.format(i)
i += 1
f.write(struct.pack('I', len(s)) + s) # Write str length and str
f.seek(0) # EDIT: This is also necessary
print 'Wrote:', s
n = struct.unpack('I', f.read(4))[0] # Read str length
s = f.read(n) # Read str
f.seek(0) # Important!!!
print 'Read:', s
time.sleep(2)
Convert the C# code into a .ps1 file.

reading data from arduino with python

im trying to do something which arduino sends bunch of data frequently, and my objective is:
every 100 data, make a new file. (lets call it a1, a2, ...)
in one generic file, take the average of each of these a files and write it inside of that file as a new line
for experiment i coded my arduino like that:
void setup(){
Serial.begin(9600);
}
void loop(){
Serial.println(random(100,500));
delay(20);
}
and here is the python code:
import serial, struct
initialfreq = 0
a = 0
interval = 0
fileName = 'general_list'
general_list = open(fileName, 'wb')
ser = serial.Serial(port = 'COM3', baudrate = 9600)
def mean(numberList):
return sum(numberList) / len(numberList)
while(1):
for i in '100' :
temparray=[]
fileName = 'interval' + str(initialfreq) + '.data'
temp_file = open(fileName, 'wb')
readoff = ser.readline()
temparray.append(readoff)
temp_file.write(readoff)
## temp_file.flush()
print("bitti")
general_list.write(str(interval)+" "+str(mean(temparray)))
general_list.write(str(mean(temparray)))
initialfreq= initialfreq + 1
a=0`
my problem is,
for loop is not working properly, even when i sad 100, its not taking 100 values.
arduino sending codes with \n. i cant see them in files but in temparray i see that there is \n 's so its not calculating the average.
thanks a lot guys.
Here is the solution for your first problem.
1)
for i in range(100):

Categories

Resources