Novell Home

HowTo: Create a Factory Rejects Data Recording system Part 2

Novell Cool Solutions: Feature
By Stomfi

Digg This - Slashdot This

Posted: 2 Mar 2005
 

StomfiLearning to use Linux at Home and Work
Welcome to my ongoing series of HowTo articles designed to help Linux newbies get comfortable with Linux. Before trying any of these HowTos, take a few minutes to study the prerequisites so you can hit the ground running.
--Stomfi

This HowTo explains the creation of a turn key system for collecting and analysing factory reject data. See part one.

First a conventional data entry system using collected hand filled out forms will be developed and tested.

Second a factory floor point of origin data entry system using conventional keyboards and screens, will be developed, using the previous data collection files and analysis system.

Third a replacement wireless pocket sized hand held data entry and read out device will be designed to replace conventional keyboards and screens with multi unit base stations for each work area.

Runtime Revolution and the Linux shell tools are the tools used to develop and create this system without requiring any specialised programming skill. Reading HowTos and Linux manuals is as heavy as it gets. When using RunRev you'll find it works best in the Gnome desktop.

The use of Linux has let this system be developed. Any other solution platform would put the cost way out of the reach of the small businesses for whom it was designed.

To simplify things each program module has been developed as a separate RunRev program stack, although RunRev has the ability to combine several stacks into one program. We shall have a look at this aspect at the end of each development.

This is the program stack window which calls the other stacks. It is named "RejCtl"."

In the first part we developed this stack and the stack for the New Rejects Entry Screen. We combined both stacks into a single application.

In this part we shall develop the stacks for the administration buttons. Open the rejctl.rev stack and add the two bottom buttons and the label.

We shall now have a look at the script for the PRODUCTS button.

on mouseUp

#This presumes the RejCtl application is saved with the Products stack.

go stack "Products"

close stack "RejCtl"

end mouseUp

Prodadmin is the name of our new stack. Open a completely new stack and give it the name "Products" in the stack property inspector pop up dialog. In the card property inspector give the card the name "ProductAdmin" and give it the label "Product Admin".

This is the Product Admin card.

Place all the fields, buttons and labels as shown.

There are more labels and buttons which are hidden at this point by having their visible property switched off.

This is the Application browser window showing all objects.

The New Fields are label fields which I didn't bother to rename.

As the only instruction is for the SEARCH button, that's what you do.

A search pop up window appears.

As the instruction says you can put any search string in here. Unusual characters will put an error message into the Product List field.

This is the list for "wheel". You can see that the search is not case sensitive.

Using the mouse to select a product from the list, puts its name into the Product Selection field, and puts Yes or No into the four fields under the list.

We can Delete or Modify the selected product and we can Add a new one.

The next picture shows what happens when the Modify button is clicked.

We can modify the name or click the Cancel button to retain the current one.

When the OK or Cancel button is clicked all the hidden fields and buttons appear.

These new buttons allow us to modify the Work Areas for the product. clicking any one allows modification or not. Not clicking them retains what was there already.

This is the pop up that appears when a button is clicked.

After all modifications have been done the user clicks the Work Area Done button.

This deletes the original record and adds the modifications as a new one.

The Messages field shows the final status.

To leave the application the user clicks the x at the top of the screen. I think this is OK for this application, but it may cause problems in the new rejects screen, so we should have a look at putting in a QUIT button and not having the x button.



This is the Basic Properties for the stack. Clicking the Controls button allows us to switch off the functions of the title bar controls.

Don't do this until the very end otherwise you can't move or minimise the window while you are developing.

Add a QUIT button and set the script to:

on mouseUp

go stack "RejCtl"

close stack "Products"

end mouseUp

Now we shall have a look at the scripts that allow all these activities to take place.

Starting from the Card script.

on openCard

   global SPRODUCT

   set the invisible of field "WorkAreaMsg" to true

   set the invisible of button "CAST" to true

   set the invisible of button "MC" to true

   set the invisible of button "LIN" to true

   set the invisible of button "PIM" to true

   set the invisible of button "DONE" to true

   global ADDONE

   global MODDONE

   put "NO" into ADDONE

   put "NO" into MODDONE

   put empty into field "PRODUCT"

   put empty into field "RESPONSE"

   put empty into field "PCAST"

   put empty into field "PLIN"

   put empty into field "PMC"

   put empty into field "PPIM"

end openCard

This script hides the fields and buttons for the work area input, sets up some global variables and empties all the data fields for a clean page at start up.

The next script is the one for the SEARCH button.

