sending commands problem
I have problem with sending commands to a device. Sometimes when I am doing a send command to the device the command doesn’t sent properly. Because it gets some commands together and not one command each time.
I am trying to do a function that gets called every time I am sending a command to the device and gets put into a queue before sending it so that proper wait time is place in between commands. But I don’t know how to do that.
Anyone knows how to do that? Or maybe have an easier way?
I am trying to do a function that gets called every time I am sending a command to the device and gets put into a queue before sending it so that proper wait time is place in between commands. But I don’t know how to do that.
Anyone knows how to do that? Or maybe have an easier way?
Comments
Button Event:
SELECT { ACTIVE(nBTN == TV_BTN_PLAY): {fnTV_Q_Cmd(TV_CMD_ARRY[TV_CMD_IR],sTVmod.nCurSet,'b0')} ACTIVE(nBTN == TV_BTN_STOP): {fnTV_Q_Cmd(TV_CMD_ARRY[TV_CMD_IR],sTVmod.nCurSet,'b1')} ACTIVE(nBTN == TV_BTN_PAUSE): {fnTV_Q_Cmd(TV_CMD_ARRY[TV_CMD_IR],sTVmod.nCurSet,'ba')}Q Function:DEFINE_FUNCTION fnTV_Q_Cmd(CHAR iCmd[],INTEGER iSet,CHAR iData[2]) { STACK_VAR INTEGER nFBS ; sTVmod.sQ[sTVmod.nQHead].cCmd = iCmd ; sTVmod.sQ[sTVmod.nQHead].nSet = iSet ; sTVmod.sQ[sTVmod.nQHead].cData = iData ; SELECT { ACTIVE(sTVmod.nQHead == TV_QSIZE): {// If head is at end if(sTVmod.nQTail <> 1) {// Don't overwrite if full sTVmod.nQHead = 1 ; } } ACTIVE(sTVmod.nQTail <> sTVmod.nQHead + 1): {// Don't overwrite if full sTVmod.nQHead++ ; } } sTVmod.nQHasItem = 1 ; if(sTVmod.nConState == IP_CLIENT_DISCO && sTVmod.nIP_Port) { fnTV_Client_Open() ; } if(!TIMELINE_ACTIVE(TL_PROCESS)) { TIMELINE_CREATE(TL_PROCESS,nTL_QRT,1,TIMELINE_ABSOLUTE,TIMELINE_REPEAT) ; CANCEL_WAIT 'TL_KILLED_QUERY' ; sTVmod.nTLActive = 1 ; } RETURN ; }Process Q to send strings:DEFINE_FUNCTION fnTV_Process_Q() { if(sTVmod.nQTail <> sTVmod.nQHead) { fnTV_DeBug("sTVmod.sQ[sTVmod.nQTail].cCmd,' 0',itoa(sTVmod.sQ[sTVmod.nQTail].nSet),' ',sTVmod.sQ[sTVmod.nQTail].cData,',CR :DEBUG<',ITOA(__LINE__),'>'") ; SEND_STRING dvTV, "sTVmod.sQ[sTVmod.nQTail].cCmd,' 0',itoa(sTVmod.sQ[sTVmod.nQTail].nSet),' ',sTVmod.sQ[sTVmod.nQTail].cData,13" ; sTVmod.nCTS = TV_TX_BUSY ; WAIT TV_CTS_TIMEOUT 'TV_CTS_TIMEOUT' { sTVmod.nCTS = TV_TX_CTS ; } sTVmod.nCmdSent = sTVmod.nQTail ; if(sTVmod.nQTail < TV_QSIZE) { sTVmod.nQTail++ ; } else { sTVmod.nQTail = 1 ; } } if(sTVmod.nQTail == sTVmod.nQHead) { sTVmod.nQHasItem = 0 ;//timeline is killed in timeline } }TIME_LINE (could be DEFINE_PROGRAM):DEFINE_EVENT //TIMELINE_EVENT [TL_PROCESS] TIMELINE_EVENT [TL_PROCESS]//200ms repeating { LOCAL_VAR INTEGER nTicToc ; nTicToc++ ; if(sTVmod.nConState >= IP_CLIENT_CONNECTED) { if(sTVmod.nQHasItem && sTVmod.nCTS == TV_TX_CTS) { fnTV_Process_Q() ; } } continued....Note sTVmod.nCTS is reset upon RX from devices and the wait gets canceled. You'll have to adpt this to your code and change the necassary vars but once you get this you'll be golden. Also note that "IP_CLIENT_CONNECTED" doesn't necassarily mean it's an IP device. In this case it just means the dev is ONLINE. In this module the dev could be IP, 232 or IR.Hi vininig,
I didn’t I understood your variables.
What data types sTVmod including and what each variable means. Can you explain more about the variables you have in the code?
I have an iLight device and the commands I sent is: SEND_STRING dvILIGHT, "'@SC001:A001:L100:F004',13" ( for example). So I need to put the string : @SC001:A001:L100:F004' into the queuing.
How I do it? How can I change your code? which vars I need to change???
Regrds,
udi
DEFINE_TYPE //TV FB VALUES STRUCTURE _sFB { CHAR cValue[20] ; INTEGER nValue ; INTEGER nMainValue ; } DEFINE_TYPE //TV CMD QUEUE STRUCTURE _sQ { CHAR cCmd[2] ; INTEGER nSet ; CHAR cData[5] ; } DEFINE_TYPE //TV RX Data STRUCTURE _sRX { CHAR cCmd[2] ; INTEGER nSet ; CHAR cResult[2] ; CHAR cData[5] ; } DEFINE_TYPE //TV STATUS STRUCTURE _sTVmod { INTEGER nConState ; INTEGER nReCon ; CHAR cIP[15] ; //IP or serial LONG nIP_Port ; INTEGER nInstance ; INTEGER nSerial ; INTEGER nCTS ; INTEGER nCurSet ; INTEGER nQHead ; INTEGER nQTail ; INTEGER nLstTail ; INTEGER nQHasItem ; INTEGER nTLActive ;//just for testing & tracting _sQ sQ[TV_QSIZE] ; _sFB sFB[TV_NUM_FB_LVLs] ; } DEFINE_VARIABLE //STRUCTURE VARIABLE VOLATILE _sTVmod sTVmod ;You could make them plain vars based on the type declared in the above DEINE_TYPES or just leave as is and remove the vars in the structure that you don't need.I have to run so I can't elaborate any more right now. Maybe later when I get back online.
Hi vining
I begin to understand your code.
But I still need a little help.
1. there are some parameters I did not understand and what their value are :
nTL_QRT, TV_TX_CTS, TV_TX_BUSY , TV_CTS_TIMEOUT , nTicToc
sTVmod.nCTS,
sTVmod.nConState
2. the parameter sTVmod.nCmdSent isn't declared in the code .
3. where do you use: CANCEL_WAIT 'TL_KILLED_QUERY' ;
4. Do I need to initialize sTVmod.nQTail and sTVmod.nQHead to 1
5. In my code I need to send 2 types of coomands.
SEND_STRING dvILIGHT, "'@SC004:A001:L100:F004',13"
SEND_STRING dvILIGHT, "'@RC04:A01',13"
So I only need the cCmd but what length should be variable right
How do I set the variable to be sometimes the first command length and sometimes the second command length?
I hope you could help me Thanks
DEFINE_CONSTANT //SEND STRING / CONTROL COMMANDS CHAR TL_PROCESS = 1 ; CHAR STR_CRLF[2] = {$0D,$0A} ; CHAR STR_CR[1] = {$0D} ; CHAR TCP = 1 ; CHAR TV_NUM_FB_LVLs = 8 ; CHAR TV_TX_CTS = 0 ; CHAR TV_TX_BUSY = $FF ; CHAR TV_IS_SERIAL = $FF ; CHAR TV_POWER_ON_DELAY = 150 ; //delay CHAR TV_CTS_TIMEOUT = 40 ; //delay CHAR TV_LENGTH_CMDs = 2 ; CHAR TV_LENGTH_PARAMs = 4 ; CHAR TV_QSIZE = 12 ; CHAR IP_CLIENT_DISABLED = 0 ; CHAR IP_CLIENT_DISCO = 1 ; CHAR IP_CLIENT_PENDING = 2 ; CHAR IP_CLIENT_CONNECTED = 3 ; CHAR IP_CLIENT_DEVICE_READY = 4 ; CHAR IP_CLIENT_RX_DATA = 5 ; CHAR IP_CLIENT_TX_DATA = 6 ;sTVmod.nCTS & sTVmod.nConstate are members of STRUCTURE _sTVmod. .nCTS is sent to TV_TX_BUSY when I send a string to the device. It has a time out in case a response is not recieved where it is set to TV_TX_CTS and the timeout wait is canceled and .nCTS is set to TV_TX_CTS when a response is received form the device. sTVmod.nConState is set to IP_CLIENT_CONNECTED in the devs online event handler. To disco in the offline and either disco or disabled in the onerror. If it's IR or serial RS232 device it's not that important to track and manage the connection state.
Here's the start up code that initializes my head and tail:
DEFINE_START //SET IP if PROVIDED && initial values { if(length_string(cIP)) { STACK_VAR INTEGER nFBS ; nFBS = find_string(cIP,"':'",1) ; if(nFBS) { sTVmod.cIP = LEFT_STRING(cIP,nFBS -1) ; sTVmod.nIP_Port = atoi(RIGHT_STRING(cIP,LENGTH_STRING(cIP) - nFBS)) ; sTVmod.nComType = TV_IS_SERIAL ; sTVmod.nConState = IP_CLIENT_DISCO ; fnTV_Client_Open() ; } else { fnTV_DeBug("'ERR! Bad IP string format no ":" found, should be "IP:PORT" :DEBUG<',ITOA(__LINE__),'>'") ; sTVmod.cIP = '' ; sTVmod.nIP_Port = 0 ; } } else { sTVmod.cIP = '' ; sTVmod.nIP_Port = 0 ; } sTVmod.nReCon = 0 ; sTVmod.nQHead = 1 ; sTVmod.nQTail = 1 ; sTVmod.nCurSet = 1 ; sTVmod.nCmdSent = 1 ; if(!sTVmod.nIP_Port) {//if not set by being IP device, then set to what is passed in. either serial or IR link sTVmod.nComType = nComType ; } sTVmod.nInstance = nInstance ; if(!TIMELINE_ACTIVE(TL_PROCESS))//this will initially start TL and if Q empty & pwr is off it will stop { //tests the connection at start up TIMELINE_CREATE(TL_PROCESS,nTL_QRT,1,TIMELINE_ABSOLUTE,TIMELINE_REPEAT) ; CANCEL_WAIT 'TL_KILLED_QUERY' ; sTVmod.nTLActive = 1 ; } }My online event:
DEFINE_EVENT //DATA_EVENT[dvTV] DATA_EVENT[dvTV]//IP or SERIAL COMMS { ONLINE://online set up for serial in comm module. This allows for IP. { fnTV_DeBug("fnDEV_TO_STRING(DATA.DEVICE),' ONLINE :DEBUG<',ITOA(__LINE__),'>'") ; CANCEL_WAIT'TV_RECONNECT' ; CANCEL_WAIT 'IP_ERR_DELAY_RECON' ; sTVmod.nConState = IP_CLIENT_CONNECTED ; if(sTVmod.nIP_Port)//this is an IP Device { fnTV_DeBug("'Dev:',fnDEV_TO_STRING(DATA.DEVICE),', is an IP Device. :DEBUG<',ITOA(__LINE__),'>'") ; } else { if(sTVmod.nComType == TV_IS_SERIAL)//$FF indicates this should be a serial device (232 not IR) { SEND_COMMAND dvTV,'SET BAUD 9600,N,8,1 485 DISABLE' SEND_COMMAND dvTV,'HSOFF' ; SEND_COMMAND dvTV,'RXON' ; fnTV_DeBug("'Dev:',fnDEV_TO_STRING(DATA.DEVICE),', is a Serial Device. :DEBUG<',ITOA(__LINE__),'>'") ; } else { SEND_COMMAND dvTV,"'PTOF',1000" ; //time = 0 - 255. Given in 1/10ths of a second. Default is 15 (1.5 seconds). SEND_COMMAND dvTV,"'SET MODE IR'" ; //sets IR port to IR mode SEND_COMMAND dvTV,"'CARON'" ; //Enable the IR carrier signals (default). SEND_COMMAND dvTV,"'CTON',2" ; //time = 0 - 255. Given in 1/10ths of a second. Default is 5 (0.5 seconds). SEND_COMMAND dvTV,"'CTOF',2" ; //time = 0 - 255. Given in 1/10ths of a second. Default is 5 (0.5 seconds). SEND_COMMAND dvTV,"'XCHM-0'" ; //Mode 0 Example (default): [x][x]<x><enter> fnTV_DeBug("'Dev:',fnDEV_TO_STRING(DATA.DEVICE),', is an IR Device. :DEBUG<',ITOA(__LINE__),'>'") ; if(sTVmod.nComType) //1-8 indicates which IO to link to { fnTV_DeBug("'Dev:',fnDEV_TO_STRING(DATA.DEVICE),', SET IO LINK-(',itoa(sTVmod.nComType),') :DEBUG<',ITOA(__LINE__),'>'") ; SEND_COMMAND dvTV,"'SET IO LINK ',itoa(sTVmod.nComType)" ;//1 sets IR port to link with I/O channel 1 (port 17) } } } if(sTVmod.nIP_Port || sTVmod.nComType == TV_IS_SERIAL) { nTV_OnlineQuery = 1 ; WAIT 900 'LGTV_ONLINE_QUERY' { if(nTV_OnlineQuery) { fnTV_Q_Cmd(TV_CMD_ARRY[TV_CMD_POWER],sTVmod.nCurSet,'FF') ; } } } sTVmod.nReCon = 0 ; }I used a multi part queue so I could logically seperate my commands from my parameters to simplify later comparing to responses but you could easily just create an array to hold the entire string and make it long enough to hold your longest possible string.
Instead of using an array and the head & tail pointers you could just as easily create a char array 512 bytes long (shorter or longer) and just concanenate your commands to it to create one long string type queue. When it's time to send a string just grab up to and including "13". (Uses 13 as the delimeter) The just do something like "send_string dev, remove_string(LongStringQueue,"13",1) ; which will pull the first command in the string.