Managing Feedback - Lighting System
Thankfully, AMX has just released the updated version of the Vantage Infusion module. This module now allows for Feedback based on button LED state. The command string will come in as (KEYPADSYSTEMBUTTONSTATUS-<address>,<status>) So for button with VID 233, it would report as KEYPADSYSTEMBUTTONSTATUS-233,ON if the button was on. Very straightforward. I have implemented the original module numerous times and it works fine. Now, my only question is with regards to the feedback. What would be the easiest way to manage the feedback. If create a new port on my TP for the lighting system, and then assign the button channels and addresses to match the VID #'s, will that automatically pass it through? If not, do I need to monitor a data event and do a find string for KEYPADSYSTEMBUTTONSTATUS? How would you guru's make this work? Keep in mind, that I'm only through Programmer I, so passing things into arrays, structures is still beyond me unless I can get some sample code. With the vantage Qlink System, I did a data event and based on data.text I would send a an on/off state to the button channel.
example:
This was easy with a small system, but I don't want to have a multitude of If statements in a data_event to do this on a larger system.
Thanks for any help?
example:
data_event[vVANTAGE]
{
string:
{
nVANTAGE_FEEDBACK = DATA.TEXT
IF (data.text == 'K:L:[1:68]:5:1')//liv room
{
ON [dvTP_VANTAGE, 101]
}
IF (data.text == 'K:L:[1:68]:5:0')
{
OFF [dvTP_VANTAGE, 101]
}
IF (data.text == 'K:L:[1:67]:5:1')//kitchen
{
ON [dvTP_VANTAGE, 102]
}
IF (data.text == 'K:L:[1:67]:5:0')
{
OFF [dvTP_VANTAGE, 102]
}
if (data.text == 'K:L:[1:68]:2:1')//kitchen dim
{
ON [dvTP_VANTAGE, 103]
}
IF (data.text == 'K:L:[1:68]:2:0')
{
OFF [dvTP_VANTAGE, 103]
}
IF (data.text == 'K:L:[1:65]:3:1')//master bedroom
{
ON [dvTP_VANTAGE, 104]
}
IF (data.text == 'K:L:[1:65]:3:0')
{
OFF [dvTP_VANTAGE, 104]
}
IF (data.text == 'K:L:[1:66]:6:1')//master bedroom DIM
{
ON [dvTP_VANTAGE, 105]
}
IF (data.text == 'K:L:[1:66]:6:0')
{
OFF [dvTP_VANTAGE, 105]
}
IF (data.text == 'K:L:[1:68]:6:1')//OFFICE NURSERY
{
ON [dvTP_VANTAGE, 106]
}
IF (data.text == 'K:L:[1:68]:6:0')
{
OFF [dvTP_VANTAGE, 106]
}
IF (data.text == 'K:L:[1:67]:2:1')//OFFICE NURSERY DIM
{
ON [dvTP_VANTAGE, 107]
}
IF (data.text == 'K:L:[1:67]:2:0')
{
OFF [dvTP_VANTAGE, 107]
}
IF (data.text == 'K:L:[1:67]:3:1')//OFFICE NURSERY LAMP
{
ON [dvTP_VANTAGE, 108]
}
IF (data.text == 'K:L:[1:67]:3:0')
{
OFF [dvTP_VANTAGE, 108]
}
IF (data.text == 'K:L:[1:68]:3:1')//CHINA HUTCH
{
ON [dvTP_VANTAGE, 109]
}
IF (data.text == 'K:L:[1:68]:3:0')
{
OFF [dvTP_VANTAGE, 109]
}
IF (data.text == 'K:L:[1:66]:5:1')//GARAGE
{
ON [dvTP_VANTAGE, 110]
}
IF (data.text == 'K:L:[1:66]:5:0')
{
OFF [dvTP_VANTAGE, 110]
}
IF (data.text == 'K:L:[1:65]:7:1')//GOODBYE
{
ON [dvTP_VANTAGE, 112]
}
IF (data.text == 'K:L:[1:65]:7:0')
{
OFF [dvTP_VANTAGE, 112]
}
}
}
This was easy with a small system, but I don't want to have a multitude of If statements in a data_event to do this on a larger system.
Thanks for any help?
0
Comments
define_type STRUCTURE _sLightLink{ integer nID integer nButton } define_variable integer nLightFB[nMaxID][nMaxButtons] _sLightLink uLightLink[nMaxLightButtons] define_function fnUpdateLightFeedback(){ stack_var integer x; for(x = nMaxLightButtons;x;x--){ [dvTP_Vantage,100+x] = nLightFB[uLightLink[x].nID][uLightLink[x].nButton]; } } define_start uLightLink[1].nID = 68; uLightLink[1].nButton = 5; uLightLink[2].nID = 67; uLightLink[2].nButton = 5; uLightLink[3].nID = 68; uLightLink[3].nButton = 2; uLightLink[4].nID = 65; uLightLink[4].nButton = 3; uLightLink[5].nID = 66; uLightLink[5].nButton = 6; //Add the rest of them define_event data_event[vVANTAGE]{ string:{ nVANTAGE_FEEDBACK = DATA.TEXT; stack_var integer nID; stack_var integer nButton; IF (find_string(data.text, 'K:L:[1:',1)){ remove_string(data.text, 'K:L:[1:',1); nId = atoi(data.text); remove_string(data.text, ']:',1); nButton = atoi(data.text); nLightFB[nID][nButton] = atoi(data.text); wait 10 fnUpdateLightFeedback(); } } }Hope this helps,
Jeff
He could of course just have an array of the maximum lighting channel numbers defined even if he doesn't use them all (i.e. nLIGHTING_BTNS[] = {101 - 201} and still approach it mathematically (which I would actually probably do), this way if the client decides to add more lights, there's no coding that needs to be changed, but just a TP change.
I'm starting to do this more and more (define much more than needed) in the event of adding another cable box, DVD, iPod, etc. to choose from and it's worked nicely so far. Many ways to skin a cat.
data_event[vVantage] { string: { if (find_string(data.text,'K:L:[1:',1)) { trash = remove_string(data.text,'K:L:[1:',1) keypad = atoI(remove_string(data.text,':',1)) buttonpressed = atoI(remove_string(data.text,':',1)) VKeypad[keypad][buttonpressed] = itoa(data.text) } [dvVantage,101] = VKeypad[68][5] [dvVantage,102] = VKeypad[67][5] [dvVantage,103] = VKeypad[68][2] [dvVantage,104] = VKeypad[65][3] [dvVantage,105] = VKeypad[66][6] [dvVantage,106] = VKeypad[68][6] [dvVantage,107] = VKeypad[67][2] [dvVantage,108] = VKeypad[67][3] [dvVantage,109] = VKeypad[68][3] [dvVantage,110] = VKeypad[66][5] [dvVantage,112] = VKeypad[65][7] } }data_event[vVantage] { string: { if (find_string(data.text,'KEYPADSYSTEMBUTTONSTATUS-',1)) { trash = remove_string(data.text,'KEYPADSYSTEMBUTTONSTATUS-',1)//IN THE EXAMPLE I MENTION IN THE ORIGINAL POST, I SHOULD ONLY HAVE 233,ON NOW VKeypad = (data.text) } [dvVantage,101] = VKeypad[233,ON] [dvVantage,102] = VKeypad[234,ON] [dvVantage,103] = VKeypad[235,ON] [dvVantage,104] = VKeypad[236,ON] [dvVantage,105] = VKeypad[237,ON] [dvVantage,106] = VKeypad[238,ON] [dvVantage,107] = VKeypad[239,ON] [dvVantage,108] = VKeypad[240,ON] } }If so, when the button is pushed off and the code comes through as saying 233,OFF, will it automatically change the sate of the button, or do I need to do If statements setting the channel on if I get an on response and off if I get an off response? This is ultimately the step I would like to condense in code instead of having two if commands for every button.
integer VKeypad[500] data_event[vVantage] { string: { if (find_string(data.text,'KEYPADSYSTEMBUTTONSTATUS-',1)) { trash = remove_string(data.text,'KEYPADSYSTEMBUTTONSTATUS-',1)//IN THE EXAMPLE I MENTION IN THE ORIGINAL POST, I SHOULD ONLY HAVE 233,ON NOW VKeypad[atoi(data.text)] = find_string(data.text,'ON',1) } [dvVantage,101] = VKeypad[233] [dvVantage,102] = VKeypad[234] [dvVantage,103] = VKeypad[235] [dvVantage,104] = VKeypad[236] [dvVantage,105] = VKeypad[237] [dvVantage,106] = VKeypad[238] [dvVantage,107] = VKeypad[239] [dvVantage,108] = VKeypad[240] } }This might work better...
Dumb question, but will this place the ON, prior to the 233? If so, will that cause any problems?
Thanks.
This was tremendously helpful. Thank you!
I think I got carried away with the example it probably wouldn't work with obvious modifcation for real vantage strings but it show another way to skin the can.
PROGRAM_NAME='TEST' DEFINE_DEVICE dvVantage = 0:5:0 ; dvTP1_Vantage = 10001:1:0 ; DEFINE_CONSTANT NUM_PROCESSORS = 1 ; NUM_LINKS_PER_PROC = 2 ; NUM_KEYPADS_PER_LINK = 32 NUM_BTNS_PER_KEYPAD = 8 ; LEN_BTNS_NAMES = 22 ; LEN_BUFFER = 2048 ; //size as needed NUM_PARAMS = 5 ; LEN_PARAMS = 4 ; STR_LF = $0A ; DEFINE_CONSTANT //LINK 1 KEYPAD BUTTON NAME VOLATILE CHAR LINK_1_BTN_NAMES[NUM_KEYPADS_PER_LINK][NUM_BTNS_PER_KEYPAD][LEN_BTNS_NAMES] = { {//keypad 1 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } , {//keypad 2 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } , {//keypad 3 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } , {//keypad 4 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } , {//keypad 5 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } , {//keypad 3 (*1 *)'KP6 Btn1', (*2 *)'KP6 Btn2', (*3 *)'KP6 Btn3', (*4 *)'KP6 Btn4', (*5 *)'KP6 Btn5', (*6 *)'KP6 Btn6', (*7 *)'KP6 Btn7', (*8 *)'KP6 Btn8' } , {//keypad 7 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } , {//keypad 8 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } , {//keypad 9 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } , {//keypad 10 (*1 *)'KP Btn1', (*2 *)'KP Btn2', (*3 *)'KP Btn3', (*4 *)'KP Btn4', (*5 *)'KP Btn5', (*6 *)'KP Btn6', (*7 *)'KP Btn7', (*8 *)'KP Btn8' } //continue } DEFINE_CONSTANT //LINK 1 KEYPAD KP BTNS TO TP BTN/CHNLS VOLATILE INTEGER LINK_1_TP_CHNLS[NUM_KEYPADS_PER_LINK][NUM_BTNS_PER_KEYPAD] = {//these are the TP button assigned for feedback of the Vantage KP buttons {//keypad 1 (*1 *) 16, (*2 *) 4, (*3 *) 66, (*4 *) 21, (*5 *) 75, (*6 *) 9, (*7 *) 45, (*8 *) 16 } , {//keypad 2 (*1 *) 11, (*2 *) 22, (*3 *) 34, (*4 *) 24, (*5 *) 58, (*6 *) 36, (*7 *) 71, (*8 *) 18 } , {//keypad 3 (*1 *) 10, (*2 *) 22, (*3 *) 30, (*4 *) 40, (*5 *) 50, (*6 *) 60, (*7 *) 70, (*8 *) 80 } , {//keypad 4 (*1 *) 11, (*2 *) 12, (*3 *) 13, (*4 *) 14, (*5 *) 15, (*6 *) 16, (*7 *) 17, (*8 *) 18 } , {//keypad 5 (*1 *) 21, (*2 *) 22, (*3 *) 23, (*4 *) 24, (*5 *) 25, (*6 *) 26, (*7 *) 27, (*8 *) 28 } , {//keypad 3 (*1 *) 1, (*2 *) 2, (*3 *) 3, (*4 *) 4, (*5 *) 5, (*6 *) 6, (*7 *) 7, (*8 *) 8 } , {//keypad 7 (*1 *) 1, (*2 *) 2, (*3 *) 3, (*4 *) 4, (*5 *) 5, (*6 *) 6, (*7 *) 7, (*8 *) 8 } , {//keypad 8 (*1 *) 1, (*2 *) 2, (*3 *) 3, (*4 *) 4, (*5 *) 5, (*6 *) 6, (*7 *) 7, (*8 *) 8 } , {//keypad 9 (*1 *) 1, (*2 *) 2, (*3 *) 3, (*4 *) 4, (*5 *) 5, (*6 *) 6, (*7 *) 7, (*8 *) 8 } , {//keypad 10 (*1 *) 1, (*2 *) 2, (*3 *) 3, (*4 *) 4, (*5 *) 5, (*6 *) 6, (*7 *) 7, (*8 *) 8 } //continue } DEFINE_TYPE //_Keypads STRUCTURE _Keypads { INTEGER nTP_Btn[NUM_BTNS_PER_KEYPAD] ; INTEGER nBtn_State[NUM_BTNS_PER_KEYPAD] ; CHAR cBtn_Name[NUM_BTNS_PER_KEYPAD][LEN_BTNS_NAMES] ; } DEFINE_TYPE //_Links STRUCTURE _Links { _Keypads sKP[NUM_KEYPADS_PER_LINK] } DEFINE_TYPE //_Porcessors STRUCTURE _Porcessors { _Links sLink[NUM_LINKS_PER_PROC] } DEFINE_TYPE //_Params STRUCTURE _Params { CHAR cParam[NUM_PARAMS][LEN_PARAMS] ; } DEFINE_VARIABLE //STRUCTURE VOLATILE _Porcessors sVantage[NUM_PROCESSORS] ; VOLATILE INTEGER nVantage_DeBug = 1 ; #WARN 'VANTAGE DEBUG ON' VOLATILE INTEGER nUpDateAll_Test = 0 ; VOLATILE INTEGER nInit_Structure_Test = 0 ; VOLATILE INTEGER nLoad_Names_Chnls_Test = 0 ; DEFINE_FUNCTION fnDevMod_DeBug(CHAR iStr[]) { if(nVantage_DeBug) { STACK_VAR CHAR cCopyStr[1024] ; STACK_VAR INTEGER nLineCount ; cCopyStr = iStr ; nLineCount ++ ; WHILE(length_string(cCopyStr) > 100) { SEND_STRING 0,"'VANTAGE MOD- DEBUG (',itoa(nLineCount),'): ',get_buffer_string(cCopyStr,80)" ; nLineCount ++ } if(length_string(cCopyStr)) { SEND_STRING 0,"'VANTAGE MOD- DEBUG (',itoa(nLineCount),'): ',cCopyStr" ; } } RETURN ; } DEFINE_FUNCTION fnParse_RXBuffer(CHAR iStr[]) { STACK_VAR _Params nData ; STACK_VAR INTEGER nFBS ; STACK_VAR INTEGER nErr ; nFBS = find_string(iStr,"'['",1) ; if(nFBS) { nData.cParam[1] = GET_BUFFER_STRING(iStr,nFBS-1) ; GET_BUFFER_CHAR(iStr) ; nFBS = find_string(iStr,"':'",1) ; if(nFBS) { nData.cParam[2] = GET_BUFFER_STRING(iStr,nFBS-1) ; GET_BUFFER_CHAR(iStr) ; nFBS = find_string(iStr,"']'",1) ; if(nFBS) { nData.cParam[3] = GET_BUFFER_STRING(iStr,nFBS-1) ; GET_BUFFER_CHAR(iStr) ; nFBS = find_string(iStr,"':'",1) ; if(nFBS) { nData.cParam[4] = GET_BUFFER_STRING(iStr,nFBS-1) ; GET_BUFFER_CHAR(iStr) ; nFBS = find_string(iStr,"STR_LF",1) ; if(nFBS) { nData.cParam[5] = GET_BUFFER_STRING(iStr,nFBS-1) ; GET_BUFFER_CHAR(iStr) ; } else { nErr = 1 ; } } else { nErr = 1 ; } } else { nErr = 1 ; } } else { nErr = 1 ; } } else { nErr = 1 ; } if(nErr) { fnDevMod_DeBug("'fnParse_RXBuffer: Error proccessing return, dumping contents :DEBUG <',ITOA(__LINE__),'>'") ; RETURN ; } fnFB_ProcessData(nData) ; } DEFINE_FUNCTION fnFB_ProcessData(_Params iData) //load structure and handle feedback { SELECT { ACTIVE(iData.cParam[1] == 'K:L:'): { STACK_VAR INTEGER nTP_Btn ; sVantage[1].sLink[atoi(iData.cParam[2])].sKP[atoi(iData.cParam[3])].nBtn_State[atoi(iData.cParam[4])] = atoi(iData.cParam[5]) nTP_Btn = sVantage[1].sLink[atoi(iData.cParam[2])].sKP[atoi(iData.cParam[3])].nTP_Btn[atoi(iData.cParam[4])] ; fnFB_Update_OneBtn(nTP_Btn,atoi(iData.cParam[5])) ; } ACTIVE(iData.cParam[1] == 'Something Else'): { //add as needed for dimmer levels etc. } ACTIVE(TRUE): { fnDevMod_DeBug("'fnFB_UI_Update: Unknown response, p1=',iData.cParam[1],', p2=',iData.cParam[2], ', p3=',iData.cParam[3],', p4=',iData.cParam[4],' p5=',iData.cParam[5],' :DEBUG <',ITOA(__LINE__),'>'") ; } } } DEFINE_FUNCTION fnFB_Update_OneBtn(INTEGER iTP_Btn, INTEGER iState) { [dvTP1_Vantage,iTP_Btn] = iState ; } DEFINE_FUNCTION fnFB_Update_AllBtns() { STACK_VAR INTEGER p ; STACK_VAR INTEGER l ; STACK_VAR INTEGER k ; STACK_VAR INTEGER b ; for(p = 1 ; p <= NUM_PROCESSORS ; p++) { for(l = 1 ; l <= NUM_LINKS_PER_PROC ; l++) { for(k = 1 ; k <= NUM_KEYPADS_PER_LINK ; k++) { for(b = 1 ; b <= NUM_BTNS_PER_KEYPAD ; b++) { [dvTP1_Vantage,sVantage[p].sLink[l].sKP[k].nTP_Btn[b]] = sVantage[p].sLink[l].sKP[k].nBtn_State[b] ; } } } } } DEFINE_FUNCTION fnInit_Structure() { STACK_VAR INTEGER p ; STACK_VAR INTEGER l ; STACK_VAR INTEGER k ; STACK_VAR INTEGER b ; for(p = 1 ; p <= NUM_PROCESSORS ; p++) { for(l = 1 ; l <= NUM_LINKS_PER_PROC ; l++) { for(k = 1 ; k <= NUM_KEYPADS_PER_LINK ; k++) { for(b = 1 ; b <= NUM_BTNS_PER_KEYPAD ; b++) { sVantage[p].sLink[l].sKP[k].cBtn_Name[b] = "'P-',itoa(p),', L-',itoa(l),', K-',itoa(k),', B-',itoa(b)" ; sVantage[p].sLink[l].sKP[k].nTP_Btn[b] = b ; sVantage[p].sLink[l].sKP[k].nBtn_State[b] = b + 10 ; } } } } } DEFINE_FUNCTION fnLoad_Names_Chnls()//modified for testing { STACK_VAR INTEGER p ; STACK_VAR INTEGER l ; STACK_VAR INTEGER k ; STACK_VAR INTEGER b ; STACK_VAR INTEGER nLengthArry ; //since I didn't create the entire array of constant values for name nLengthArry = length_array(LINK_1_TP_CHNLS) ; fnDevMod_DeBug("'DEFINE_START: Lenght Array LLINK_1_TP_CHNLS =',itoa(nLengthArry),' :DEBUG <',ITOA(__LINE__),'>'") ; //for(p = 1 ; p <= NUM_PROCESSORS ; p++) //{ //for(l = 1 ; l <= NUM_LINKS_PER_PROC ; l++) //{ for(k = 1 ; k <= nLengthArry ; k++) { for(b = 1 ; b <= NUM_BTNS_PER_KEYPAD ; b++) { sVantage[1].sLink[1].sKP[k].cBtn_Name[b] = LINK_1_BTN_NAMES[k][b] ; sVantage[1].sLink[1].sKP[k].nTP_Btn[b] = LINK_1_TP_CHNLS[k][b] ; } } // } // } //} DEFINE_START WAIT 300 { fnInit_Structure() ; fnLoad_Names_Chnls() ; } DEFINE_EVENT //DATA_EVENT[dvVantage] DATA_EVENT[dvVantage] { STRING: { LOCAL_VAR CHAR cRX_Buffer[LEN_BUFFER] ; cRX_Buffer = "cRX_Buffer,DATA.TEXT" ; WHILE(find_string(cRX_Buffer,"STR_LF",1))//this assume the device send one response at a time and each response terminates w/ $0A (LF) { fnParse_RXBuffer(REMOVE_STRING(cRX_Buffer,"STR_LF",1)) ; } } } DEFINE_PROGRAM if(nUpDateAll_Test) { fnFB_Update_AllBtns() ; nUpDateAll_Test = 0 ; } if(nInit_Structure_Test) { fnInit_Structure() ; nInit_Structure_Test = 0 ; } if(nLoad_Names_Chnls_Test) { fnLoad_Names_Chnls() ; nLoad_Names_Chnls_Test = 0 ; }Like I said I got a little carried away and needed a change from what I was doing. Hope this gives you some ideas!
PS some of the initalization values assigned were just to see something other than zero. The Init intialization would normally be 0 but I can't see if it works so I fudged it for testing.
I've never seen a nested for loop 4 levels deep before, except maybe in chess software. Its something to behold.
Paul
DEFINE_FUNCTION fnFB_Update_AllBtns() { STACK_VAR INTEGER p ; STACK_VAR INTEGER l ; STACK_VAR INTEGER k ; STACK_VAR INTEGER b ; for(p = 1 ; p <= NUM_PROCESSORS ; p++) { for(l = 1 ; l <= NUM_LINKS_PER_PROC ; l++) { for(k = 1 ; k <= NUM_KEYPADS_PER_LINK ; k++) { for(b = 1 ; b <= NUM_BTNS_PER_KEYPAD ; b++) { [dvTP1_Vantage,sVantage[p].sLink[l].sKP[k].nTP_Btn[b]] = sVantage[p].sLink[l].sKP[k].nBtn_State[b] ; } } } } }I'm open to sugesstions for alternatives.
BTW, I'm totally in favor of all forum member sharing their code since it can only improve AMX by improving their dealers so let us see how in your mind it should be done. Then maybe someone else will post a different idea and we'll all benefit.
FYI, it's my company so my time is "my time" and I don't pay myself for writing code. I only get paid when there's a profit after the job is complete.
NUM_PROCESSORS = 5
NUM_LINKS_PER_PROC = 20
NUM_KEYPADS_PER_LINK = 256
NUM_BTNS_PER_KEYPAD = 16
then it runs 409,600 times. It'll get slow fast. I generally do lazy panel updating, meaning I never update the panel unless I absolutely have to, ie: feedback has changed, and the user is looking at it right now. In the case of a panel coming online, I'll only update whatever's on the page they will see once online. One of the rare occasions when my natural laziness has side benefits.
Paul
Ok, so I've been working with AMX directly on this, and one of the tech guys was kind enough to send me an AXS file to do what I'm wanting to do. The only caveat is that you set it up so that the button #'s on the TP, match your VID (Button address) on vantage. The control of the vantage system is working just fine. The feedback, however, is not. I verified with my guy that it needs to match the channel code of the button. Any thoughts, looking into this code, as to what may be causing that?