USB Badge Reader
Hello All,
I have a USB badge reader, that I'd like to use for authenticating users to access a touch panel. I have a CSV file of all of the users that are allowed access. I'm trying to figure out the best way to program the panel for authentication. Basically, the badge reader just works as a keyboard function, inputting the badge ID number when it's scanned.
Thanks,
Matt
I have a USB badge reader, that I'd like to use for authenticating users to access a touch panel. I have a CSV file of all of the users that are allowed access. I'm trying to figure out the best way to program the panel for authentication. Basically, the badge reader just works as a keyboard function, inputting the badge ID number when it's scanned.
Thanks,
Matt
0
Comments
When text comes in from this it will then fill into this button. From here you a couple of options:
1) Add a button with it's port set to the loopback port (0) and channel of 'Keyboard: Exit'. When pressed this will fire the contents of all of your text inputs on that page back to the master as a string event prefixed with the text input button's name. Depending on your desired interaction pattern you could also have this hidden and use a do_push *shudder* at say a one second interval when your are in this area of your UI.
2) Alternatively, you could query the contents of this button at a set interval. This would keep all controls hidden and enable your users to auth etc just by the physical interaction with the reader.
Hey Kim,
Thanks so much for the help! I am trying to do exactly what you thought, hooking it directly to the panel and using it as the keyboard function. What I think I am going to need the most help with is getting it to authenticate based on the numbers it reads. I have a CSV file with all of the badge numbers available, but how do I get the master to check against these numbers?
If you could provide any netlinx code I'd appreciate any help I can get!
THANKS!
Depending on your environment though (number of users, frequency of updates etc.) you may want to store this sort of data in an external service though and query it as required.
Thanks Kim,
I'm a novice programmer, so I think this is going to be way above my head. For testing of the equipment purposes, is there a simple way to see if the reader is working and make it flip pages?
Thanks,
Matt
Also, don't be afraid I've diving into something that seems over your head. If you keep doing what your comfortable doing you never have any fun
Okay thanks,
So I tried that, and sure enough it did read the badge and numbers appeared in the box. Without getting overly complicated for now, how would I create a string of code in netlinx that would authenticate a page flip based on if only my badge ID was entered? I'll dive into the CSV file and all that once I get a better sense of what I'm doing! Thanks for the words of encouragement! You seem like a very talented programmer.
Matt
Been fooling around with this all day: Can't seem to get it to work just for basic testing. Any ideas where I'm going wrong?
PROGRAM_NAME='Keypad Testing'
DEFINE_DEVICE
dvTP = 10001:1:0 //AMX Modero NXTCV10
dvMaster = 0:1:0 //NI700 Master Controller
DEFINE_START
SEND_COMMAND dvTP, "'?TXT-1,0'"
DEFINE_VARIABLE
NON_VOLATILE char Text[11]
DEFINE_EVENT
DATA_EVENT[dvTP]
{
ONLINE:
{
SEND_COMMAND dvTP, 'PAGE-Swipe'
}
}
BUTTON_EVENT[dvTP,212]
{
PUSH:
IF(Text == '13960017776')
{
SEND_COMMAND dvTP, 'PAGE-Error'
}
ELSE
{
SEND_COMMAND dvTP, 'PAGE-Main'
}
}
I was able to use one badge id to authenticate... now how to get multiple badges using a text file is the next step..
PROGRAM_NAME='Keypad Testing'
DEFINE_DEVICE
dvTP = 10001:1:0 //AMX Modero NXTCV10
dvMaster = 0:1:0 //NI700 Master Controller
DEFINE_VARIABLE
NON_VOLATILE CHAR Text
DEFINE_START
SEND_COMMAND dvTP, "'^TXT-1,3',ITOA(Text)"
DEFINE_EVENT
DATA_EVENT[dvTP]
{
ONLINE:
{
SEND_COMMAND dvTP, 'Page-Swipe'
}
STRING:
{
IF
(FIND_STRING(DATA.TEXT,'139600177',1))
SEND_COMMAND dvTP, 'Page-Main'
ELSE
SEND_COMMAND dvTP, 'Page-Swipe'
}
}
BUTTON_EVENT[dvTP,212]
{
PUSH:
{
SEND_COMMAND dvTP, '@PKP'
}
}
Please note that this code has been edited from a MUCH larger file that tests lots of different things. I know it compiles and I think it will work OK but I don't have any hardware to test it with at the moment so YMMV.
Kim:
My read_file function continually truncates the length of cSUBJECT with objects that I cannot see in Debug. For whatever reason, it thinks there is a comma or space in the CSV file. Can you tell what I'm doing wrong?
DEFINE_FUNCTION fnREAD_FILE_MTG (CHAR cFILENAME[]) { LOCAL_VAR SLONG slFILE_VAL slFILE_VAL = FILE_OPEN(cFILENAME,FILE_READ_ONLY) IF(slFILE_VAL < 0) { SELECT { ACTIVE(slFILE_VAL == -2): SEND_STRING 0, "'Invalid Path'" ACTIVE(slFILE_VAL == -3): SEND_STRING 0, "'Invalid Value'" ACTIVE(slFILE_VAL == -5): SEND_STRING 0, "'I/O Error'" ACTIVE(slFILE_VAL == -14):SEND_STRING 0, "'Max Files Open'" ACTIVE(slFILE_VAL == -15):SEND_STRING 0, "'Invalid File Format'" } } ELSE IF(slFILE_VAL > 0) { LOCAL_VAR SLONG slVAL LOCAL_VAR INTEGER i LOCAL_VAR CHAR cBUFF[120] FOR(i=1; i<=MAX_LENGTH_ARRAY(uMTG); i++) { slVAL = FILE_READ_LINE(slFILE_VAL,cBUFF,MAX_LENGTH_ARRAY(cBUFF)) uMTG[i].cHOST_NAME = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cHOST_NAME,LENGTH_ARRAY(uMTG[i].cHOST_NAME)-1) uMTG[i].cSTART_DATE = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cSTART_DATE,LENGTH_ARRAY(uMTG[i].cSTART_DATE)-1) uMTG[i].cSTART_HOUR = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cSTART_HOUR,LENGTH_ARRAY(uMTG[i].cSTART_HOUR)-1) uMTG[i].cSTART_MINUTE = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cSTART_MINUTE,LENGTH_ARRAY(uMTG[i].cSTART_MINUTE)-1) uMTG[i].cEND_HOUR = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cEND_HOUR,LENGTH_ARRAY(uMTG[i].cEND_HOUR)-1) uMTG[i].cEND_MINUTE = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cEND_MINUTE,LENGTH_ARRAY(uMTG[i].cEND_MINUTE)-1) uMTG[i].cSUBJECT = REMOVE_STRING(cBUFF, ',',1) IF(i > MAX_LENGTH_ARRAY(uMTG)) { BREAK; } } FILE_CLOSE(slFILE_VAL) } }One thing I see as a possibility from the code below is your cBUFF variable is only 120 characters. This will result in a max line length of 120. As your subject is the last column of that CSV format it will be the item that is truncated during the read line.
I've attached code for reference. I tried to solve the cBUFF issue by having it ignore commas or blank space, but I'd prefer not to. Any tips would be helpful. I changed the cBUFF length back to 2048, what should it be?
Thanks,
PROGRAM_NAME='Calendar Demo Rev 1' (***********************************************************) (* FILE CREATED ON: 01/16/2015 AT: 08:00:17 *) (***********************************************************) (* FILE_LAST_MODIFIED_ON: 02/03/2015 AT: 07:17:07 *) (***********************************************************) DEFINE_DEVICE dvMaster = 0:1:0 dvTP = 10001:1:0 dvTP_Locked = 10001:3:0 dvTP_Mtg = 10001:4:0 (***********************************************************) (* CONSTANT DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_CONSTANT MAX_USERS = 500 MAX_MEETINGS = 36 TL_FEEDBACK = 1 TL_FEEDBACK2 = 2 TL_FEEDBACK3 = 3 (***********************************************************) (* DATA TYPE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_TYPE STRUCTURE _sUSERS //Presets Structure { CHAR cID[15] CHAR cFIRST_NAME[25] CHAR cLAST_NAME[25] CHAR cEMAIL[50] } STRUCTURE _sMTG //Mtg Structure { CHAR cHOST_NAME[25] CHAR cSTART_DATE[25] CHAR cSTART_HOUR[4] CHAR cSTART_MINUTE[4] CHAR cEND_HOUR[4] CHAR cEND_MINUTE[4] CHAR cSUBJECT[50] } (***********************************************************) (* VARIABLE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_VARIABLE PERSISTENT _sUSERS uUSERS[MAX_USERS] PERSISTENT _sMTG uMTG[MAX_MEETINGS] VOLATILE CHAR cDATA[25] VOLATILE CHAR cBADGE[20] VOLATILE INTEGER nVALID_ENTRY VOLATILE INTEGER nDONE VOLATILE CHAR cHOST_NAME[25] VOLATILE CHAR cSTART_DATE[25] VOLATILE CHAR cSTART_HOUR[4] VOLATILE CHAR cSTART_MINUTE[4] VOLATILE CHAR cEND_HOUR[4] VOLATILE CHAR cEND_MINUTE[4] VOLATILE CHAR cSUBJECT[50] VOLATILE INTEGER nMINUTE VOLATILE INTEGER nHOUR VOLATILE INTEGER nMINUTE2 VOLATILE INTEGER nHOUR2 VOLATILE INTEGER nTIME NON_VOLATILE sINTEGER nCURRENT_HOUR NON_VOLATILE sINTEGER nCURRENT_MIN NON_VOLATILE sINTEGER nCURRENT_MEETING VOLATILE LONG nTIMER[] = {500} VOLATILE LONG nTIMER2[] = {5000} VOLATILE LONG nTIMER3[] = {10000} VOLATILE INTEGER nCLOSED NON_VOLATILE DEVCHAN dcMTGs[] = { {dvTP_Locked, 1}, {dvTP_Locked, 2}, {dvTP_Locked, 3}, {dvTP_Locked, 4}, {dvTP_Locked, 5}, {dvTP_Locked, 6}, {dvTP_Locked, 7}, {dvTP_Locked, 8}, {dvTP_Locked, 9}, {dvTP_Locked, 10}, {dvTP_Locked, 11}, {dvTP_Locked, 12}, {dvTP_Locked, 13}, {dvTP_Locked, 14}, {dvTP_Locked, 15}, {dvTP_Locked, 16}, {dvTP_Locked, 17}, {dvTP_Locked, 18}, {dvTP_Locked, 19}, {dvTP_Locked, 20}, {dvTP_Locked, 21}, {dvTP_Locked, 22}, {dvTP_Locked, 23}, {dvTP_Locked, 24}, {dvTP_Locked, 25}, {dvTP_Locked, 26}, {dvTP_Locked, 27}, {dvTP_Locked, 28}, {dvTP_Locked, 29}, {dvTP_Locked, 30}, {dvTP_Locked, 31}, {dvTP_Locked, 32}, {dvTP_Locked, 33}, {dvTP_Locked, 34}, {dvTP_Locked, 35}, {dvTP_Locked, 36} } (***********************************************************) (* LATCHING DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_LATCHING (***********************************************************) (* MUTUALLY EXCLUSIVE DEFINITIONS GO BELOW *) (***********************************************************) DEFINE_MUTUALLY_EXCLUSIVE (***********************************************************) (* SUBROUTINE/FUNCTION DEFINITIONS GO BELOW *) (***********************************************************) (* EXAMPLE: DEFINE_FUNCTION <RETURN_TYPE> <NAME> (<PARAMETERS>) *) (* EXAMPLE: DEFINE_CALL '<NAME>' (<PARAMETERS>) *) DEFINE_FUNCTION INTEGER fnCONVERT_REQUEST (INTEGER nSTART_HOUR, INTEGER nSTART_MINUTE, INTEGER nEND_HOUR, INTEGER nEND_MINUTE) { STACK_VAR INTEGER nDURATION STACK_VAR i STACK_VAR x IF(nSTART_HOUR == 1) { nSTART_HOUR = 13 } ELSE IF(nSTART_HOUR == 2) { nSTART_HOUR = 14 } ELSE IF(nSTART_HOUR == 3) { nSTART_HOUR = 15 } ELSE IF(nSTART_HOUR == 4) { nSTART_HOUR = 16 } IF(nEND_HOUR == 1) { nEND_HOUR = 13 } ELSE IF(nEND_HOUR == 2) { nEND_HOUR = 14 } ELSE IF(nEND_HOUR == 3) { nEND_HOUR = 15 } ELSE IF(nEND_HOUR == 4) { nEND_HOUR = 16 } ELSE IF(nEND_HOUR == 5) { nEND_HOUR = 17 } i = ((nEND_HOUR - nSTART_HOUR)*60) x = nEND_MINUTE - nSTART_MINUTE nDURATION = i + x RETURN nDURATION } DEFINE_FUNCTION INTEGER fnPROCESS_TIME (INTEGER nHOUR, INTEGER nMINUTE) { STACK_VAR INTEGER t IF(nHOUR > 12) { nHOUR = nHOUR - 12 } IF(nHOUR == 8 && nMINUTE < 15) { t = 1 } ELSE IF(nHOUR == 8 && nMINUTE >= 15 && nMINUTE < 30) { t = 2 } ELSE IF(nHOUR == 8 && nMINUTE >= 30 && nMINUTE < 45) { t = 3 } ELSE IF(nHOUR == 8 && nMINUTE >= 45) { t = 4 } ELSE IF(nHOUR == 9 && nMINUTE < 15) { t = 5 } ELSE IF(nHOUR == 9 && nMINUTE >= 15 && nMINUTE < 30) { t = 6 } ELSE IF(nHOUR == 9 && nMINUTE >= 30 && nMINUTE < 45) { t = 7 } ELSE IF(nHOUR == 9 && nMINUTE >= 45) { t = 8 } ELSE IF(nHOUR == 10 && nMINUTE < 15) { t = 9 } ELSE IF(nHOUR == 10 && nMINUTE >= 15 && nMINUTE < 30) { t = 10 } ELSE IF(nHOUR == 10 && nMINUTE >= 30 && nMINUTE < 45) { t = 11 } ELSE IF(nHOUR == 10 && nMINUTE >= 45) { t = 12 } ELSE IF(nHOUR == 11 && nMINUTE < 15) { t = 13 } ELSE IF(nHOUR == 11 && nMINUTE >= 15 && nMINUTE < 30) { t = 14 } ELSE IF(nHOUR == 11 && nMINUTE >= 30 && nMINUTE < 45) { t = 15 } ELSE IF(nHOUR == 11 && nMINUTE >= 45) { t = 16 } ELSE IF(nHOUR == 12 && nMINUTE < 15) { t = 17 } ELSE IF(nHOUR == 12 && nMINUTE >= 15 && nMINUTE < 30) { t = 18 } ELSE IF(nHOUR == 12 && nMINUTE >= 30 && nMINUTE < 45) { t = 19 } ELSE IF(nHOUR == 12 && nMINUTE >= 45) { t = 20 } ELSE IF(nHOUR == 1 && nMINUTE < 15) { t = 21 } ELSE IF(nHOUR == 1 && nMINUTE >= 15 && nMINUTE < 30) { t = 22 } ELSE IF(nHOUR == 1 && nMINUTE >= 30 && nMINUTE < 45) { t = 23 } ELSE IF(nHOUR == 1 && nMINUTE >= 45) { t = 24 } ELSE IF(nHOUR == 2 && nMINUTE < 15) { t = 25 } ELSE IF(nHOUR == 2 && nMINUTE >= 15 && nMINUTE < 30) { t = 26 } ELSE IF(nHOUR == 2 && nMINUTE >= 30 && nMINUTE < 45) { t = 27 } ELSE IF(nHOUR == 2 && nMINUTE >= 45) { t = 28 } ELSE IF(nHOUR == 3 && nMINUTE < 15) { t = 29 } ELSE IF(nHOUR == 3 && nMINUTE >= 15 && nMINUTE < 30) { t = 30 } ELSE IF(nHOUR == 3 && nMINUTE >= 30 && nMINUTE < 45) { t = 31 } ELSE IF(nHOUR == 3 && nMINUTE >= 45) { t = 32 } ELSE IF(nHOUR == 4 && nMINUTE < 15) { t = 33 } ELSE IF(nHOUR == 4 && nMINUTE >= 15 && nMINUTE < 30) { t = 34 } ELSE IF(nHOUR == 4 && nMINUTE >= 30 && nMINUTE < 45) { t = 35 } ELSE IF(nHOUR == 4 && nMINUTE >= 45) { t = 36 } RETURN t } DEFINE_FUNCTION INTEGER fnFILL_CALENDAR (INTEGER nHOUR, INTEGER nMIN) { STACK_VAR INTEGER x STACK_VAR INTEGER nINDEX FOR(x=1; x<=MAX_LENGTH_ARRAY(uMTG); x++) { IF(LENGTH_ARRAY(uMTG[x].cSUBJECT) > 0) { IF(uMTG[x].cSUBJECT == uMTG[x].cSUBJECT) { ON[dvTP_Locked, x] } } ELSE { OFF[dvTP_Locked, x] } } IF(nHOUR > 12) { nHOUR = nHOUR - 12 } nINDEX = fnPROCESS_TIME(nHOUR, nMIN) IF(LENGTH_ARRAY(uMTG[nINDEX].cSUBJECT) > 0) { SEND_COMMAND dvTP, "'^TXT-1,0,',uMTG[nINDEX].cSUBJECT" RETURN TRUE } ELSE { SEND_COMMAND dvTP, "'^TXT-1,0,Vacant'" RETURN FALSE } } DEFINE_FUNCTION INTEGER fnPROCESS_REQUEST (INTEGER nINDEX, INTEGER nNUM_MTGs) { STACK_VAR INTEGER i IF(LENGTH_ARRAY(uMTG[nINDEX].cSUBJECT) < 1) { FOR(i=1; i<=nNUM_MTGs; i++) { IF(LENGTH_ARRAY(uMTG[nINDEX].cSUBJECT) < 1) { RETURN TRUE } ELSE IF(LENGTH_ARRAY(uMTG[nINDEX].cSUBJECT) > 1) { RETURN FALSE BREAK; } nINDEX++ } } } DEFINE_FUNCTION fnRead_BadgeID (CHAR cFILENAME[]) { LOCAL_VAR SLONG slFILE_VAL slFILE_VAL = FILE_OPEN(cFILENAME,FILE_READ_ONLY) IF(slFILE_VAL < 0) { SELECT { ACTIVE(slFILE_VAL == -2): SEND_STRING 0, "'Invalid Path'" ACTIVE(slFILE_VAL == -3): SEND_STRING 0, "'Invalid Value'" ACTIVE(slFILE_VAL == -5): SEND_STRING 0, "'I/O Error'" ACTIVE(slFILE_VAL == -14):SEND_STRING 0, "'Max Files Open'" ACTIVE(slFILE_VAL == -15):SEND_STRING 0, "'Invalid File Format'" } } ELSE IF(slFILE_VAL > 0) { LOCAL_VAR SLONG slVAL LOCAL_VAR INTEGER i LOCAL_VAR CHAR cBUFF[2048] FOR(i=1; i<=MAX_LENGTH_ARRAY(uUSERS); i++) { slVAL = FILE_READ_LINE(slFILE_VAL,cBUFF,MAX_LENGTH_ARRAY(cBUFF)) uUSERS[i].cID = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uUSERS[i].cID,LENGTH_ARRAY(uUSERS[i].cID)-1) uUSERS[i].cFIRST_NAME = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uUSERS[i].cFIRST_NAME,LENGTH_ARRAY(uUSERS[i].cFIRST_NAME)-1) uUSERS[i].cLAST_NAME = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uUSERS[i].cLAST_NAME,LENGTH_ARRAY(uUSERS[i].cLAST_NAME)-1) uUSERS[i].cEMAIL = cBUFF } FILE_CLOSE(slFILE_VAL) } } DEFINE_FUNCTION fnREAD_FILE_MTG (CHAR cFILENAME[]) { LOCAL_VAR SLONG slFILE_VAL slFILE_VAL = FILE_OPEN(cFILENAME,FILE_READ_ONLY) IF(slFILE_VAL < 0) { SELECT { ACTIVE(slFILE_VAL == -2): SEND_STRING 0, "'Invalid Path'" ACTIVE(slFILE_VAL == -3): SEND_STRING 0, "'Invalid Value'" ACTIVE(slFILE_VAL == -5): SEND_STRING 0, "'I/O Error'" ACTIVE(slFILE_VAL == -14):SEND_STRING 0, "'Max Files Open'" ACTIVE(slFILE_VAL == -15):SEND_STRING 0, "'Invalid File Format'" } } ELSE IF(slFILE_VAL > 0) { LOCAL_VAR SLONG slVAL LOCAL_VAR INTEGER i LOCAL_VAR CHAR cBUFF[2048] FOR(i=1; i<=MAX_LENGTH_ARRAY(uMTG); i++) { slVAL = FILE_READ_LINE(slFILE_VAL,cBUFF,MAX_LENGTH_ARRAY(cBUFF)) uMTG[i].cHOST_NAME = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cHOST_NAME,LENGTH_ARRAY(uMTG[i].cHOST_NAME)-1) uMTG[i].cSTART_DATE = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cSTART_DATE,LENGTH_ARRAY(uMTG[i].cSTART_DATE)-1) uMTG[i].cSTART_HOUR = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cSTART_HOUR,LENGTH_ARRAY(uMTG[i].cSTART_HOUR)-1) uMTG[i].cSTART_MINUTE = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cSTART_MINUTE,LENGTH_ARRAY(uMTG[i].cSTART_MINUTE)-1) uMTG[i].cEND_HOUR = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cEND_HOUR,LENGTH_ARRAY(uMTG[i].cEND_HOUR)-1) uMTG[i].cEND_MINUTE = REMOVE_STRING(cBUFF,',',1) SET_LENGTH_ARRAY(uMTG[i].cEND_MINUTE,LENGTH_ARRAY(uMTG[i].cEND_MINUTE)-1) uMTG[i].cSUBJECT = cBUFF IF((LENGTH_ARRAY(cBUFF) > 0) && LEFT_STRING(cBUFF, 1) == $2C || LEFT_STRING(cBUFF, 1) == $00) { SET_LENGTH_ARRAY(uMTG[i].cHOST_NAME, 0) SET_LENGTH_ARRAY(uMTG[i].cSTART_DATE, 0) SET_LENGTH_ARRAY(uMTG[i].cSTART_HOUR, 0) SET_LENGTH_ARRAY(uMTG[i].cSTART_MINUTE, 0) SET_LENGTH_ARRAY(uMTG[i].cEND_HOUR, 0) SET_LENGTH_ARRAY(uMTG[i].cEND_MINUTE, 0) SET_LENGTH_ARRAY(uMTG[i].cSUBJECT, 0) } } FILE_CLOSE(slFILE_VAL) } } DEFINE_FUNCTION fnWRITE_FILE_MTG(CHAR cFILENAME[]) { LOCAL_VAR CHAR cBUFF[120] LOCAL_VAR SLONG slFILE_VAR LOCAL_VAR INTEGER i LOCAL_VAR SLONG slRESULT slFILE_VAR = FILE_OPEN(cFILENAME, FILE_RW_NEW) IF(slFILE_VAR > 0) { FOR(i=1; i<=MAX_LENGTH_ARRAY(uMTG); i++) { cBUFF = "uMTG[i].cHOST_NAME,',',uMTG[i].cSTART_DATE,',',uMTG[i].cSTART_HOUR,',',uMTG[i].cSTART_MINUTE,',',uMTG[i].cEND_HOUR,',',uMTG[i].cEND_MINUTE,',',uMTG[i].cSUBJECT" slRESULT = FILE_WRITE_LINE(slFILE_VAR,cBUFF,LENGTH_ARRAY(cBUFF)) SEND_STRING 0, "slRESULT" } FILE_CLOSE(slFILE_VAR) SEND_STRING 0,"'GOOD FILE CLOSED ',ITOA(FILE_CLOSE(slFILE_VAR))" } ELSE { SEND_STRING 0,"'BAD FILE OPEN ',ITOA(FILE_CLOSE(slFILE_VAR))" } } (***********************************************************) (* STARTUP CODE GOES BELOW *) (***********************************************************) DEFINE_START TIMELINE_CREATE(TL_FEEDBACK, nTIMER, 1, TIMELINE_ABSOLUTE, TIMELINE_REPEAT) //Half Second TIMELINE_CREATE(TL_FEEDBACK2, nTIMER2, 1, TIMELINE_ABSOLUTE, TIMELINE_REPEAT) // 5 Seconds TIMELINE_CREATE(TL_FEEDBACK3, nTIMER3, 1, TIMELINE_ABSOLUTE, TIMELINE_REPEAT) //60 Seconds (***********************************************************) (* THE EVENTS GO BELOW *) (***********************************************************) DEFINE_EVENT DATA_EVENT[dvMaster] //Master Data Event { ONLINE: { SEND_COMMAND dvTP, "'ADBEEP'" //When online, BEEP! } } DATA_EVENT[dvTP] { STRING: { STACK_VAR INTEGER x SEND_STRING 0, "'FROM TP: ', DATA.TEXT" SELECT { ACTIVE(FIND_STRING(DATA.TEXT, 'Button 16-', 1)): { REMOVE_STRING(DATA.TEXT, 'Button 16-', 1) cBADGE = DATA.TEXT IF(LENGTH_ARRAY(cBADGE == 11)) { fnRead_BadgeID('Badge_IDs.csv') FOR(x=1; x<=MAX_LENGTH_ARRAY(uUSERS); x++) { IF(cBADGE == uUSERS[x].cID) { SEND_COMMAND dvTP, "'@PPN-New Mtg'" SEND_COMMAND dvTP, "'@PPK-Authorization'" SEND_COMMAND dvTP, "'@PPK-Invalid Entry'" SEND_COMMAND dvTP_Mtg, "'^TXT-1,0,',uUSERS[x].cFIRST_NAME,',',uUSERS[x].cLAST_NAME" ON[nVALID_ENTRY] cHOST_NAME = "uUSERS[x].cFIRST_NAME,' ',uUSERS[x].cLAST_NAME" SEND_COMMAND dvTP_Mtg, "'^TXT-2,0,',DATE" BREAK; } ELSE { SEND_COMMAND dvTP, "'@PPN-Invalid Entry'" SEND_COMMAND dvTP, "'@PPK-Authorization'" OFF[nVALID_ENTRY] WAIT 40 { SEND_COMMAND dvTP, "'@PPK-Invalid Entry'" SEND_COMMAND dvTP, "'PAGE-Locked'" } } } } } ACTIVE(FIND_STRING(DATA.TEXT, '@PPF-Authorization;Locked', 1)): { SEND_COMMAND dvTP_Mtg, "'^TXT-3,0,'" SEND_COMMAND dvTP_Mtg, "'^TXT-4,0,'" SEND_COMMAND dvTP_Mtg, "'^TXT-5,0,'" SEND_COMMAND dvTP_Mtg, "'^TXT-6,0,'" SEND_COMMAND dvTP_Mtg, "'^TXT-11,0,'" SEND_COMMAND dvTP_Mtg, "'^TXT-12,0,'" SEND_COMMAND dvTP_Mtg, "'^TXT-13,0,'" } ACTIVE(FIND_STRING(DATA.TEXT,'KEYB-',1)): { REMOVE_STRING(DATA.TEXT,'KEYB-',1) cDATA = DATA.TEXT } ACTIVE(FIND_STRING(DATA.TEXT,'KEYP-',1)): { REMOVE_STRING(DATA.TEXT,'KEYP-',1) IF(nTIME == 1) { nHOUR = ATOI(DATA.TEXT) } ELSE IF(nTIME == 2) { nMINUTE = ATOI(DATA.TEXT) } ELSE IF(nTIME == 3) { nHOUR2 = ATOI(DATA.TEXT) } ELSE IF(nTIME == 4) { nMINUTE2 = ATOI(DATA.TEXT) } } } PULSE[nDONE] } } BUTTON_EVENT[dvTP_Mtg, 3] { PUSH: { TO[BUTTON.INPUT] nTIME = 1; } RELEASE: { WAIT_UNTIL(nDONE) { cSTART_HOUR = ITOA(nHOUR) SEND_COMMAND dvTP_Mtg, "'^TXT-3,0,',cSTART_HOUR" IF(nHOUR >= 8 && nHOUR < 12) { SEND_COMMAND dvTP_Mtg, "'^TXT-5,0,AM'" } ELSE { SEND_COMMAND dvTP_Mtg, "'^TXT-5,0,PM'" } } } } BUTTON_EVENT[dvTP_Mtg, 4] { PUSH: { nTIME = 2; } RELEASE: { WAIT_UNTIL(nDONE) { cSTART_MINUTE = ITOA(nMINUTE) IF(nMINUTE == 0) { cSTART_MINUTE = "'00'" } SEND_COMMAND dvTP_Mtg, "'^TXT-4,0,',cSTART_MINUTE" } } } BUTTON_EVENT[dvTP_Mtg, 11] { PUSH: { nTIME = 3; } RELEASE: { WAIT_UNTIL(nDONE) { cEND_HOUR = ITOA(nHOUR2) SEND_COMMAND dvTP_Mtg, "'^TXT-11,0,',cEND_HOUR" IF(nHOUR2 >= 8 && nHOUR2 < 12) { SEND_COMMAND dvTP_Mtg, "'^TXT-13,0,AM'" } ELSE { SEND_COMMAND dvTP_Mtg, "'^TXT-13,0,PM'" } } } } BUTTON_EVENT[dvTP_Mtg, 12] { PUSH: { nTIME = 4; } RELEASE: { WAIT_UNTIL(nDONE) { cEND_MINUTE = ITOA(nMINUTE2) IF(nMINUTE2 == 0) { cEND_MINUTE = "'00'" } SEND_COMMAND dvTP_Mtg, "'^TXT-12,0,',cEND_MINUTE" } } } BUTTON_EVENT[dvTP_Mtg, 6] { PUSH: { } RELEASE: { WAIT_UNTIL(nDONE) { cSUBJECT = cDATA SEND_COMMAND dvTP_Mtg, "'^TXT-6,0,',cSUBJECT" } } } BUTTON_EVENT[dvTP_Mtg, 10] //reserve a new meeting { PUSH: { LOCAL_VAR INTEGER x LOCAL_VAR INTEGER INDEX LOCAL_VAR INTEGER nDURATION LOCAL_VAR INTEGER nNUM_MTGS LOCAL_VAR INTEGER ACCESS INDEX = fnPROCESS_TIME(nHOUR, nMINUTE) nDURATION = fnCONVERT_REQUEST(nHOUR, nMINUTE, nHOUR2, nMINUTE2) nNUM_MTGS = (nDURATION/15) ACCESS = fnPROCESS_REQUEST(INDEX, nNUM_MTGS) IF(LENGTH_ARRAY(cSUBJECT) > 0) { OFF[dvTP_Mtg, 16] IF(ACCESS == 1) { FOR(x=1; x<=nNUM_MTGS; x++) { uMTG[INDEX].cHOST_NAME = cHOST_NAME uMTG[INDEX].cSTART_DATE = DATE uMTG[INDEX].cSTART_HOUR = cSTART_HOUR uMTG[INDEX].cSTART_MINUTE = cSTART_MINUTE uMTG[INDEX].cEND_HOUR = cEND_HOUR uMTG[INDEX].cEND_MINUTE = cEND_MINUTE uMTG[INDEX].cSUBJECT = cSUBJECT INDEX++ IF(x > nNUM_MTGS) { BREAK; } } fnWRITE_FILE_MTG('New_Mtg.csv') SEND_COMMAND dvTP, "'@PPX-New Mtg'" } ELSE IF(ACCESS == 0) { SEND_COMMAND dvTP, "'@PPN-Error'" } } ELSE { ON[dvTP_Mtg, 16] } } } BUTTON_EVENT[dvTP, 4] //Cancel the current meeting { PUSH: { LOCAL_VAR INTEGER i LOCAL_VAR INTEGER nDURATION2 LOCAL_VAR INTEGER nNUM_MTGs2 LOCAL_VAR INTEGER nLINE nLINE = fnPROCESS_TIME(nCURRENT_HOUR, nCURRENT_MIN) nDURATION2 = fnCONVERT_REQUEST(ATOI(uMTG[nLINE].cSTART_HOUR), ATOI(uMTG[nLINE].cSTART_MINUTE), ATOI(uMTG[nLINE].cEND_HOUR), ATOI(uMTG[nLINE].cEND_MINUTE)) nNUM_MTGs2 = (nDURATION2/15) FOR(i=1; i<=nNUM_MTGS2; i++) { SET_LENGTH_ARRAY(uMTG[nLINE].cHOST_NAME, 0) SET_LENGTH_ARRAY(uMTG[nLINE].cSTART_DATE, 0) SET_LENGTH_ARRAY(uMTG[nLINE].cSTART_HOUR, 0) SET_LENGTH_ARRAY(uMTG[nLINE].cSTART_MINUTE, 0) SET_LENGTH_ARRAY(uMTG[nLINE].cEND_HOUR, 0) SET_LENGTH_ARRAY(uMTG[nLINE].cEND_MINUTE, 0) SET_LENGTH_ARRAY(uMTG[nLINE].cSUBJECT, 0) nLINE++ IF(i > nNUM_MTGs2) { BREAK; } } fnWRITE_FILE_MTG('New_Mtg.csv') } } BUTTON_EVENT[dcMTGs] { PUSH: { STACK_VAR INTEGER BIC BIC = BUTTON.INPUT.CHANNEL ON[dvTP, 6] ON[dvTP, 7] IF(LENGTH_ARRAY(uMTG[BIC].cSUBJECT) > 0) { SEND_COMMAND dvTP, "'^TXT-2,0,',uMTG[BIC].cSUBJECT,' ',uMTG[BIC].cSTART_HOUR,':',uMTG[BIC].cSTART_MINUTE,' - ',uMTG[BIC].cEND_HOUR,':',uMTG[BIC].cEND_MINUTE" } ELSE { SEND_COMMAND dvTP, "'^TXT-2,0,Meeting room vacant'" } WAIT 50 { OFF[dvTP, 6] OFF[dvTP, 7] } } } BUTTON_EVENT[dvTP, 3] { PUSH: { STACK_VAR INTEGER y y = fnPROCESS_TIME(nCURRENT_HOUR, nCURRENT_MIN) IF(LENGTH_ARRAY(uMTG[y].cSUBJECT) > 0) { SEND_COMMAND dvTP, "'^TXT-3,0,',uMTG[y].cSUBJECT" } ELSE { SEND_COMMAND dvTP, "'^TXT-3,0,There is no meeting to cancel...'" } } } TIMELINE_EVENT[TL_FEEDBACK] { nCURRENT_HOUR = TIME_TO_HOUR(TIME) nCURRENT_MIN = TIME_TO_MINUTE(TIME) } TIMELINE_EVENT[TL_FEEDBACK2] { nCURRENT_MEETING = fnFILL_CALENDAR(nCURRENT_HOUR, nCURRENT_MIN) } TIMELINE_EVENT[TL_FEEDBACK3] { fnREAD_FILE_MTG('New_Mtg.csv') } (***********************************************************) (* THE ACTUAL PROGRAM GOES BELOW *) (***********************************************************) DEFINE_PROGRAM [dvTP, 1] = (nCURRENT_MEETING == 1) (***********************************************************) (* END OF PROGRAM *) (* DO NOT PUT ANY CODE BELOW THIS COMMENT *) (***********************************************************)Unless you have trailing comma's you may have more luck replacing: with
Alternatively, the explode(..) function I pointed to earlier in the thread may be able to neaten things up a bit.
Kim,
thank you... that is exactly what is happening. I was able to write my own function to clean up the commas and blank spaces before I saw the explode function!
sorry for the delay:
DEFINE_TYPE STRUCTURE _sMTG //Mtg Structure { CHAR cHOST_NAME[25] CHAR cSTART_DATE[25] CHAR cSTART_HOUR[4] CHAR cSTART_MINUTE[4] CHAR cEND_HOUR[4] CHAR cEND_MINUTE[4] CHAR cSUBJECT[50] } DEFINE_VARIABLE VOLATILE _sMTG uMTG[MAX_MEETINGS] DEFINE_CONSTANT MAX_MEETINGS = 36