dvViziaRF is an AMX port with something connected to it. When you send_command you are sending instructions or commands to the AMX port but when you send_string you are sending instructions or commands through the AMX port to the device connected to it.
SEND_COMMANDS are normally for sending instruction to an AMX device that controls the AMX device. SEND_STRING is normally used to send instruction (protocol) through an AMX device to a 3rd party device (normally used with COM PORTS). You can use SEND_STRING when sending messages to the master because you want the string to go through the master to terminal or telnet session. When it comes to virtual devices, SEND_COMMAND and SEND_STRING send instruction to handlers of the DATA_EVENT. STRING and COMMAND recieve this data in DATA.TEXT.
In Modules, SEND_COMMAND to the virtual device controls the code in the module that would in turn send a string to the controlled 3rd party device. The module would SEND_STRINGs back through the virtualDEVICE for feedback intreperted by the code in the module.
Thanks for the help on that. Ok so I can turn the light On but not off because of the feedback and did not have time to troubleshoot because the home owner had to leave. So I did some work on it at home. This is what I am receiving on the feedback from the lites
Line 8 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<N004L255$0D$0A]
I need the 004 and the 255 from that string, the 004 is the node and 255 means it is on. So here is what I came up with this is only for the individual lites.
STRING:
{
STACK_VAR CHAR cTemp[40] // Max 40 characters in the received data from Vizia RS232 module
cTemp = (DATA.TEXT)
send_string 0, "cTemp"
SELECT
{
ACTIVE (FIND_STRING(cTemp,'<N',1)): //Looks to see if it is a Node Level Status
{
cNode = REMOVE_STRING (cTemp,'0A<N',1) //Makes cNode xxxLyyy,etc
SEND_STRING 0,"'Node',cNode"
nNode = ATOI(cNode)
cStatus = MID_STRING(cNode, 4,4) //Makes Level Lyyy and cNode xxx
SEND_STRING 0,"'Level',cStatus"
IF (cStatus == 'L255') //255 means lite is On
{
nLiteStatus[nNode] = 1 //set LiteStatus to 1 for TP feedback
SEND_STRING 0,"'cStatus On: ', nLiteStatus[nNode]"
}
ELSE
{
nLiteStatus[nNode] = 0 //set LiteStatus to 0 for TP feedback
SEND_STRING 0,"'cStatus Off: ', nLiteStatus[nNode]"
}
}
I appreciate everyones help and patience, and have a Happy Thanksgiving.
I was just reviewing the code above and that is not going to work. So this is what I receive
Line 5 (18:18:02):: String From [5001:1:1]-[<E000$0D$0A]
Line 6 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<E000$0D$0A<N004L255$0D$0A]
Line 7 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<E000$0D$0A]
Line 8 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<N004L255$0D$0A]
I need the X000 for RF info, the Nxxx for the node number and the Lxxx for the light status. I was wondering if there is a string to array function in NS2. I have not found one so far. In a previous language I have used (not a control system) I could do a split string using a delimiter and go through the array looking for what I wanted. Sort of like this.
This is how I would do it in AutoIT
$stringArray = splitstring(data.text, "$0D$0A") ;creates an array from a string using the delimiter
For $i = 1 to $stringArray[0] ; For loop starting in array position 1, position 0 is an index
If StringInString($stringArray[$i],"<N") Then ;checks array element for <N
$node = stringmid($stringArray[$i], 2,3) ;just like MID_STRING
$level = stringright($stringArray[$i], 3) ;just like RIGHT_STRING
ElseIf StringInString($stringArray[$i], "<X") Then ;and so on through the if statements
$rf = stringmid($stringArray[$i], 2, 3)
ElseIf StringInString($stringArray[$i], "<E") Then
$error = stringmid($stringArray[$i], 2, 3)
EndIf
Next ;next element
Well it appears all your response end with $0D,$0A but in your string event handler you never test for a complete response before parsing.
your code:
STRING:
{
STACK_VAR CHAR cTemp[17] // Max 17 characters in the received data from Vizia RS232 module
cTemp = itoa(DATA.TEXT)
send_string 0, "cTemp"
SELECT
{
ACTIVE (FIND_STRING(cTemp,'<N',1)): //Looks to see if it is a Node Level Status
{
REMOVE_STRING (cTemp,'<',1) //Makes the message NxxxLyyy
SEND_STRING 0,"'Node',cTemp"
cNode = MID_STRING(cTemp,2,3)
nNode = ATOI(cNode)
cStatus = MID_STRING(cTemp,6,3)
nStatus = ATOI(cStatus)
IF (cStatus == '000')
{
nLiteStatus[nNode] = 0
}
ELSE IF (cStatus == '255')
{
nLiteStatus[nNode] = 1
}
}
ACTIVE (FIND_STRING(cTemp, '<G',1)): //Looks to see if it is a Group Level Status
{
REMOVE_STRING (cTemp,'<',1) //cTemp is now GxxxLyyy
SEND_STRING 0,"'Group',cTemp"
}
ACTIVE (FIND_STRING(cTemp, '<X',1)): //Looks to see if it is a RF Transmission Status
{
REMOVE_STRING (cTemp,'<',1) //cTemp is now Xxxx
SEND_STRING 0, "'RF Trans', cTemp"
cReady = '0' //ViziaRF is ready to receive a command
IF (cTemp == 'X002')
{
AddtoViziaRFQue(cLastcCmd)
}
}
ACTIVE (FIND_STRING(cTemp, '<E',1)): //Looks to see if it is an Error Message
{
REMOVE_STRING (cTemp,'<',1) //cTemp is now Exxx
SEND_STRING 0, "'Error', cTemp"
ON[cReady]
}
ACTIVE (FIND_STRING(cTemp, '<F',1)): //Found new node message
{
REMOVE_STRING (cTemp,'<',1) //cTemp is now Fxxx
SEND_STRING 0, "'Found Node', cTemp"
}
ACTIVE (FIND_STRING(cTemp, '$00',1)):
{
ON[cReady]
}
}
}
}
Try something like this:
DEFINE_CONSTANT
CRLF[2] = {$0D,$0A}
DATA_EVENT
STRING:
{
STACK_VAR CHAR cTemp[255] ; // Max 17 characters in the received data from Vizia RS232 module
cTemp = "cTemp,DATA.TEXT" ;
send_string 0, "cTemp" ;
WHILE(FIND_STRING(cTemp,"CRLF",1))
{
STACK_VAR CHAR cParseStr[255] ;
cParseStr = REMOVE_STRING(cTemp,"CRLF",1) ;
SELECT
{
ACTIVE(FIND_STRING(cParseStr,'<N',1)):
{
//remove N stuff
//then
//remove L stuff
}
ACTIVE(FIND_STRING(cParseStr,'<X',1)):
{
//remove X stuff
}
ACTIVE(FIND_STRING(cParseStr,'<E',1)):
{
//remove X stuff
}
ACTIVE(1):
{
//could clear cParseStr but it's a stack and will clear itself
}
In a previous language I have used (not a control system) I could do a split string using a delimiter and go through the array looking for what I wanted.
You may want to check out Tech Note 662, it's a SPLIT_STRING function which can save you the time from writing your own.
I don't think this is a standard library function. You probably need to copy the function out of TN662 and paste it into your program to use SPLIT_STRING. I searched through Netlinx.axi and did not see the function.
Vining, I am looking at doing it by your approach and just let me know if I am correct at what I think the code does.
It will continue looking at the data.text until it sees the CRLF, once it sees it is passes through the ACTIVE statements. So I should see them individually as <E000$0D$0A then another on as <X000$0D$0A going into the Select Actives. Instead of <E000$0D$0A<X000$0D$0A.
I think that I am gonna use that STRING_SPLIT function from the tech note. I am wary about the ACTIVE statements not going to see all the strings that I need. So what I am thinking about doing is split it by the $0D$0A and then run it through a TO or FOR loop, that way each response is its own element.
Here is what I coded for the SPLIT_STRING function
Function
DEFINE_FUNCTION SPLIT_STRING (CHAR strINPUT[], CHAR strDELIMITER[], CHAR arOUTPUT[][])
{
STACK_VAR
CHAR strTEMP[1000], strTRASH[100]
INTEGER nLOOP, lenDELIMITER
strTEMP = strINPUT //use a temporary string to keep integrity of original string
nLOOP = 1 //variable used to track how many sub-strings there are and how many elements should be used
lenDELIMITER = LENGTH_STRING(strDELIMITER) //length of delimiter
WHILE(LENGTH_STRING(strTEMP)) //keep looking until the end of the string
{
IF(FIND_STRING(strTEMP,strDELIMITER,1)) //look for the delimiter, if it is in the string proceed
{
arOUTPUT[nLOOP]=REMOVE_STRING(strTEMP,strDELIMITER,1) //assign sub-strings to array element
IF(RIGHT_STRING(arOUTPUT[nLOOP],lenDELIMITER)=strDELIMITER)
{
SET_LENGTH_STRING(arOUTPUT[nLOOP],LENGTH_STRING(arOUTPUT[nLOOP])-lenDELIMITER) //remove delimiter from array element
}
}
ELSE //no more delimiters
{
arOUTPUT[nLOOP]=strTEMP //assign remaining portion of string to array element
SET_LENGTH_STRING(strTEMP,0) //clear temporary string to kill loop
}
SET_LENGTH_ARRAY(arOUTPUT,nLOOP) //set length of array
nLOOP++ //increment
}
}
I went out on-site today and had to correct the code a little bit but so far it is working pretty good. Just every now and then it lags a little sending a commands and then blasts off a bunch in a row. For instance I press Garage On and about 3-5 seconds later press Driveway On, it will take about 8-10 seconds before sending anything, and the system is not waiting for a response back to trigger nReady, it would just fire off after a while. I could not get the que to send commands correctly with this:
The nReady should be renamed to nBusy. Then the statement !nReady would make more sense. It would now read if !nBusy. So if NOT BUSY (!nbusy) and there is length in the command buffer then parse it. When and where do you turn off the nReady (nBusy)?
So if you don't get either of those strings the command buffer does not parse. Correct? I would clear the busy state on any string coming back and drop the busy state after .5 seconds. The device should provide a response well before then.
I was watching it as it happened and the nReady was always getting cleared, but I can clear it after so long I think I would be more comfortable with 1 second the device is a little sluggish on the responses. I think I am actually seeing a connectivity problem more than an issue with the code. I was there today and I was having some issues on the wireless with my laptop.
Comments
dvViziaRF is an AMX port with something connected to it. When you send_command you are sending instructions or commands to the AMX port but when you send_string you are sending instructions or commands through the AMX port to the device connected to it.
Does that help clarify this?
In Modules, SEND_COMMAND to the virtual device controls the code in the module that would in turn send a string to the controlled 3rd party device. The module would SEND_STRINGs back through the virtualDEVICE for feedback intreperted by the code in the module.
Line 8 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<N004L255$0D$0A]
I need the 004 and the 255 from that string, the 004 is the node and 255 means it is on. So here is what I came up with this is only for the individual lites.
I appreciate everyones help and patience, and have a Happy Thanksgiving.
Line 5 (18:18:02):: String From [5001:1:1]-[<E000$0D$0A]
Line 6 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<E000$0D$0A<N004L255$0D$0A]
Line 7 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<E000$0D$0A]
Line 8 (18:18:02):: String From [5001:1:1]-[<X000$0D$0A<N004L255$0D$0A]
I need the X000 for RF info, the Nxxx for the node number and the Lxxx for the light status. I was wondering if there is a string to array function in NS2. I have not found one so far. In a previous language I have used (not a control system) I could do a split string using a delimiter and go through the array looking for what I wanted. Sort of like this.
This is how I would do it in AutoIT
your code:
Try something like this:
It will continue looking at the data.text until it sees the CRLF, once it sees it is passes through the ACTIVE statements. So I should see them individually as <E000$0D$0A then another on as <X000$0D$0A going into the Select Actives. Instead of <E000$0D$0A<X000$0D$0A.
Your're actually looking at cTemp for "$0D.$0A" not data.text.
Function
So this is how it looks right now