TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

File path as string

Thu Jul 10, 2014 1:38 pm

All,

I am working on a script for RFID. I will have a folder that has only one file, but that filename changes, and I have therefore called the file as a variable. Running the script shows that the variable filename is found correctly.

After a UID is found from the RFID reader, I need the script to open the variable filename, and append the file with the newly-found UID.

The card reads successfully, but nothing is copied into the variable file.

I'd appreciate a second set of eyes on this. I'm rather new to python, so please forgive my ignorance.

Code: Select all

import RPi.GPIO as GPIO
import MFRC522
import signal
import glob
MYFILE = glob.glob('/home/pi/RXRFID/newscans/*.txt')

continue_reading = True


# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
    global continue_reading
    print "Ctrl+C captured, ending read."
    continue_reading = False
    GPIO.cleanup()

# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:

    # Scan for cards
    (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

    # If a card is found
    if status == MIFAREReader.MI_OK:
        print "Card detected"
        print MYFILE

    # Get the UID of the card
    (status,uid) = MIFAREReader.MFRC522_Anticoll()

    # If we have the UID, continue
    if status == MIFAREReader.MI_OK:

        # Print UID
        print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])

User avatar
Douglas6
Posts: 4874
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: File path as string

Thu Jul 10, 2014 3:17 pm

glob will return a list of file names (there could be more than one). If you know there is exactly one, you need to use something like

Code: Select all

MYFILE = glob.glob('/home/pi/RXRFID/newscans/*.txt')[0]
for the file name. If I'm understanding correctly, you will then need to open that file for appending, and append the card name (from my failing memory):

Code: Select all

f = open(MYFILE, 'a')
f.write(str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3]+"\n")
and when you're all done, close the file.

Code: Select all

f.close()
Or, more pythonically:

Code: Select all

with open(MYFILE, 'a') as f:
    f.write(str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3]+"\n")

TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

Re: File path as string

Thu Jul 10, 2014 3:45 pm

Thank you,

I rewrote per your instructions, but am receiving an error:

f.close() invalid syntax

Any thoughts as to what might be the problem?

Update: I found the syntax problem to in the f.write command as a parenthesis was missing for uid[3]).

However, I am now getting an error on the f.write line that the list index is out of range. I have confirmed there is only one file in the listed directory, and the script prints the file path correctly.

User avatar
AndrewS
Posts: 3625
Joined: Sun Apr 22, 2012 4:50 pm
Location: Cambridge, UK
Contact: Website

Re: File path as string

Thu Jul 10, 2014 4:33 pm

Perhaps 'uid' contains less than 4 elements?
I'd personally rewrite

Code: Select all

    f.write(str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])+"\n")
as

Code: Select all

    uid_str = ",".join([str(x) for x in uid])
    f.write(uid_str+"\n")
as it's both more compact, and it'll work with any number of elements in 'uid'.

TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

Re: File path as string

Thu Jul 10, 2014 4:51 pm

Now the error is:

uid_str = ",".........
NameError: name 'uid' is not defined.

Doesn't uid_str = set the uid name?

User avatar
Douglas6
Posts: 4874
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: File path as string

Thu Jul 10, 2014 4:58 pm

It's telling you that uid is not defined. uid gets defined here:

Code: Select all

(status,uid) = MIFAREReader.MFRC522_Anticoll()
Are you trying to write the UID out before having read it? Perhaps you should post your current code.

TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

Re: File path as string

Thu Jul 10, 2014 5:01 pm

I'm using cards that are read only, so I can't write the uid. Full code below.

Code: Select all

import RPi.GPIO as GPIO
import MFRC522
import signal
import glob
MYFILE = glob.glob('/home/pi/RXRFID/newscans/*.txt') [0]

continue_reading = True


# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
    global continue_reading
    print "Ctrl+C captured, ending read."
    continue_reading = False
    GPIO.cleanup()

# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:

    # Scan for cards
   (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

    # If a card is found
if status == MIFAREReader.MI_OK:
        print "Card detected"
        print MYFILE

with open(MYFILE, 'a') as f:
    uid_str = ",".join([str(x) for x in uid])
    f.write(uid_str+"\n")
f.close()

    # Get the UID of the card
(status,uid) = MIFAREReader.MFRC522_Anticoll()


    # If we have the UID, continue
if status == MIFAREReader.MI_OK:

        # Print UID
        print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])

        # This is the default key for authentication
        key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]

        # Select the scanned tag
        MIFAREReader.MFRC522_SelectTag(uid)

        # Authenticate
        status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 8, key, uid)

        # Check if authenticated
        if status == MIFAREReader.MI_OK:
            MIFAREReader.MFRC522_Read(8)
            MIFAREReader.MFRC522_StopCrypto1()

User avatar
Douglas6
Posts: 4874
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: File path as string

Thu Jul 10, 2014 5:31 pm

I meant writing the UID to the file before you have it, which is indeed what you are trying to do. But it also looks like your indentation has gone bad. Python is very picky about indentation, you'll want to read a tutorial to learn how and why to properly indent a Python program.

In the meantime, what you want is more like this [UNTESTED]:

Code: Select all

    
import RPi.GPIO as GPIO
import MFRC522
import signal
import glob
MYFILE = glob.glob('/home/pi/RXRFID/newscans/*.txt')[0]

continue_reading = True

# Capture SIGINT for cleanup when the script is aborted
def end_read(signal,frame):
    global continue_reading
    print "Ctrl+C captured, ending read."
    continue_reading = False
    GPIO.cleanup()

# Hook the SIGINT
signal.signal(signal.SIGINT, end_read)

# Create an object of the class MFRC522
MIFAREReader = MFRC522.MFRC522()

# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:

    # Scan for cards
    (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)

    # If a card is found
    if status == MIFAREReader.MI_OK:
        print "Card detected"
        print MYFILE

        # Get the UID of the card
        (status,uid) = MIFAREReader.MFRC522_Anticoll()

        # If we have the UID, continue
        if status == MIFAREReader.MI_OK:
            # Print UID
            print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])

            # Write the card UID to a file
            with open(MYFILE, 'a') as f:
                uid_str = ",".join([str(x) for x in uid])
                f.write(uid_str+"\n")

            # This is the default key for authentication
            key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]

            # Select the scanned tag
            MIFAREReader.MFRC522_SelectTag(uid)

            # Authenticate
            status = MIFAREReader.MFRC522_Auth(MIFAREReader.PICC_AUTHENT1A, 8, key, uid)

            # Check if authenticated
            if status == MIFAREReader.MI_OK:
                MIFAREReader.MFRC522_Read(8)
                MIFAREReader.MFRC522_StopCrypto1()

User avatar
AndrewS
Posts: 3625
Joined: Sun Apr 22, 2012 4:50 pm
Location: Cambridge, UK
Contact: Website

Re: File path as string

Thu Jul 10, 2014 7:08 pm

Yeah, you could also move the

Code: Select all

uid_str = ",".join([str(x) for x in uid])
line to immediately above the '# Print UID' line (remembering to adjust the indentation as appropriate), and then change the line immediately after '# Print UID' to just

Code: Select all

print "Card read UID: "+uid_str
Note: Also untested as I don't have an RFID reader ;)

User avatar
Douglas6
Posts: 4874
Joined: Sat Mar 16, 2013 5:34 am
Location: Chicago, IL

Re: File path as string

Thu Jul 10, 2014 7:17 pm

That's better, as it ensures that "what you see (on the console) is what you get (in the file)" (and handles the case where there are fewer (or more) than 4 items in uid[].) I was being lazy.

TW79
Posts: 36
Joined: Wed Jul 02, 2014 4:09 pm

Re: File path as string

Thu Jul 10, 2014 7:45 pm

Wow!

Thank you very much for your help. The script you provided works marvelously.

I am now going to start on my next step: Making this script wait for a button command then execute a different script.

Return to “Python”