1

Afternoon all,

I have a webpage that is being used to write NFC tags. When I submit the form on the page PHP sends the variables to the python script. This script (write.py) checks that the read.py script is killed and processes the write request. This part works fine.

The issue I have is when I recall the read.py, it contains a loop which is preventing the web page from refreshing once the write is complete. I have tried calling the read.py from inside the PHP script and at the end of the write.py and the same thing happens. I have also tried adding a & to the end of the read.py command.

Could someone please have a look at what I have so far and let me know what I am doing wrong and how I would go about fixing it please.

Cheers,

Blinky

HTML/PHP

<?php
session_start();
if( !empty( $_POST ) )
{
    echo "Write to card using python";
    $company = $_POST[ 'company' ];
    $name    = $_POST[ 'name' ];
    $email   = $_POST[ 'email' ];
    $cmd     = "sudo python write.py '$company' '$name' '$email' &";
    $resp    = shell_exec( $cmd );
    if( strpos( $resp, 'written' ) !== false )
    {
        header("Location: http://192.168.1.176/index.php");
    }
    unset( $_POST );
}
?>

<form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="post">
    <input type="text" name="name" id="name">
    <input type="text" name="email" id="email">
    <select name="company" id="company">
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
    </select>
    <input type="submit">
</form>

read.py

#!/usr/bin/env python
# -*- coding: utf8 -*-

import RPi.GPIO as GPIO
import MFRC522
import signal
import MySQLdb
import os
from datetime import datetime

os.system("sudo kill $(ps aux | grep 'write.py' | awk '{print $2}')")

db = MySQLdb.connect(host="", user="", passwd="", db="")
cursor = db.cursor()

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()

# Welcome message
print "Welcome to the MFRC522 data read example"
print "Press Ctrl-C to stop."

# 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"

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

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

        uid_str = str(uid[0])+"."+str(uid[1])+"."+str(uid[2])+"."+str(uid[3])
        # Print UID
        #print "Card read UID: "+str(uid[0])+","+str(uid[1])+","+str(uid[2])+","+str(uid[3])
        #print "\n".join(str(uid))    
        # 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:
            print "Inserting data"
            data = MIFAREReader.MFRC522_Read(8)
            try:
                date_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                query = "INSERT INTO %s (tag_uid, company, date_time, card_data) VALUES ('%s', '%s', '%s', '%s')"%('attendance_reader',uid_str,1,str(date_time),data)
                cursor.execute(query)
                db.commit()
                print "Data committed"
            except (MySQLdb.Error, MySQLdb.Warning) as e:
                print(e)
                print "Error: the database is being rolled back"
                db.rollback()
            MIFAREReader.MFRC522_StopCrypto1()
        else:
            print "Authentication error"

write.py

#!/usr/bin/env python
# -*- coding: utf8 -*-

import RPi.GPIO as GPIO
import MFRC522
import signal
import sys
import binascii
import os
import time
from random import randint

os.system("sudo kill $(ps aux | grep 'read.py' | awk '{print $2}')")

company = sys.argv[1]
name    = sys.argv[2]
email   = sys.argv[3]

ident_code = [int(company)]
for x in range(0,15):
    ident_code.append(randint(001, 255))

print ident_code

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"

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

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

    # 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)
    #print "\n"

    # Check if authenticated
    if status == MIFAREReader.MI_OK:

        #print "Sector 8 will now be filled with 0xFF:"
        # Write the data
        MIFAREReader.MFRC522_Write(8, ident_code)

        # Stop
        MIFAREReader.MFRC522_StopCrypto1()
        #time.sleep(5)
        continue_reading = False
        os.system( "sudo python read.py" )
        # os.system( "sudo python read.py &" )
        # os.system( "sudo kill $(ps aux | grep 'write.py' | awk '{print $2}')" )
        # Make sure to stop reading for cards
    else:
        print "Authentication error"
Blinkydamo
  • 1,582
  • 9
  • 20
  • Where exactly are you calling read.py at the moment? – roelofs Nov 22 '17 at 13:29
  • At the bottom of the write file, I have also tried calling it from the PHP file as well – Blinkydamo Nov 22 '17 at 13:30
  • I'm not sure if adding a & when calling from within PHP will have the desired effect. Have you considered putting a timeout around the loop, dropping back to php, and if nothing was read, executing it again? It's a bit of a hard 'yield', but might work. – roelofs Nov 22 '17 at 13:32
  • That loop will tie up that entire process. – roelofs Nov 22 '17 at 13:32
  • So if the loop is preventing the reload how do I get around it? Surely a timeout will hold up the page reload for a set time and then the loop will start and prevent the page reload as well? – Blinkydamo Nov 22 '17 at 13:35
  • Yes. The other option is to use PHP to loop the read.py file. That way, your PHP can refresh if something is available, and you don't have to worry about killing and restarting processes? – roelofs Nov 22 '17 at 13:42
  • Can you update your question to show where in the PHP file you would be calling the ready.py script right now? – roelofs Nov 22 '17 at 13:42
  • Please excuse this question, but my PHP is rusty. Does your PHP check for a database update (which is what read.py seems to do), before calling write.py? I'm sure there is a way to solve your query, but just wondering whether there's an overall more elegant approach to solving it. – roelofs Nov 22 '17 at 13:47
  • Just found something that might fix your immediate problem: https://stackoverflow.com/questions/3595685/start-python-script-as-background-process-from-within-a-python-script – roelofs Nov 22 '17 at 13:50

0 Answers0