on mouseUp

   set the invisible of field "WorkAreaMsg" to true

   set the invisible of button "CAST" to true

   set the invisible of button "MC" to true

   set the invisible of button "LIN" to true

   set the invisible of button "PIM" to true

   set the invisible of button "DONE" to true

   global ADDONE

   global MODDONE

   put "NO" into ADDONE

   put "NO" into MODDONE 

   put empty into field "PCAST"

   put empty into field "PMC"

   put empty into field "PLIN"

   put empty into field "PPIM"

   ask "Enter product name or search pattern"

   global SPRODUCT

   put it into SPRODUCT

   if SPRODUCT <> empty

   then

      # create a case insensitive pattern matching shell command

      put ("grep -i " & SPRODUCT && $HOME & "/frejects/lists/products.
         txt | awk -F# '{print $1}'") into mycommand

      replace return with empty in mycommand

      put the shell of mycommand into field "SLIST"

   end if

end mouseUp 

The first part of this script repeats the open card functions. Then we use the "ask" command which creates the pop up window. The user response gets put into SPRODUCT. The if test makes sure the rest of the script doesn't get run if the user has either clicked Cancel or OK without entering anything.

The end result of the grep -i is piped to awk to print out only the product names. The resulting list gets put into the Product List.

Clicking a product in this list activates the list script.

on mouseDown

   #create a global variable name to hold the whole product line from
      the database file

   global LongProd

   put the selectedText of me into HPROD

   #Check in case a blank line was clicked

   if HPROD <> empty

   then

      #Put the product name into the Product Selection field so that 
         Delete or Modify can use it

      put HPROD into field "PRODUCT"

      #Fetch the Long Product 

      put ("grep" && quote & HPROD & quote && $HOME & "/frejects/lists/
         products.txt") into onecom

      replace return with empty in onecom

      put the shell of onecom into LongProd


      #Cut up LongProd and put the bits into the relevant fields or 
         variable names

      put ("echo " & LongProd & "|cut -d# -f4") into Castcom

      replace return with empty in Castcom

      put the shell of Castcom into field "PCAST"

      put ("echo " & LongProd & "|cut -d# -f5") into Machcom

      replace return with empty in Machcom

      put the shell of Machcom into field "PMC"

      put ("echo " & LongProd & "|cut -d# -f6") into Lincom

      replace return with empty in Lincom

      put the shell of Lincom into field "PLIN"

      put ("echo " & LongProd & "|cut -d# -f7") into Pimcom

      replace return with empty in Pimcom

      put the shell of Pimcom into field "PPIM"


      #Save existing data when modifying. We are not creating this 
         bit in this example

      global CUST

      global CUSTNO

      put ("echo " & LongProd & "|cut -d# -f2") into CustName

      replace return with empty in CustName

      put the shell of CustName into CUST

      put ("echo " & LongProd & "| cut -d# -f3") into CustCode

      replace return with empty in CustCode

      put the shell of CustCode into CUSTNO

   end if

end mouseDown

I think this script is self explanatory. The CUST and CUSTNO variables are used in a real application, but not in this example. The fields are there in the database file, so these variables are used to save this info when modifying a product. Another RunRev data entry application is used by accounting staff on an MS windows machine to fill in these two fields in the real world database application.

The next scripts show the DELETE, ADD and MODIFY button actions.

First is the delete button RunRev actions.

on mouseUp

   put field "PRODUCT" into DPROD

   put ($HOME & "/frejects/bin/delprod.sh " & quote & DPROD & quote)
      into DelProd

   replace return with empty in DelProd

   answer "Really delete this product?" with "Yes" or "No"

   put it into SURE

   if SURE = "Yes"

   then

      open process DelProd for read

      read from process DelProd until EOF

      put it into field "RESPONSE"

      close process DelProd

   end if 

   global SPRODUCT

   put ("grep -i" && quote & SPRODUCT & quote && $HOME & "/frejects/
      lists/products.txt | awk -F# '{print $1}' " ) into mycommand

   put the shell of mycommand into field "SLIST"

end mouseUp

Now the delprod.sh shell script.

#!/bin/bash

#delprod.sh product

#

#Change product into RE

PRODUCT=`echo $@`

#DEBUG

#touch $HOME/frejects/tmp/deleted.txt

#echo $PRODUCT >> $HOME/frejects/tmp/deleted.txt

#

#should create a file lock here so no one else can do anything

if [ -e $HOME/frejects/tmp/products.lock ]

then

   echo "File in use. Delete aborted"

   exit

else

   echo "locked" & $HOME/frejects/tmp/products.lock 

   mv -f $HOME/frejects/lists/products.txt $HOME/frejects/lists/
dproducts.txt 

   grep -v "$PRODUCT" $HOME/frejects/lists/dproducts.txt > $HOME/
frejects/lists/eproducts.txt 

   if [ ! -s $HOME/frejects/lists/eproducts.txt ]

   then

      #didn't work as size is less than 1

      mv -f $HOME/frejects/lists/dproducts.txt $HOME/frejects/lists/
         products.txt 

      echo "Problem with delete. Original list restored"

      rm -f $HOME/frejects/tmp/products.lock 

      exit

   else

      mv -f $HOME/frejects/lists/eproducts.txt $HOME/frejects/lists/
         products.txt 

   fi

   echo "Product Deleted"

   rm -f $HOME/frejects/tmp/products.lock 

fi

exit

Now the add RunRev button script.

on mouseUp

   global NCAST

   global NMC

   global NLIN

   global NPIM

   global NPROD

   global WADONE

   global ADDONE

   #These make sure that we set the new name and the needed work areas

   put empty into NPROD

   put "No" into NCAST

   put "No" into NMC

   put "No" into NLIN

   put "No" into NPIM

   put "NO" into WADONE

   #Ask for a new product name

   ask "Enter Full Product Name"

   put it into NPROD

   #Check that we got a name before we do any actions.

   if NPROD <> empty

   then

      put NPROD into field "PRODUCT"

      #This lets the DONE button script know it's a new addition

      put "YES" into ADDONE


      # SHOW WORKAREA BUTTONS

      set the invisible of field "WorkAreaMsg" to false

      set the invisible of button "CAST" to false

      set the invisible of button "MC" to false

      set the invisible of button "LIN" to false

      set the invisible of button "PIM" to false

      set the invisible of button "DONE" to false

   end if

end mouseUp

And lastly the MODIFY button RunRev script.

on mouseUp

   global LongProd

   global NPROD

   #Make sure the N variables are populated with the existing values 

   put field "PRODUCT" into NPROD

   global NCAST

   put field "PCAST" into NCAST

   global NMC

   put field "PMC" into NMC

   global NLIN

   put field "PLIN" into NLIN

   global NPIM

   put field "PPIM" into NPIM

   #Ask for a modified name or none

   ask "Enter Modified Product Name or Cancel for no change"

   put it into ENPROD

   #Check for a value before acting on it

   if ENPROD <> empty

   then

      put ENPROD into NPROD

      put NPROD into field "PRODUCT"

   end if

   #Let the DONE button know this is a modification

   global MODDONE

   put "YES" into MODDONE

   # SHOW WORKAREA BUTTONS

   set the invisible of field "WorkAreaMsg" to false

   set the invisible of button "CAST" to false

   set the invisible of button "MC" to false

   set the invisible of button "LIN" to false

   set the invisible of button "PIM" to false

   set the invisible of button "DONE" to false

end mouseUp

The next actions are associated with the Work Areas. This is the script for one of the work area buttons. The other scripts are similar with the message and the variable names relevant to the individual work area.

on mouseUp

   global NCAST

   answer "Mark Product for Casting Work" with "Yes" or "No"

   put it into NCAST

   put it into field "PCAST"

end mouseUp

Now for the DONE button which calls the shell scripts that add to or modify the database file.

on mouseUp

   #Declare all the global variables

   global ADDONE

   global MODDONE

   global NPROD

   global NCAST

   global NMC

   global NLIN

   global NPIM

   global LongProd

   global CUST

   global CUSTNO

   #Find out whether one of the DONE variables have been set to YES
      before taking any action

   if ADDONE = "YES" or MODDONE = "YES"

   then

      if ADDONE = "YES"

      then

         put "Adding Product" into field "RESPONSE"

         global WADONE

         put "DONE" into WADONE

         #Create the new product database line

         put (NPROD & "#" & CUST & "#" & CUSTNO & "#" & NCAST & "#" &
           NMC & "#" & NLIN & "#" & NPIM) into NewPLine

         replace return with empty in NewPLine

         put ($HOME & "/frejects/bin/newprod.sh" && NewPLine) into
           NewProd

         replace return with empty in NewProd

         #Do the new product shell script and read the response

         open process NewProd for read

         read from process NewProd until EOF

         put it into field "RESPONSE"

         close process NewProd

         #Reset the ADDONE variable to NO

         put "NO" into ADDONE

      end if

      if MODDONE = "YES"
      
      then

         put "Modifying Product" into field "RESPONSE"

         #Create the Modified product database line

         put (NPROD & "#" & CUST & "#" & CUSTNO & "#" & NCAST & "#" &
            NMC & "#" & NLIN & "#" & NPIM) into MPROD

         replace return with empty in MPROD

         #Set up the add and delete shell script commands

         put ($HOME & "/frejects/bin/newprod.sh " & MPROD) into NewMod

         replace return with empty in NewMod

         put ($HOME & "/frejects/bin/delprod.sh " & LongProd) into DelMod

         replace return with empty in DelMod

         #Delete the original product line

         open process DelMod for read

         read from process DelMod until EOF

         put it into field "RESPONSE"

         close process DelMod


         #There really should be an if check based on a success message
            from DelMod before NewMod is run

         #I'll leave that for the clever one to implement.

         #Add the newly modified product line

         open process NewMod for read

         read from process NewMod until EOF

         put it into field "RESPONSE"

         close process NewMod

         #Reset the MODDONE variable to NO

         put "NO" into MODDONE

      end if

      #Search and list the new product name

      put ("echo" && quote & NPROD & quote & "|awk '{print $1}'")
         into SearchName

      replace return with empty in SearchName

      put the shell of SearchName into SearchProd

      put ("grep -i" && quote & SearchProd & quote && $HOME & "/frejects
         /lists/products.txt|awk -F# '{print $1}'") into pshell

      replace return with empty in pshell

      put the shell of pshell into field "SLIST"

      #Hide the work area messages and buttons 

      set the invisible of field "WorkAreaMsg" to true

      set the invisible of button "CAST" to true

      set the invisible of button "MC" to true

      set the invisible of button "LIN" to true

      set the invisible of button "PIM" to true

      #We can't hide the DONE button because we are still using it

      #Clever users may figure out how to do this

   end if

end mouseUp

This is the newprod.sh shell script.

#!/bin/bash

#newprod.sh productfileline

#

#should create a file lock here so no one else can 

#add or delete to the product list

if [ -e $HOME/frejects/tmp/products.lock ]

then

   echo "File in use. Add new aborted"

   exit

else

   echo "locked" > $HOME/frejects/tmp/products.lock 

   #Copy file to process file

   cp -f $HOME/frejects/lists/products.txt $HOME/frejects/lists/
      aproducts.txt

   #echo newline and product into file

   #DEBUG

   #echo "$@" >> $HOME/frejects/tmp/newproducts.txt

   #END DEBUG

   echo -e "\n$@" >> $HOME/frejects/lists/aproducts.txt

   #Sort file

   sort -f -o $HOME/frejects/lists/bproducts.txt $HOME/frejects/lists/
      aproducts.txt

   #get rid of any duplicates

   uniq $HOME/frejects/lists/bproducts.txt > $HOME/frejects/lists/
      cproducts.txt

   #get rid of blank lines

   sed -e /^$/d $HOME/frejects/lists/cproducts.txt > $HOME/frejects/
      lists/dproducts.txt

   #copy process file back to production list

   cp -f $HOME/frejects/lists/dproducts.txt $HOME/frejects/lists/
      products.txt

   echo "Product Added"

   rm -f $HOME/frejects/tmp/products.lock 

fi

exit

Don't forget to add the QUIT button as shown above. Finally change the window decoration functions as shown.

Open the new rejects stack and do these same things for it, creating a QUIT button with its script as:

on mouseUp

   go stack "RejCtl"

   close stack "NewRejects"

end mouseUp

and then change the NewRejects button script in the RejCtl stack to this.

on mouseUp

   #This presumes the RejCtl application is saved with the Products
      stack included.

   go stack "NewRejects"

   close stack "RejCtl"

end mouseUp

All that's left to do is to compile the project. There are three stacks now. Open the RejCtl stack and save and close all other stacks. In the file menu select Distribution Settings. In the Stacks tab, add the newrejects.rev and the products.rev stacks. Click the x to quit this window. In the File menu select Build as Standalone distribution and build it in the frejects bin directory. The program will be what you called it and its folder will include the newrejects.rev and the products.rev files. When you run the program it will open these files when you click the relevant button, and close the RejCtl stack. When you quit the rejects or products stacks it will reopen the RejCtl stack. The file is only 2M plus the small amount for the .rev files.

In the three stacks and their associated shell scripts, you have developed a real world application which can be modified for use in an actual business you know. The one I built is being used as you read this. The cost for the hardware was $0 as a disused P2 was used. The cost of the software was $11 for a magazine with KNOPPIX which was installed on the hard drive, and $199 for RunRev. The development cost was $300 as it was done by two factory workers at a Linux end user course as a real world project. A reinstall CD was also created to minimise maintenance. Total cost $510. total time 10 man days.

Since all data is backed up to the corporate MS environment, the worst case scenario is reinstalling the system on another inexpensive PC.

Quotes from MS centric sources for the same system functions were $40,000 and $15,000, with at least 6 month development time. So the small business achieved savings of at least $14,490, and had their system operational within a month. Viva Linux users!

In the next part of this how to we shall build the Operators admin and Charting stacks and the shell scripts that do the processing, and add these to our RejCtl application. This will finish the first aim of this HowTo.


Novell Cool Solutions (corporate web communities) are produced by WebWise Solutions. www.webwiseone.com

© 2014 Novell